From 1c76101e68c41392ff20825e313c13aa755fd6bc Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Thu, 21 Nov 2019 07:40:42 +0100 Subject: [PATCH] some documentation --- example/client/app/app.go | 7 ++--- example/go.mod | 8 ++--- go.mod | 3 ++ pkg/rp/default_rp.go | 64 ++++++++++++++++++++++++++------------ pkg/rp/default_verifier.go | 2 +- 5 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 go.mod diff --git a/example/client/app/app.go b/example/client/app/app.go index 137d015..424b1c8 100644 --- a/example/client/app/app.go +++ b/example/client/app/app.go @@ -10,9 +10,8 @@ import ( "github.com/google/uuid" - "github.com/caos/oidc/pkg/client" - "github.com/caos/oidc/pkg/client/defaults" "github.com/caos/oidc/pkg/oidc" + "github.com/caos/oidc/pkg/rp" "github.com/caos/oidc/pkg/utils" "github.com/caos/utils/logging" ) @@ -30,7 +29,7 @@ func main() { ctx := context.Background() - rpConfig := &client.RelayingPartyConfig{ + rpConfig := &rp.Config{ ClientID: clientID, ClientSecret: clientSecret, Issuer: issuer, @@ -38,7 +37,7 @@ func main() { Scopes: []string{"openid", "profile", "email"}, } cookieHandler := utils.NewCookieHandler(hashKey, nil, utils.WithUnsecure()) - provider, err := defaults.NewDefaultRelayingParty(rpConfig, defaults.WithCookieHandler(cookieHandler)) + provider, err := rp.NewDefaultRP(rpConfig, rp.WithCookieHandler(cookieHandler)) logging.Log("APP-nx6PeF").OnError(err).Panic("error creating provider") // state := "foobar" diff --git a/example/go.mod b/example/go.mod index 8fc9e66..546742f 100644 --- a/example/go.mod +++ b/example/go.mod @@ -6,16 +6,16 @@ replace github.com/caos/oidc => /Users/livio/workspaces/go/src/github.com/caos/o replace github.com/caos/oidc/pkg/oidc => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/oidc -replace github.com/caos/oidc/pkg/server => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/server +replace github.com/caos/oidc/pkg/op => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/op -replace github.com/caos/oidc/pkg/client => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/client +replace github.com/caos/oidc/pkg/rp => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/rp replace github.com/caos/oidc/pkg/utils => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/utils require ( - github.com/caos/oidc/pkg/client v0.0.0-00010101000000-000000000000 github.com/caos/oidc/pkg/oidc v0.0.0-00010101000000-000000000000 - github.com/caos/oidc/pkg/server v0.0.0-00010101000000-000000000000 + github.com/caos/oidc/pkg/op v0.0.0-00010101000000-000000000000 // indirect + github.com/caos/oidc/pkg/rp v0.0.0-00010101000000-000000000000 github.com/caos/oidc/pkg/utils v0.0.0-00010101000000-000000000000 github.com/caos/utils/logging v0.0.0-20191104132131-b318678afbef github.com/google/uuid v1.1.1 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1c4b985 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/caos/oidc + +go 1.13 diff --git a/pkg/rp/default_rp.go b/pkg/rp/default_rp.go index 6b4d2d7..4087a97 100644 --- a/pkg/rp/default_rp.go +++ b/pkg/rp/default_rp.go @@ -20,6 +20,7 @@ const ( stateParam = "state" ) +//DefaultRP impements the `DelegationTokenExchangeRP` interface extending the `RelayingParty` interface type DefaultRP struct { endpoints Endpoints @@ -32,7 +33,11 @@ type DefaultRP struct { verifier Verifier } -func NewDefaultRelayingParty(rpConfig *Config, rpOpts ...DefaultRPOpts) (DelegationTokenExchangeRP, error) { +//NewDefaultRP creates `DefaultRP` with the given +//Config and possible configOptions +//it will run discovery on the provided issuer +//if no verifier is provided using the options the `DefaultVerifier` is set +func NewDefaultRP(rpConfig *Config, rpOpts ...DefaultRPOpts) (DelegationTokenExchangeRP, error) { p := &DefaultRP{ config: rpConfig, httpClient: utils.DefaultHTTPClient, @@ -47,30 +52,38 @@ func NewDefaultRelayingParty(rpConfig *Config, rpOpts ...DefaultRPOpts) (Delegat } if p.verifier == nil { - // p.verifier = NewVerifier(rpConfig.Issuer, rpConfig.ClientID, utils.NewRemoteKeySet(p.httpClient, p.endpoints.JKWsURL)) //TODO: keys endpoint + p.verifier = NewDefaultVerifier(rpConfig.Issuer, rpConfig.ClientID, nil) //utils.NewRemoteKeySet(p.httpClient, p.endpoints.JKWsURL)) //TODO: keys endpoint } return p, nil } +//DefaultRPOpts is the type for providing dynamic options to the DefaultRP type DefaultRPOpts func(p *DefaultRP) +//WithCookieHandler set a `CookieHandler` for securing the various redirects func WithCookieHandler(cookieHandler *utils.CookieHandler) DefaultRPOpts { return func(p *DefaultRP) { p.cookieHandler = cookieHandler } } +//WithHTTPClient provides the ability to set an http client to be used for the relaying party and verifier func WithHTTPClient(client *http.Client) DefaultRPOpts { return func(p *DefaultRP) { p.httpClient = client } } +//AuthURL is the `RelayingParty` interface implementation +//wrapping the oauth2 `AuthCodeURL` +//returning the url of the auth request func (p *DefaultRP) AuthURL(state string) string { return p.oauthConfig.AuthCodeURL(state) } +//AuthURL is the `RelayingParty` interface implementation +//extending the `AuthURL` method with a http redirect handler func (p *DefaultRP) AuthURLHandler(state string) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if err := p.trySetStateCookie(w, state); err != nil { @@ -81,6 +94,9 @@ func (p *DefaultRP) AuthURLHandler(state string) http.HandlerFunc { } } +//AuthURL is the `RelayingParty` interface implementation +//handling the oauth2 code exchange, extracting and validating the id_token +//returning it paresed together with the oauth2 tokens (access, refresh) func (p *DefaultRP) CodeExchange(ctx context.Context, code string) (tokens *oidc.Tokens, err error) { token, err := p.oauthConfig.Exchange(ctx, code) if err != nil { @@ -99,6 +115,8 @@ func (p *DefaultRP) CodeExchange(ctx context.Context, code string) (tokens *oidc return &oidc.Tokens{Token: token, IDTokenClaims: idToken}, nil } +//AuthURL is the `RelayingParty` interface implementation +//extending the `CodeExchange` method with callback function func (p *DefaultRP) CodeExchangeHandler(callback func(http.ResponseWriter, *http.Request, *oidc.Tokens, string)) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { state, err := p.tryReadStateCookie(w, r) @@ -127,28 +145,20 @@ func (p *DefaultRP) CodeExchangeHandler(callback func(http.ResponseWriter, *http func (p *DefaultRP) Userinfo() {} -func (p *DefaultRP) TokenExchange(ctx context.Context, request *grants_tx.TokenExchangeRequest) (newToken *oauth2.Token, err error) { - return p.callTokenEndpoint(request) -} - -func (p *DefaultRP) callTokenEndpoint(request interface{}) (newToken *oauth2.Token, err error) { - req, err := utils.FormRequest(p.endpoints.TokenURL, request) - if err != nil { - return nil, err - } - auth := base64.StdEncoding.EncodeToString([]byte(p.config.ClientID + ":" + p.config.ClientSecret)) - req.Header.Set("Authorization", "Basic "+auth) - token := new(oauth2.Token) - if err := utils.HttpRequest(p.httpClient, req, token); err != nil { - return nil, err - } - return token, nil -} - +//ClientCredentials is the `RelayingParty` interface implementation +//handling the oauth2 client credentials grant func (p *DefaultRP) ClientCredentials(ctx context.Context, scopes ...string) (newToken *oauth2.Token, err error) { return p.callTokenEndpoint(grants.ClientCredentialsGrantBasic(scopes...)) } +//TokenExchange is the `TokenExchangeRP` interface implementation +//handling the oauth2 token exchange (draft) +func (p *DefaultRP) TokenExchange(ctx context.Context, request *grants_tx.TokenExchangeRequest) (newToken *oauth2.Token, err error) { + return p.callTokenEndpoint(request) +} + +//DelegationTokenExchange is the `TokenExchangeRP` interface implementation +//handling the oauth2 token exchange for a delegation token (draft) func (p *DefaultRP) DelegationTokenExchange(ctx context.Context, subjectToken string, reqOpts ...grants_tx.TokenExchangeOption) (newToken *oauth2.Token, err error) { return p.TokenExchange(ctx, DelegationTokenRequest(subjectToken, reqOpts...)) } @@ -178,6 +188,20 @@ func (p *DefaultRP) discover() error { return nil } +func (p *DefaultRP) callTokenEndpoint(request interface{}) (newToken *oauth2.Token, err error) { + req, err := utils.FormRequest(p.endpoints.TokenURL, request) + if err != nil { + return nil, err + } + auth := base64.StdEncoding.EncodeToString([]byte(p.config.ClientID + ":" + p.config.ClientSecret)) + req.Header.Set("Authorization", "Basic "+auth) + token := new(oauth2.Token) + if err := utils.HttpRequest(p.httpClient, req, token); err != nil { + return nil, err + } + return token, nil +} + func (p *DefaultRP) trySetStateCookie(w http.ResponseWriter, state string) error { if p.cookieHandler != nil { if err := p.cookieHandler.SetQueryCookie(w, stateParam, state); err != nil { diff --git a/pkg/rp/default_verifier.go b/pkg/rp/default_verifier.go index 5123c1c..4d429e0 100644 --- a/pkg/rp/default_verifier.go +++ b/pkg/rp/default_verifier.go @@ -24,7 +24,7 @@ type DefaultVerifier struct { keySet oidc.KeySet } -//ConfFunc is the type for providing dynamic verifierConfig +//ConfFunc is the type for providing dynamic options to the DefaultVerfifier type ConfFunc func(*verifierConfig) //ACRVerifier specifies the function to be used by the `DefaultVerifier` for validating the acr claim