profile
viewpoint

alindeman/active_model_serializers 1

ActiveModel::Serializer implementation and Rails hooks

alindeman/alindeman.heroku.com 1

Simple sinatra app to redirect to alindeman.github.com

alindeman/camper_van 1

A Campfire to IRC bridge

alindeman/activerecord-jdbc-adapter 0

ActiveRecord adapter for JDBC and JRuby.

alindeman/activerecord-sqlserver-adapter 0

SQL Server Adapter For Rails

alindeman/akka 0

Akka Project

startedglobocom/gsh

started time in 15 days

Pull request review commentpardot/deci

Implement a consent screen in v2

 func (s *Server) authorization(w http.ResponseWriter, req *http.Request) { 	ar, err := s.oidc.StartAuthorization(w, req) 	if err != nil { 		l.WithError(err).Error("error starting authorization flow")-		http.Error(w, "Internal error", http.StatusInternalServerError)

Not sure I understand this removal. Will the user just see a blank page in the case of this error now?

lstoll

comment created time in 19 days

Pull request review commentpardot/deci

Implement a consent screen in v2

 func (s *Server) Authenticate(ctx context.Context, authID string, ident oidcserv 		return "", err 	} +	if s.consentAll ||+		(s.consentOffline && strContains(sess.LoginRequest.Scopes, "offline_access")) {+		return fmt.Sprintf("/consent?authid=%s", authID), nil+	}+	return s.finishAuthenticate(ctx, authID)+}++func (s *Server) consent(w http.ResponseWriter, req *http.Request) {+	if req.Method == "POST" {
	if req.Method == http.MethodPost {
lstoll

comment created time in 19 days

Pull request review commentpardot/deci

Implement a consent screen in v2

 func (s *Server) Authenticate(ctx context.Context, authID string, ident oidcserv 		return "", err 	} +	if s.consentAll ||+		(s.consentOffline && strContains(sess.LoginRequest.Scopes, "offline_access")) {+		return fmt.Sprintf("/consent?authid=%s", authID), nil+	}+	return s.finishAuthenticate(ctx, authID)+}++func (s *Server) consent(w http.ResponseWriter, req *http.Request) {+	if req.Method == "POST" {+		s.finalizeConsent(w, req)+		return+	}+	s.renderConsent(w, req)+}++func (s *Server) renderConsent(w http.ResponseWriter, req *http.Request) {+	l := s.logger.WithField("fn", "renderConsent")+	ctx := req.Context()++	authID := req.URL.Query().Get("authid")+	if authID == "" {+		http.Error(w, "Missing auth ID", http.StatusBadRequest)+		return+	}++	sess := &storagev2beta1.Session{}+	if _, err := s.sessionMgr.storage.Get(ctx, sessKeyspace, authID, sess); err != nil {+		l.WithError(err).Error("failed to get session")+		http.Error(w, "Internal error", http.StatusInternalServerError)+		return+	}++	cl, err := s.clients.clients.GetClient(sess.LoginRequest.ClientId)+	if err != nil {+		l.WithError(err).WithField("client-id", sess.LoginRequest.ClientId).Error("couldn't find client")+		http.Error(w, "Internal error", http.StatusInternalServerError)+		return+	}++	cname := sess.LoginRequest.ClientId+	if cl.Name != "" {+		cname = cl.Name+	}++	td := &consentData{+		AuthID:     authID,+		ClientName: cname,+		Offline:    strContains(sess.LoginRequest.Scopes, "offline_access"),

Optional: Consider making "offline_access" a constant since it's used multiple times.

lstoll

comment created time in 19 days

Pull request review commentpardot/deci

Implement a consent screen in v2

 func (s *Server) Authenticate(ctx context.Context, authID string, ident oidcserv 		return "", err 	} +	if s.consentAll ||+		(s.consentOffline && strContains(sess.LoginRequest.Scopes, "offline_access")) {+		return fmt.Sprintf("/consent?authid=%s", authID), nil

I'm not 100% sure anyone could cause havoc here because authID is known to be valid by this point, but I think I would feel like this was less of a red flag if authID were passed through url.QueryEscape before being placed into a URL.

		return fmt.Sprintf("/consent?authid=%s", url.QueryEscape(authID)), nil
lstoll

comment created time in 19 days

startedahmetb/kubectl-tree

started time in 23 days

startedwiinci/stops

started time in 24 days

startediovisor/bcc

started time in a month

PR opened juliosueiras/terraform-lsp

Bump xerrors to latest

This appears to resolve the build errors with go 1.13 described in #42

+3 -0

0 comment

2 changed files

pr created time in a month

create barnchalindeman/terraform-lsp

branch : xerrors

created branch time in a month

fork alindeman/terraform-lsp

Language Server Protocol for Terraform

fork in a month

pull request commentthephw/take_home

Add support for the medicare surplus tax rate

My understanding is that the additional medicare tax is only on income above the threshold amount.

For instance, a single person making $210,000 would be taxed as: ($210,000 * 1.45%) + ($10,000 * 0.9%). Going above the threshold amount doesn't mean that all income is taxed at the higher rate.

If it's more convenient, it should be possible to model this as if it were a marginal tax bracket system, just like regular income tax. In that case it'd be 1.45% up to $200,000 (single) and 2.35% from $200,000 to infinity.

thephw

comment created time in a month

startedxyele/secretx

started time in a month

startedstevemcquaid/kubecon-2019-notes

started time in a month

Pull request review commentpardot/deci

Add pardot/oidc backed server

+package oidcserverv2++import (+	"context"+	"encoding/base64"+	"encoding/json"+	"fmt"+	"io"+	"io/ioutil"+	"net/http"+	"net/http/httptest"+	"net/url"+	"sync"+	"time"++	"github.com/golang/protobuf/proto"+	"github.com/golang/protobuf/ptypes/wrappers"+	"github.com/pardot/deci/oidcserver"+	storagev1beta1 "github.com/pardot/deci/proto/deci/storage/v1beta1"+	storagev2beta1 "github.com/pardot/deci/proto/deci/storage/v2beta1"+	"github.com/pardot/deci/storage"+	"github.com/pardot/oidc/core"+	"github.com/pardot/oidc/discovery"+	"github.com/sirupsen/logrus"+)++var _ oidcserver.Authenticator = (*Server)(nil)++// ServerOption defines optional configuration items for the OIDC server.+type ServerOption func(s *Server) error++// WithIDTokenValidity sets how long issued ID tokens are valid for+func WithIDTokenValidity(validFor time.Duration) ServerOption {+	return ServerOption(func(s *Server) error {+		s.idTokensValidFor = validFor+		return nil+	})+}++// WithAuthRequestValidity sets how long an authorization flow is considered+// valid.+func WithAuthRequestValidity(validFor time.Duration) ServerOption {+	return ServerOption(func(s *Server) error {+		s.authRequestsValidFor = validFor+		return nil+	})+}++// WithLogger sets a logger on the server, otherwise no output will be logged+func WithLogger(logger logrus.FieldLogger) ServerOption {+	return ServerOption(func(s *Server) error {+		s.logger = logger+		return nil+	})+}++// Server is a cut-down OIDC server. It is designed to be a drop-in for the+// current oidcserver as a migration step towards a pardot/oidc implementation+type Server struct {+	logger logrus.FieldLogger++	idTokensValidFor     time.Duration+	authRequestsValidFor time.Duration+	refreshValidFor      time.Duration++	oidc *core.OIDC++	connector   oidcserver.Connector+	connectorID string++	clients *clientMgr++	sessionMgr *sessionMgr++	discovery *discovery.Handler++	issuerURL *url.URL++	mux      *http.ServeMux+	muxSetup sync.Once++	now func() time.Time+}++func New(issuer string, storage storage.Storage, signer oidcserver.Signer, connectors map[string]oidcserver.Connector, clients oidcserver.ClientSource, opts ...ServerOption) (*Server, error) {+	issURL, err := url.Parse(issuer)+	if err != nil {+		return nil, fmt.Errorf("server: can't parse issuer URL")+	}++	if len(connectors) != 1 {+		return nil, fmt.Errorf("only one connector is currently supported")+	}++	smgr := &sessionMgr{storage: storage}+	cmgr := &clientMgr{clients: clients}++	md := &discovery.ProviderMetadata{+		Issuer:                issURL.String(),+		AuthorizationEndpoint: issURL.String() + "/auth",+		TokenEndpoint:         issURL.String() + "/token",+		UserinfoEndpoint:      issURL.String() + "/userinfo",+	}++	disco, err := discovery.NewHandler(md,+		discovery.WithCoreDefaults(),+		discovery.WithKeysource(signer, 5*time.Second),+	)+	if err != nil {+		return nil, err+	}++	logger := logrus.New()+	logger.Out = ioutil.Discard++	s := &Server{+		idTokensValidFor:     15 * time.Minute,+		authRequestsValidFor: 15 * time.Minute,+		refreshValidFor:      12 * time.Hour,++		issuerURL:  issURL,+		logger:     logger,+		now:        time.Now,+		clients:    cmgr,+		sessionMgr: smgr,+		discovery:  disco,+	}++	for k, v := range connectors {+		s.connectorID = k+		s.connector = v+		v.Initialize(s)+	}++	for _, o := range opts {+		if err := o(s); err != nil {+			return nil, err+		}+	}++	ccfg := &core.Config{+		AuthValidityTime: s.authRequestsValidFor,+	}++	o, err := core.New(ccfg, smgr, cmgr, signer)+	if err != nil {+		return nil, err+	}++	s.oidc = o++	return s, nil+}++func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {+	s.muxSetup.Do(func() {+		s.mux = http.NewServeMux()+		s.mux.HandleFunc("/auth", s.authorization)+		s.mux.HandleFunc("/token", s.token)+		s.mux.HandleFunc("/userinfo", s.userinfo)+		s.mux.Handle(+			"/.well-known/openid-configuration/",+			http.StripPrefix("/.well-known/openid-configuration", s.discovery),+		)+	})++	s.mux.ServeHTTP(w, req)+}++// Authenticate associates the user's identity with the given authID, then+// returns final redirect URL.+//+// This is passed to the connector and used via "Initialize"+func (s *Server) Authenticate(ctx context.Context, authID string, ident oidcserver.Identity) (returnURL string, err error) {+	l := s.logger.WithFields(logrus.Fields{+		"authID": authID,+		"userID": ident.UserID,+		"fn":     "Authenticate",+	})+	l.Info("Starting Authenticate")++	var acr string+	if ident.ACR != nil {+		acr = *ident.ACR+	}++	// Stash the data alongside our session++	sess := &storagev2beta1.Session{}+	sessVer, err := s.sessionMgr.storage.Get(ctx, sessKeyspace, authID, sess)+	if err != nil {+		return "", err+	}++	identToSess(ident, sess)++	if _, err := s.sessionMgr.storage.Put(ctx, sessKeyspace, authID, sessVer, sess); err != nil {+		l.WithError(err).Error("failed to put session")+		return "", err+	}++	auth := &core.Authorization{+		Scopes: sess.LoginRequest.Scopes,+		ACR:    acr,+		AMR:    ident.AMR,+	}++	l.Debugf("finishing authorization with scopes %v acr %s amr %s", auth.Scopes, auth.ACR, auth.AMR)

Personally I like using WithFields so things get split out into individual searchable fields in downstream log processors, but I don't feel super strongly about it. We can always add logging at a higher level for this use case.

lstoll

comment created time in a month

pull request commentpardot/oidc

core: Always initialize extra

@alindeman do you have any thoughts on this vs. http.Header style custom type with Get/Set methods that handle this better?

I don't have a strong preference. As far as I can tell, even http.Header needs to be initialized.

lstoll

comment created time in a month

starteddlenski/python-vipaccess

started time in a month

startedPortSwigger/command-injection-attacker

started time in a month

startedSemmle/SecurityExploits

started time in a month

startedoffensive-security/exploitdb

started time in 2 months

Pull request review commentpardot/oidc

core: Fix AMR to be slice

 const loginPage = `<!DOCTYPE html> 			<p>Subject: <input type="text" name="subject" value="auser" required size="15"></p> 			<p>Granted Scopes (space delimited): <input type="text" name="scopes" value="{{ .acr }}" size="15"></p> 			<p>ACR: <input type="text" name="acr" size="15"></p>-			<p>AMR: <input type="text" name="amr" value="{{ .acr }}" size="15"></p>+			<p>AMR (comma delimited): <input type="text" name="amr" value="{{ .acr }}" size="15"></p>

It looks like value="{{ .acr }}" is duplicated on this line and line 38, possibly a copy & paste error.

lstoll

comment created time in 2 months

Pull request review commentpardot/oidc

OIDC Discovery support

+package discovery++import (+	"context"+	"encoding/json"+	"fmt"+	"net/http"+	"sync"++	"gopkg.in/square/go-jose.v2"+)++const oidcwk = "/.well-known/openid-configuration"++// keep us looking like a keysource, for consistency+var _ KeySource = (*Client)(nil)

Nice

lstoll

comment created time in 2 months

Pull request review commentpardot/oidc

OIDC Discovery support

+package discovery++import (+	"context"+	"encoding/json"+	"fmt"+	"net/http"+	"sync"++	"gopkg.in/square/go-jose.v2"+)++const oidcwk = "/.well-known/openid-configuration"++// keep us looking like a keysource, for consistency+var _ KeySource = (*Client)(nil)++// Client can be used to fetch the provider metadata for a given issuer, and can+// also return the signing keys on demand.+//+// It should be created via `NewClient` to ensure it is initialized correctly.+type Client struct {+	md *ProviderMetadata++	hc *http.Client++	jwks   *jose.JSONWebKeySet+	jwksMu sync.Mutex+}++// ClientOpt is an option that can configure a client+type ClientOpt func(c *Client)++// WithHTTPClient will set a http.Client for the initial discovery, and key+// fetching. If not set, http.DefaultClient will be used.+func WithHTTPClient(hc *http.Client) func(c *Client) {+	return func(c *Client) {+		c.hc = hc+	}+}++// NewClient will initialize a Client, performing the initial discovery.+func NewClient(ctx context.Context, issuer string, opts ...ClientOpt) (*Client, error) {+	c := &Client{+		md: &ProviderMetadata{},+		hc: http.DefaultClient,+	}++	for _, o := range opts {+		o(c)+	}++	mdr, err := c.hc.Get(issuer + oidcwk)+	if err != nil {+		return nil, fmt.Errorf("error fetching %s: %v", issuer+oidcwk, err)+	}+	err = json.NewDecoder(mdr.Body).Decode(c.md)+	_ = mdr.Body.Close()+	if err != nil {+		return nil, fmt.Errorf("error decoding provider metadata response: %v", err)+	}++	return c, nil+}++// Metadata returns the ProviderMetadata that was retrieved when the client was+// instantiated+func (c *Client) Metadata() *ProviderMetadata {+	return c.md+}++// PublicKeys will fetch and return the JWKS endpoint for this metadata. each+// request will perform a new HTTP request to the endpoint.+func (c *Client) PublicKeys(ctx context.Context) (*jose.JSONWebKeySet, error) {+	if c.md.JWKSURI == "" {+		return nil, fmt.Errorf("metadata has no JWKS endpoint, cannot fetch keys")+	}++	res, err := c.hc.Get(c.md.JWKSURI)+	if err != nil {+		return nil, fmt.Errorf("failed to get keys from %s: %v", c.md.JWKSURI, err)+	}++	ks := &jose.JSONWebKeySet{}+	err = json.NewDecoder(res.Body).Decode(ks)+	_ = res.Body.Close()+	if err != nil {+		return nil, fmt.Errorf("failed decoding JWKS response: %v", err)+	}++	return ks, nil+}++// GetKey will return the key for the given kid. If the key has already+// been fetched, no network request will be made - the cached version will be+// returned. Otherwise, a call to the keys endpoint will be made.+func (c *Client) GetKey(ctx context.Context, kid string) (*jose.JSONWebKey, error) {

Having a ctx passed at GetKey time fixes a huge usability issue with using go-oidc's implementation. Nice.

lstoll

comment created time in 2 months

startedswisskyrepo/PayloadsAllTheThings

started time in 2 months

PR opened alecthomas/kingpin

Remove newline before #compdef

zsh's compinit only considers files where the absolute first line starts with #compdef or #autoload 1. Kingpin was generating completion files with a leading newline, causing this logic to skip the file.

+1 -2

0 comment

1 changed file

pr created time in 2 months

create barnchalindeman/kingpin

branch : zsh-completion-newline

created branch time in 2 months

fork alindeman/kingpin

A Go (golang) command line and flag parser

fork in 2 months

startedmweagle/Sparta

started time in 2 months

Pull request review commentpardot/oidc

Core OIDC Server

+package core++import (+	"context"+	"crypto/rand"+	"encoding/base64"+	"net/http"+	"net/http/httptest"+	"testing"+	"time"++	"github.com/golang/protobuf/ptypes"+	"golang.org/x/oauth2"+)++func TestE2E(t *testing.T) {+	const (+		clientID     = "client-id"+		clientSecret = "client-secret"+	)++	for _, tc := range []struct {+		Name string+	}{+		{+			Name: "Simple authorization",+		},+	} {+		t.Run(tc.Name, func(t *testing.T) {+			ctx := context.Background()++			callbackChan := make(chan string, 1)+			state := randomStateValue()++			cliSvr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {+				if err := req.ParseForm(); err != nil {+					t.Fatalf("failed to parse form: %v", err)+				}

Nit: Not needed

lstoll

comment created time in 2 months

Pull request review commentpardot/oidc

Core OIDC Server

+package main++import (+	"crypto/rand"+	"encoding/base64"+	"fmt"+	"html/template"+	"sync"++	"net/http"++	"golang.org/x/oauth2"+)++const (+	stateCookie = "state"+)++type server struct {+	oa2cfg   *oauth2.Config+	mux      *http.ServeMux+	muxSetup sync.Once+}++const homePage = `<!DOCTYPE html>+<html>+	<head>+		<meta charset="UTF-8">+		<title>LOG IN</title>+	</head>+	<body>+		<h1>Start auth flow</h1>+		<form action="/start" method="POST">+    		<input type="submit" value="Submit">+		</form>+	</body>+</html>`++var homeTmpl = template.Must(template.New("loginPage").Parse(homePage))++func (s *server) home(w http.ResponseWriter, req *http.Request) {+	tmplData := map[string]interface{}{}++	if err := homeTmpl.Execute(w, tmplData); err != nil {+		http.Error(w, fmt.Sprintf("failed to render template: %v", err), http.StatusInternalServerError)+		return+	}+}++// start the actual flow. this builds up the request and sends the user on+func (s *server) start(w http.ResponseWriter, req *http.Request) {+	if err := req.ParseForm(); err != nil {+		http.Error(w, fmt.Sprintf("failed to parse form: %v", err), http.StatusInternalServerError)+		return+	}++	// track a random state var to prevent CSRF+	state := mustRandStr(16)+	sc := &http.Cookie{+		Name:   stateCookie,+		Value:  state,+		MaxAge: 60,+	}+	http.SetCookie(w, sc)++	http.Redirect(w, req, s.oa2cfg.AuthCodeURL(state), http.StatusSeeOther)+}++const callbackPage = `<!DOCTYPE html>+<html>+	<head>+		<meta charset="UTF-8">+		<title>LOG IN</title>+	</head>+	<body>+		<div>access_token: {{ .access_token }}</div>+		<div>id_token: {{ .id_token }}</div>+	</body>+</html>`++var callbackTmpl = template.Must(template.New("loginPage").Parse(callbackPage))++func (s *server) callback(w http.ResponseWriter, req *http.Request) {+	if err := req.ParseForm(); err != nil {+		http.Error(w, fmt.Sprintf("failed to parse form: %v", err), http.StatusInternalServerError)+		return+	}

Nit: This is not necessary when using req.FormValue.

lstoll

comment created time in 2 months

Pull request review commentpardot/oidc

Core OIDC Server

+package main++import (+	"encoding/json"+	"fmt"+	"html/template"+	"log"+	"strings"+	"sync"+	"time"++	"net/http"++	"github.com/pardot/oidc/core"+)++const (+	sessIDCookie = "sessID"+)++type server struct {+	oidc     *core.OIDC+	mux      *http.ServeMux+	muxSetup sync.Once+	storage  *storage+}++const loginPage = `<!DOCTYPE html>+<html>+	<head>+		<meta charset="UTF-8">+		<title>LOG IN</title>+	</head>+	<body>+		<h1>Log in to IDP</h1>+		<form action="/finish" method="POST">+			<p>Subject: <input type="text" name="subject" value="auser" required size="15"></p>+			<p>Granted Scopes (space delimited): <input type="text" name="scopes" value="{{ .acr }}" size="15"></p>+			<p>ACR: <input type="text" name="acr" size="15"></p>+			<p>AMR: <input type="text" name="amr" value="{{ .acr }}" size="15"></p>+			<p>Userinfo: <textarea name="userinfo" rows="10" cols="30">{"name": "A User"}</textarea></p>+    		<input type="submit" value="Submit">+		</form>+	</body>+</html>`++var loginTmpl = template.Must(template.New("loginPage").Parse(loginPage))++func (s *server) authorization(w http.ResponseWriter, req *http.Request) {+	ar, err := s.oidc.StartAuthorization(w, req)+	if err != nil {+		http.Error(w, fmt.Sprintf("error starting authorization flow: %v", err), http.StatusInternalServerError)+		return+	}++	// set a cookie with the auth ID, so we can track it. Note - this should+	// _never_ be done in a real application. The auth ID should generally be+	// kept secret from the user, and the user should not be able to pass one+	// directly.+	aidc := &http.Cookie{+		Name:   sessIDCookie,+		Value:  ar.SessionID,+		MaxAge: 600,+	}+	http.SetCookie(w, aidc)++	var acr string+	if len(ar.ACRValues) > 0 {+		acr = ar.ACRValues[0]+	}+	tmplData := map[string]interface{}{+		"acr":    acr,+		"scopes": strings.Join(ar.Scopes, " "),+	}++	if err := loginTmpl.Execute(w, tmplData); err != nil {+		http.Error(w, fmt.Sprintf("failed to render template: %v", err), http.StatusInternalServerError)+		return+	}+}++func (s *server) finishAuthorization(w http.ResponseWriter, req *http.Request) {+	if err := req.ParseForm(); err != nil {+		http.Error(w, fmt.Sprintf("failed to parse form: %v", err), http.StatusInternalServerError)+		return+	}

Optional: Using req.FormValue (instead of req.Form) calls ParseForm automatically.

lstoll

comment created time in 2 months

Pull request review commentpardot/oidc

Core OIDC Server

+package main++import (+	"encoding/json"+	"fmt"+	"html/template"+	"log"+	"strings"+	"sync"+	"time"++	"net/http"++	"github.com/pardot/oidc/core"+)++const (+	sessIDCookie = "sessID"+)++type server struct {+	oidc     *core.OIDC+	mux      *http.ServeMux+	muxSetup sync.Once+	storage  *storage+}++const loginPage = `<!DOCTYPE html>+<html>+	<head>+		<meta charset="UTF-8">+		<title>LOG IN</title>+	</head>+	<body>+		<h1>Log in to IDP</h1>+		<form action="/finish" method="POST">+			<p>Subject: <input type="text" name="subject" value="auser" required size="15"></p>+			<p>Granted Scopes (space delimited): <input type="text" name="scopes" value="{{ .acr }}" size="15"></p>+			<p>ACR: <input type="text" name="acr" size="15"></p>+			<p>AMR: <input type="text" name="amr" value="{{ .acr }}" size="15"></p>+			<p>Userinfo: <textarea name="userinfo" rows="10" cols="30">{"name": "A User"}</textarea></p>+    		<input type="submit" value="Submit">+		</form>+	</body>+</html>`++var loginTmpl = template.Must(template.New("loginPage").Parse(loginPage))++func (s *server) authorization(w http.ResponseWriter, req *http.Request) {+	ar, err := s.oidc.StartAuthorization(w, req)+	if err != nil {+		http.Error(w, fmt.Sprintf("error starting authorization flow: %v", err), http.StatusInternalServerError)+		return+	}++	// set a cookie with the auth ID, so we can track it. Note - this should+	// _never_ be done in a real application. The auth ID should generally be+	// kept secret from the user, and the user should not be able to pass one+	// directly.+	aidc := &http.Cookie{+		Name:   sessIDCookie,+		Value:  ar.SessionID,+		MaxAge: 600,+	}+	http.SetCookie(w, aidc)++	var acr string+	if len(ar.ACRValues) > 0 {+		acr = ar.ACRValues[0]+	}+	tmplData := map[string]interface{}{+		"acr":    acr,+		"scopes": strings.Join(ar.Scopes, " "),+	}++	if err := loginTmpl.Execute(w, tmplData); err != nil {+		http.Error(w, fmt.Sprintf("failed to render template: %v", err), http.StatusInternalServerError)+		return+	}+}++func (s *server) finishAuthorization(w http.ResponseWriter, req *http.Request) {+	if err := req.ParseForm(); err != nil {+		http.Error(w, fmt.Sprintf("failed to parse form: %v", err), http.StatusInternalServerError)+		return+	}++	sessID, err := req.Cookie(sessIDCookie)+	if err != nil {+		http.Error(w, fmt.Sprintf("failed to get auth id cookie: %v", err), http.StatusInternalServerError)+		return+	}++	auth := &core.Authorization{+		Scopes: strings.Split(req.Form.Get("scopes"), " "),+		ACR:    req.Form.Get("acr"),+		AMR:    req.Form.Get("amr"),+	}++	// We have the session ID. This is stable for the session, so we can track+	// whatever we want along with it. We always get the session ID in later+	// requests, so we can always pull things out++	meta := &metadata{+		Subject:  req.Form.Get("subject"),+		Userinfo: map[string]interface{}{},+	}+	if err := json.Unmarshal([]byte(req.Form.Get("userinfo")), &meta.Userinfo); err != nil {+		http.Error(w, fmt.Sprintf("failed to unmarshal userinfo: %v", err), http.StatusInternalServerError)+		return+	}+	s.storage.sessions[sessID.Value].Meta = meta++	// finalize it. this will redirect the user to the appropriate place+	if err := s.oidc.FinishAuthorization(w, req, sessID.Value, auth); err != nil {+		log.Printf("error finishing authorization: %v", err)+	}+}++func (s *server) token(w http.ResponseWriter, req *http.Request) {+	err := s.oidc.Token(w, req, func(tr *core.TokenRequest) (*core.TokenResponse, error) {+		// This is how we could update our metadata+		meta := s.storage.sessions[tr.SessionID].Meta+		s.storage.sessions[tr.SessionID].Meta = meta++		idt := tr.PrefillIDToken("http://localhost:8085", "subject", time.Now().Add(5*time.Minute))++		return &core.TokenResponse{+			AllowRefresh: false,+			IDToken:      idt,+		}, nil

I like this interface

lstoll

comment created time in 2 months

Pull request review commentpardot/oidc

Core OIDC Server

+package main++import (+	"crypto/rand"+	"encoding/base64"+	"fmt"+	"html/template"+	"sync"++	"net/http"++	"golang.org/x/oauth2"+)++const (+	stateCookie = "state"+)++type server struct {+	oa2cfg   *oauth2.Config+	mux      *http.ServeMux+	muxSetup sync.Once+}++const homePage = `<!DOCTYPE html>+<html>+	<head>+		<meta charset="UTF-8">+		<title>LOG IN</title>+	</head>+	<body>+		<h1>Start auth flow</h1>+		<form action="/start" method="POST">+    		<input type="submit" value="Submit">+		</form>+	</body>+</html>`++var homeTmpl = template.Must(template.New("loginPage").Parse(homePage))++func (s *server) home(w http.ResponseWriter, req *http.Request) {+	tmplData := map[string]interface{}{}++	if err := homeTmpl.Execute(w, tmplData); err != nil {+		http.Error(w, fmt.Sprintf("failed to render template: %v", err), http.StatusInternalServerError)+		return+	}+}++// start the actual flow. this builds up the request and sends the user on+func (s *server) start(w http.ResponseWriter, req *http.Request) {+	if err := req.ParseForm(); err != nil {+		http.Error(w, fmt.Sprintf("failed to parse form: %v", err), http.StatusInternalServerError)+		return+	}++	// track a random state var to prevent CSRF+	state := mustRandStr(16)+	sc := &http.Cookie{+		Name:   stateCookie,+		Value:  state,+		MaxAge: 60,+	}+	http.SetCookie(w, sc)++	http.Redirect(w, req, s.oa2cfg.AuthCodeURL(state), http.StatusSeeOther)+}++const callbackPage = `<!DOCTYPE html>+<html>+	<head>+		<meta charset="UTF-8">+		<title>LOG IN</title>+	</head>+	<body>+		<div>access_token: {{ .access_token }}</div>+		<div>id_token: {{ .id_token }}</div>+	</body>+</html>`++var callbackTmpl = template.Must(template.New("loginPage").Parse(callbackPage))++func (s *server) callback(w http.ResponseWriter, req *http.Request) {+	if err := req.ParseForm(); err != nil {+		http.Error(w, fmt.Sprintf("failed to parse form: %v", err), http.StatusInternalServerError)+		return+	}++	statec, err := req.Cookie(stateCookie)+	if err != nil {+		http.Error(w, fmt.Sprintf("failed to get state cookie: %v", err), http.StatusInternalServerError)+		return+	}++	if errMsg := req.FormValue("error"); errMsg != "" {+		http.Error(w, fmt.Sprintf("error returned to callback %s: %s", errMsg, req.FormValue("error_description")), http.StatusInternalServerError)+		return+	}++	code := req.FormValue("code")+	if code == "" {+		http.Error(w, "no code in callback response", http.StatusBadRequest)+		return+	}++	gotState := req.FormValue("state")+	if gotState == "" || gotState != statec.Value {+		http.Error(w, fmt.Sprintf("returned state %q doesn't match request state %q", gotState, statec.Value), http.StatusBadRequest)+		return+	}++	oa2Tok, err := s.oa2cfg.Exchange(req.Context(), code)+	if err != nil {+		http.Error(w, fmt.Sprintf("error exchanging code %q for token: %v", code, err), http.StatusInternalServerError)+	}++	rawIDToken, ok := oa2Tok.Extra("id_token").(string)+	if !ok {+		http.Error(w, "no id_token included in response", http.StatusBadRequest)+	}++	tmplData := map[string]interface{}{+		"access_token": oa2Tok.AccessToken,+		"id_token":     rawIDToken,+	}++	if err := callbackTmpl.Execute(w, tmplData); err != nil {+		http.Error(w, fmt.Sprintf("failed to render template: %v", err), http.StatusInternalServerError)+		return+	}

This is only about the 100th time we've written this same code, heh. Looks good though.

lstoll

comment created time in 2 months

Pull request review commentpardot/oidc

Core OIDC Server

+package main++import (+	"encoding/json"+	"fmt"+	"html/template"+	"log"+	"strings"+	"sync"+	"time"++	"net/http"++	"github.com/pardot/oidc/core"+)++const (+	sessIDCookie = "sessID"+)++type server struct {+	oidc     *core.OIDC+	mux      *http.ServeMux+	muxSetup sync.Once+	storage  *storage+}++const loginPage = `<!DOCTYPE html>+<html>+	<head>+		<meta charset="UTF-8">+		<title>LOG IN</title>+	</head>+	<body>+		<h1>Log in to IDP</h1>+		<form action="/finish" method="POST">+			<p>Subject: <input type="text" name="subject" value="auser" required size="15"></p>+			<p>Granted Scopes (space delimited): <input type="text" name="scopes" value="{{ .acr }}" size="15"></p>+			<p>ACR: <input type="text" name="acr" size="15"></p>+			<p>AMR: <input type="text" name="amr" value="{{ .acr }}" size="15"></p>+			<p>Userinfo: <textarea name="userinfo" rows="10" cols="30">{"name": "A User"}</textarea></p>+    		<input type="submit" value="Submit">+		</form>+	</body>+</html>`++var loginTmpl = template.Must(template.New("loginPage").Parse(loginPage))++func (s *server) authorization(w http.ResponseWriter, req *http.Request) {+	ar, err := s.oidc.StartAuthorization(w, req)+	if err != nil {+		http.Error(w, fmt.Sprintf("error starting authorization flow: %v", err), http.StatusInternalServerError)+		return+	}++	// set a cookie with the auth ID, so we can track it. Note - this should+	// _never_ be done in a real application. The auth ID should generally be+	// kept secret from the user, and the user should not be able to pass one+	// directly.

What are the potential issues with exposing the auth ID? I think today we do thread it through via query string parameters, so it is possible to tamper with it.

lstoll

comment created time in 2 months

startediagox86/poracle

started time in 2 months

startedkubernetes/sample-cli-plugin

started time in 2 months

startedsebnow/configs

started time in 2 months

startedtomasiser/vim-code-dark

started time in 2 months

issue openedsalesforce/sloop

Join Slack link is expired

The "Join Slack" link in README.md appears to be expired.

Screen Shot 2019-11-19 at 4 38 32 PM

created time in 2 months

delete branch pardot/oidc

delete branch : oidc-middleware

delete time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha af93d2750d158e7a3974655e7f4be4b65ed6eefd

Implement a `middleware.Handler` to protect an inner handler with OIDC (#5)

view details

push time in 2 months

PR merged pardot/oidc

Implement a `middleware.Handler` to protect an inner handler with OIDC

Basically what it says on the tin.

+719 -0

0 comment

4 changed files

alindeman

pr closed time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha f696aebfadac3e0c5d0ed438b8d0a2e22bf2f728

Implement a `middleware.Handler` to protect an inner handler with OIDC

view details

push time in 2 months

startedhbolimovsky/webauthn-example

started time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha aa3aa724f8a7ad5cb9421d8da658064d4338e47d

Implement a `middleware.Handler` to protect an inner handler with OIDC

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 8d28159a157b148717a1de9f942e0ec87f36a64b

Implement a `middleware.Handler` to protect an inner handler with OIDC

view details

push time in 2 months

startedlxfontes/poconetes

started time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 45fcdc625eaa228ed8b9840dda177b92bc8e529e

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 5c1c04c7f6a8b0cbaa82170d4e1e20866b8da7f7

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha c10bf5d0c972ceee10823297584878b4c64bf6d2

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha a39baa6af2e0ea57adb0d9c68751da2b6c8682e3

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 0f5d3f01a1fdd9c7bd4e56636248397e754143b3

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha b497a205d5972cc9379b3281bdca05dbda6f38af

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 083779268515f7f828ece619ef1229917a631c6c

Fix module name (#4)

view details

Andy Lindeman

commit sha 93eca5a11096e53e7c17d407a23ad6ac0ea08c9c

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 083779268515f7f828ece619ef1229917a631c6c

Fix module name (#4)

view details

push time in 2 months

delete branch pardot/oidc

delete branch : fix-module-name

delete time in 2 months

PR merged pardot/oidc

Fix module name
+2 -2

0 comment

2 changed files

alindeman

pr closed time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 6691ee0a174e5a6bc33bc47523178b5aeaafc5db

Fix module name

view details

push time in 2 months

PR opened pardot/oidc

Fix module name
+1 -1

0 comment

1 changed file

pr created time in 2 months

create barnchpardot/oidc

branch : fix-module-name

created branch time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 42e5768fdf1993c64c0317419e5cce438e9faa98

Fix module name

view details

Andy Lindeman

commit sha d9613b7768633ce77e37ee45397b86f09b44f1d3

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha db6d204db54af37855f1376b28eb8b9fb36f4db7

WIP

view details

push time in 2 months

push eventpardot/oidc

Andy Lindeman

commit sha 78dd67b1e6e6acdb01458f23ce3d837a0edc1fc6

WIP

view details

push time in 2 months

create barnchpardot/oidc

branch : oidc-middleware

created branch time in 2 months

fork alindeman/sourcegraph

Code search and navigation tool (self-hosted)

https://sourcegraph.com

fork in 2 months

startedquay/quay

started time in 3 months

created tagalindeman/wither2

tagv0.0.11

created time in 3 months

push eventalindeman/wither2

Andy Lindeman

commit sha 599cf8663219c3277a95d9ccb1ea0dba958ff970

Fix nil pointer

view details

push time in 3 months

push eventalindeman/wither2

Andy Lindeman

commit sha 7db780201878a69e1e4d15a1bb25b622da5943cb

Reconnect to RCON as needed

view details

push time in 3 months

created tagalindeman/wither2

tagv0.0.10

created time in 3 months

startednetanel01/ctf-writeups

started time in 3 months

startedaws/aws-service-operator-k8s

started time in 3 months

startedkislyuk/keymaker

started time in 3 months

startedTylerBrock/saw

started time in 3 months

startedbufbuild/buf

started time in 3 months

fork alindeman/docker-compose-buildkite-plugin

🐳⚡️ Run build scripts, and build + push images, w/ Docker Compose

fork in 3 months

created tagalindeman/wither2

tagv0.0.9

created time in 3 months

push eventalindeman/wither2

Andy Lindeman

commit sha 2fe2813831eed4bbf2d57af6429e462308bd36cd

Remove "on slack" for a more unified experience

view details

push time in 3 months

startedoam-dev/rudr

started time in 3 months

created tagalindeman/wither2

tagv0.0.8

created time in 3 months

push eventalindeman/wither2

Andy Lindeman

commit sha 9ccac0848244a9775ab17d6a9a960ecd3c88b3e6

Additional advancement messages

view details

push time in 3 months

push eventalindeman/wither2

Andy Lindeman

commit sha 5ef597cfc9032db27997b801a31b11feb63be6f7

Add advancement messages

view details

push time in 3 months

created tagalindeman/wither2

tagv0.0.7

created time in 3 months

startedso-fancy/diff-so-fancy

started time in 4 months

created tagalindeman/wither2

tagv0.0.6

created time in 4 months

push eventalindeman/wither2

Andy Lindeman

commit sha 6795136e2ace0086d31aed92aa03feb980117a2f

Ignore users

view details

Andy Lindeman

commit sha 7a350e33c6706b4c45e0339d9cdf09fcbadf7a9b

Death messages

view details

push time in 4 months

push eventalindeman/wither2

Andy Lindeman

commit sha ffd569bbb3f145c4e9fad75d2db6e31e05c512a5

Fix Slack webhook parsing

view details

push time in 4 months

created tagalindeman/wither2

tagv0.0.5

created time in 4 months

push eventalindeman/wither2

Andy Lindeman

commit sha bcd53f4e0ba71c447d682dc77585242b91fb1cef

Adds MVP Slack->Minecraft integration

view details

push time in 4 months

created tagalindeman/wither2

tagv0.0.3

created time in 4 months

push eventalindeman/wither2

Andy Lindeman

commit sha 86deb44666caabf009abc359cbc2b3140052281f

Discard messages that seem too far into the past/future

view details

push time in 4 months

push eventalindeman/wither2

Andy Lindeman

commit sha c1ea455c19e59d0cb6f05d774dc893b6d8ebe57b

Ignore /.git

view details

push time in 4 months

created tagalindeman/wither2

tagv0.0.2

created time in 4 months

push eventalindeman/wither2

Andy Lindeman

commit sha 1d1842c5fdf18b34ba88896ed76386c2dff92a8b

Freshen CA certificates

view details

push time in 4 months

created tagalindeman/wither2

tagv0.0.1

created time in 4 months

create barnchalindeman/wither2

branch : master

created branch time in 4 months

created repositoryalindeman/wither2

created time in 4 months

push eventalindeman/mod_auth_openidc

Hans Zandbelt

commit sha ce37080c6aea30aabae8b4a9b4eea7808445cc8e

2.4.0.2 oops Signed-off-by: Hans Zandbelt <hans.zandbelt@zmartzone.eu>

view details

AIMOTO NORIHITO

commit sha fc485b0247a157711acb97adba675ca485e9fb05

Fix open redirect starting with a slash

view details

Hans Zandbelt

commit sha 6c9a42e88e1f821c309c12bf73171469b529af3a

Merge pull request #451 from oss-aimoto/fix_openredirect_starting_slash Fix open redirect starting with a slash

view details

Hans Zandbelt

commit sha e6b95de3aa3fa5de651bc09b7286d0c3d96f65fe

tag 2.4.0.3: further logout URL validation improvement Signed-off-by: Hans Zandbelt <hans.zandbelt@zmartzone.eu>

view details

Andy Lindeman

commit sha 190576496b335975a6afd44236892ea0682d2a37

Unset chunked cookies if setting a non-chunked cookie It's possible to get into a scenario where: * A previous session needed a chunked cookie * That previous session is now expired * mod_auth_openidc starts a new auth request, which is successful * The new auth request results in a token that does _not_ need a chunked cookie * mod_auth_openidc only sets the non-chunked cookie, leaving the chunked cookies (including the counter cookie) * mod_auth_openidc continues using the chunked cookie, because the counter cookie exists, resulting in an infinite auth loop until the user manually clears their cookies Additionally, to save on request size, unset the non-chunked cookie if we end up setting a chunked cookie.

view details

Andy Lindeman

commit sha 0fcc909765ea6f4ae2ea9db6a6219ba90b019456

AUTHORS and ChangeLog

view details

push time in 4 months

push eventalindeman/mod_auth_openidc

Andy Lindeman

commit sha 8f4de77b4e4d2ebf6abd6b6aa20e462fd78d419c

Unset chunked cookies if setting a non-chunked cookie It's possible to get into a scenario where: * A previous session needed a chunked cookie * That previous session is now expired * mod_auth_openidc starts a new auth request, which is successful * The new auth request results in a token that does _not_ need a chunked cookie * mod_auth_openidc only sets the non-chunked cookie, leaving the chunked cookies (including the counter cookie) * mod_auth_openidc continues using the chunked cookie, because the counter cookie exists, resulting in an infinite auth loop until the user manually clears their cookies Additionally, to save on request size, unset the non-chunked cookie if we end up setting a chunked cookie.

view details

Andy Lindeman

commit sha e7361687afda7114ad54f61ddadf3fcfc8c1d6f4

AUTHORS and ChangeLog

view details

push time in 4 months

more