some documentation
This commit is contained in:
parent
6b4b8f20a5
commit
1c76101e68
5 changed files with 55 additions and 29 deletions
|
@ -10,9 +10,8 @@ import (
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"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/oidc"
|
||||||
|
"github.com/caos/oidc/pkg/rp"
|
||||||
"github.com/caos/oidc/pkg/utils"
|
"github.com/caos/oidc/pkg/utils"
|
||||||
"github.com/caos/utils/logging"
|
"github.com/caos/utils/logging"
|
||||||
)
|
)
|
||||||
|
@ -30,7 +29,7 @@ func main() {
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
rpConfig := &client.RelayingPartyConfig{
|
rpConfig := &rp.Config{
|
||||||
ClientID: clientID,
|
ClientID: clientID,
|
||||||
ClientSecret: clientSecret,
|
ClientSecret: clientSecret,
|
||||||
Issuer: issuer,
|
Issuer: issuer,
|
||||||
|
@ -38,7 +37,7 @@ func main() {
|
||||||
Scopes: []string{"openid", "profile", "email"},
|
Scopes: []string{"openid", "profile", "email"},
|
||||||
}
|
}
|
||||||
cookieHandler := utils.NewCookieHandler(hashKey, nil, utils.WithUnsecure())
|
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")
|
logging.Log("APP-nx6PeF").OnError(err).Panic("error creating provider")
|
||||||
|
|
||||||
// state := "foobar"
|
// state := "foobar"
|
||||||
|
|
|
@ -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/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
|
replace github.com/caos/oidc/pkg/utils => /Users/livio/workspaces/go/src/github.com/caos/oidc/pkg/utils
|
||||||
|
|
||||||
require (
|
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/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/oidc/pkg/utils v0.0.0-00010101000000-000000000000
|
||||||
github.com/caos/utils/logging v0.0.0-20191104132131-b318678afbef
|
github.com/caos/utils/logging v0.0.0-20191104132131-b318678afbef
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
|
|
3
go.mod
Normal file
3
go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module github.com/caos/oidc
|
||||||
|
|
||||||
|
go 1.13
|
|
@ -20,6 +20,7 @@ const (
|
||||||
stateParam = "state"
|
stateParam = "state"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//DefaultRP impements the `DelegationTokenExchangeRP` interface extending the `RelayingParty` interface
|
||||||
type DefaultRP struct {
|
type DefaultRP struct {
|
||||||
endpoints Endpoints
|
endpoints Endpoints
|
||||||
|
|
||||||
|
@ -32,7 +33,11 @@ type DefaultRP struct {
|
||||||
verifier Verifier
|
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{
|
p := &DefaultRP{
|
||||||
config: rpConfig,
|
config: rpConfig,
|
||||||
httpClient: utils.DefaultHTTPClient,
|
httpClient: utils.DefaultHTTPClient,
|
||||||
|
@ -47,30 +52,38 @@ func NewDefaultRelayingParty(rpConfig *Config, rpOpts ...DefaultRPOpts) (Delegat
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.verifier == nil {
|
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
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//DefaultRPOpts is the type for providing dynamic options to the DefaultRP
|
||||||
type DefaultRPOpts func(p *DefaultRP)
|
type DefaultRPOpts func(p *DefaultRP)
|
||||||
|
|
||||||
|
//WithCookieHandler set a `CookieHandler` for securing the various redirects
|
||||||
func WithCookieHandler(cookieHandler *utils.CookieHandler) DefaultRPOpts {
|
func WithCookieHandler(cookieHandler *utils.CookieHandler) DefaultRPOpts {
|
||||||
return func(p *DefaultRP) {
|
return func(p *DefaultRP) {
|
||||||
p.cookieHandler = cookieHandler
|
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 {
|
func WithHTTPClient(client *http.Client) DefaultRPOpts {
|
||||||
return func(p *DefaultRP) {
|
return func(p *DefaultRP) {
|
||||||
p.httpClient = client
|
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 {
|
func (p *DefaultRP) AuthURL(state string) string {
|
||||||
return p.oauthConfig.AuthCodeURL(state)
|
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 {
|
func (p *DefaultRP) AuthURLHandler(state string) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
if err := p.trySetStateCookie(w, state); err != nil {
|
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) {
|
func (p *DefaultRP) CodeExchange(ctx context.Context, code string) (tokens *oidc.Tokens, err error) {
|
||||||
token, err := p.oauthConfig.Exchange(ctx, code)
|
token, err := p.oauthConfig.Exchange(ctx, code)
|
||||||
if err != nil {
|
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
|
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 {
|
func (p *DefaultRP) CodeExchangeHandler(callback func(http.ResponseWriter, *http.Request, *oidc.Tokens, string)) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
state, err := p.tryReadStateCookie(w, r)
|
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) Userinfo() {}
|
||||||
|
|
||||||
func (p *DefaultRP) TokenExchange(ctx context.Context, request *grants_tx.TokenExchangeRequest) (newToken *oauth2.Token, err error) {
|
//ClientCredentials is the `RelayingParty` interface implementation
|
||||||
return p.callTokenEndpoint(request)
|
//handling the oauth2 client credentials grant
|
||||||
}
|
|
||||||
|
|
||||||
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) ClientCredentials(ctx context.Context, scopes ...string) (newToken *oauth2.Token, err error) {
|
func (p *DefaultRP) ClientCredentials(ctx context.Context, scopes ...string) (newToken *oauth2.Token, err error) {
|
||||||
return p.callTokenEndpoint(grants.ClientCredentialsGrantBasic(scopes...))
|
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) {
|
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...))
|
return p.TokenExchange(ctx, DelegationTokenRequest(subjectToken, reqOpts...))
|
||||||
}
|
}
|
||||||
|
@ -178,6 +188,20 @@ func (p *DefaultRP) discover() error {
|
||||||
return nil
|
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 {
|
func (p *DefaultRP) trySetStateCookie(w http.ResponseWriter, state string) error {
|
||||||
if p.cookieHandler != nil {
|
if p.cookieHandler != nil {
|
||||||
if err := p.cookieHandler.SetQueryCookie(w, stateParam, state); err != nil {
|
if err := p.cookieHandler.SetQueryCookie(w, stateParam, state); err != nil {
|
||||||
|
|
|
@ -24,7 +24,7 @@ type DefaultVerifier struct {
|
||||||
keySet oidc.KeySet
|
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)
|
type ConfFunc func(*verifierConfig)
|
||||||
|
|
||||||
//ACRVerifier specifies the function to be used by the `DefaultVerifier` for validating the acr claim
|
//ACRVerifier specifies the function to be used by the `DefaultVerifier` for validating the acr claim
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue