From 2ebbd7a2e0a13616c06485c7d16f2d5311507a5f Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 21 Oct 2020 10:36:34 +0200 Subject: [PATCH 01/11] fix: grant_types_supported in discovery --- pkg/oidc/token_request.go | 6 +++++- pkg/op/config.go | 2 ++ pkg/op/discovery.go | 25 +++++++++++++------------ pkg/op/op.go | 18 ++++++++---------- pkg/op/tokenrequest.go | 25 +++++++++++++++++-------- 5 files changed, 45 insertions(+), 31 deletions(-) diff --git a/pkg/oidc/token_request.go b/pkg/oidc/token_request.go index e80d28a..1312b18 100644 --- a/pkg/oidc/token_request.go +++ b/pkg/oidc/token_request.go @@ -9,8 +9,12 @@ import ( const ( //GrantTypeCode defines the grant_type `authorization_code` used for the Token Request in the Authorization Code Flow GrantTypeCode GrantType = "authorization_code" - //GrantTypeBearer define the grant_type `urn:ietf:params:oauth:grant-type:jwt-bearer` used for the JWT Authorization Grant + + //GrantTypeBearer defines the grant_type `urn:ietf:params:oauth:grant-type:jwt-bearer` used for the JWT Authorization Grant GrantTypeBearer GrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer" + + //GrantTypeTokenExchange defines the grant_type `urn:ietf:params:oauth:grant-type:token-exchange` used for the OAuth Token Exchange Grant + GrantTypeTokenExchange GrantType = "urn:ietf:params:oauth:grant-type:token-exchange" ) type GrantType string diff --git a/pkg/op/config.go b/pkg/op/config.go index d64c0ee..a2b831e 100644 --- a/pkg/op/config.go +++ b/pkg/op/config.go @@ -19,6 +19,8 @@ type Configuration interface { AuthMethodPostSupported() bool CodeMethodS256Supported() bool + GrantTypeTokenExchangeSupported() bool + GrantTypeJWTAuthorizationSupported() bool } func ValidateIssuer(issuer string) error { diff --git a/pkg/op/discovery.go b/pkg/op/discovery.go index 7611090..4bc1272 100644 --- a/pkg/op/discovery.go +++ b/pkg/op/discovery.go @@ -52,22 +52,23 @@ func Scopes(c Configuration) []string { func ResponseTypes(c Configuration) []string { return []string{ - "code", - "id_token", - // "code token", - // "code id_token", - "id_token token", - // "code id_token token" - } + string(oidc.ResponseTypeCode), + string(oidc.ResponseTypeIDTokenOnly), + string(oidc.ResponseTypeIDToken), + } //TODO: ok for now, check later if dynamic needed } func GrantTypes(c Configuration) []string { - return []string{ - "client_credentials", - "authorization_code", - // "password", - "urn:ietf:params:oauth:grant-type:token-exchange", + grantTypes := []string{ + string(oidc.GrantTypeCode), } + if c.GrantTypeTokenExchangeSupported() { + grantTypes = append(grantTypes, string(oidc.GrantTypeTokenExchange)) + } + if c.GrantTypeJWTAuthorizationSupported() { + grantTypes = append(grantTypes, string(oidc.GrantTypeBearer)) + } + return grantTypes } func SupportedClaims(c Configuration) []string { diff --git a/pkg/op/op.go b/pkg/op/op.go index bba7a14..3d2fe41 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -50,7 +50,6 @@ type OpenIDProvider interface { Decoder() utils.Decoder Encoder() utils.Encoder IDTokenHintVerifier() IDTokenHintVerifier - JWTProfileVerifier() JWTProfileVerifier AccessTokenVerifier() AccessTokenVerifier Crypto() Crypto DefaultLogoutRedirectURI() string @@ -90,15 +89,6 @@ type Config struct { CryptoKey [32]byte DefaultLogoutRedirectURI string CodeMethodS256 bool - - //TODO: add to config after updating Configuration interface for DiscoveryConfig - // ScopesSupported: oidc.SupportedScopes, - // ResponseTypesSupported: responseTypes, - // GrantTypesSupported: oidc.SupportedGrantTypes, - // ClaimsSupported: oidc.SupportedClaims, - // IdTokenSigningAlgValuesSupported: []string{keys.SigningAlgorithm}, - // SubjectTypesSupported: []string{"public"}, - // TokenEndpointAuthMethodsSupported: } type endpoints struct { @@ -196,6 +186,14 @@ func (o *openidProvider) CodeMethodS256Supported() bool { return o.config.CodeMethodS256 } +func (o *openidProvider) GrantTypeTokenExchangeSupported() bool { + return false +} + +func (o *openidProvider) GrantTypeJWTAuthorizationSupported() bool { + return true +} + func (o *openidProvider) Storage() Storage { return o.storage } diff --git a/pkg/op/tokenrequest.go b/pkg/op/tokenrequest.go index cba70f3..d414221 100644 --- a/pkg/op/tokenrequest.go +++ b/pkg/op/tokenrequest.go @@ -17,6 +17,12 @@ type Exchanger interface { Signer() Signer Crypto() Crypto AuthMethodPostSupported() bool + GrantTypeTokenExchangeSupported() bool + GrantTypeJWTAuthorizationSupported() bool +} + +type JWTAuthorizationGrantExchanger interface { + Exchanger JWTProfileVerifier() JWTProfileVerifier } @@ -27,17 +33,20 @@ func tokenHandler(exchanger Exchanger) func(w http.ResponseWriter, r *http.Reque CodeExchange(w, r, exchanger) return case string(oidc.GrantTypeBearer): - JWTProfile(w, r, exchanger) - return - case "exchange": - TokenExchange(w, r, exchanger) + if ex, ok := exchanger.(JWTAuthorizationGrantExchanger); ok && exchanger.GrantTypeJWTAuthorizationSupported() { + JWTProfile(w, r, ex) + return + } + case string(oidc.GrantTypeTokenExchange): + if exchanger.GrantTypeTokenExchangeSupported() { + TokenExchange(w, r, exchanger) + return + } case "": RequestError(w, r, ErrInvalidRequest("grant_type missing")) return - default: - RequestError(w, r, ErrInvalidRequest("grant_type not supported")) - return } + RequestError(w, r, ErrInvalidRequest("grant_type not supported")) } } @@ -137,7 +146,7 @@ func AuthorizeCodeChallenge(ctx context.Context, tokenReq *oidc.AccessTokenReque return authReq, nil } -func JWTProfile(w http.ResponseWriter, r *http.Request, exchanger Exchanger) { +func JWTProfile(w http.ResponseWriter, r *http.Request, exchanger JWTAuthorizationGrantExchanger) { profileRequest, err := ParseJWTProfileRequest(r, exchanger.Decoder()) if err != nil { RequestError(w, r, err) From 84a295c2b5df6221f4dc50ba89ec2c3aeefc6499 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 21 Oct 2020 10:38:38 +0200 Subject: [PATCH 02/11] update configuration.mock.go --- pkg/op/mock/configuration.mock.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pkg/op/mock/configuration.mock.go b/pkg/op/mock/configuration.mock.go index 88e9aa7..ece747c 100644 --- a/pkg/op/mock/configuration.mock.go +++ b/pkg/op/mock/configuration.mock.go @@ -89,6 +89,34 @@ func (mr *MockConfigurationMockRecorder) EndSessionEndpoint() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EndSessionEndpoint", reflect.TypeOf((*MockConfiguration)(nil).EndSessionEndpoint)) } +// GrantTypeJWTAuthorizationSupported mocks base method +func (m *MockConfiguration) GrantTypeJWTAuthorizationSupported() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GrantTypeJWTAuthorizationSupported") + ret0, _ := ret[0].(bool) + return ret0 +} + +// GrantTypeJWTAuthorizationSupported indicates an expected call of GrantTypeJWTAuthorizationSupported +func (mr *MockConfigurationMockRecorder) GrantTypeJWTAuthorizationSupported() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GrantTypeJWTAuthorizationSupported", reflect.TypeOf((*MockConfiguration)(nil).GrantTypeJWTAuthorizationSupported)) +} + +// GrantTypeTokenExchangeSupported mocks base method +func (m *MockConfiguration) GrantTypeTokenExchangeSupported() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GrantTypeTokenExchangeSupported") + ret0, _ := ret[0].(bool) + return ret0 +} + +// GrantTypeTokenExchangeSupported indicates an expected call of GrantTypeTokenExchangeSupported +func (mr *MockConfigurationMockRecorder) GrantTypeTokenExchangeSupported() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GrantTypeTokenExchangeSupported", reflect.TypeOf((*MockConfiguration)(nil).GrantTypeTokenExchangeSupported)) +} + // Issuer mocks base method func (m *MockConfiguration) Issuer() string { m.ctrl.T.Helper() From 939e1095150206763039510532b85f2d328adcb7 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Wed, 21 Oct 2020 11:15:57 +0200 Subject: [PATCH 03/11] chore(workflow): update github actions in release workflow (#65) * chore(workflow): update github actions in release workflow * chore(workflow): add github-actions to dependabot.yml * fix dependabot.yml --- .github/dependabot.yml | 4 ++++ .github/workflows/release.yml | 6 ++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3d24fe9..79ff704 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: commit-message: prefix: chore include: scope +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 18f5c01..49016bb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Setup go - uses: actions/setup-go@v2-beta + uses: actions/setup-go@v2 with: go-version: ${{ matrix.go }} - run: go test -race -v -coverprofile=profile.cov ./pkg/... @@ -25,9 +25,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Source checkout - uses: actions/checkout@v1 - with: - fetch-depth: 1 + uses: actions/checkout@v2 - name: Semantic Release uses: cycjimmy/semantic-release-action@v2 with: From deb33653d4a6150f4dc29668101a9ce83cf0feff Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Fri, 23 Oct 2020 15:59:44 +0200 Subject: [PATCH 04/11] fix: decode basic auth header components (clientID, clientSecret) --- pkg/op/tokenrequest.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pkg/op/tokenrequest.go b/pkg/op/tokenrequest.go index d414221..c3860ff 100644 --- a/pkg/op/tokenrequest.go +++ b/pkg/op/tokenrequest.go @@ -4,6 +4,7 @@ import ( "context" "errors" "net/http" + "net/url" "github.com/caos/oidc/pkg/oidc" "github.com/caos/oidc/pkg/oidc/grants/tokenexchange" @@ -84,9 +85,14 @@ func ParseAccessTokenRequest(r *http.Request, decoder utils.Decoder) (*oidc.Acce } clientID, clientSecret, ok := r.BasicAuth() if ok { - tokenReq.ClientID = clientID - tokenReq.ClientSecret = clientSecret - + tokenReq.ClientID, err = url.QueryUnescape(clientID) + if err != nil { + return nil, ErrInvalidRequest("invalid basic auth header") + } + tokenReq.ClientSecret, err = url.QueryUnescape(clientSecret) + if err != nil { + return nil, ErrInvalidRequest("invalid basic auth header") + } } return tokenReq, nil } @@ -115,7 +121,7 @@ func AuthorizeClient(ctx context.Context, tokenReq *oidc.AccessTokenRequest, exc return authReq, client, err } if client.AuthMethod() == AuthMethodPost && !exchanger.AuthMethodPostSupported() { - return nil, nil, errors.New("basic not supported") + return nil, nil, errors.New("auth_method post not supported") } err = AuthorizeClientIDSecret(ctx, tokenReq.ClientID, tokenReq.ClientSecret, exchanger.Storage()) if err != nil { From ab9cef7605ccc71a450e8f51f1959fcb91cc70aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2020 04:06:24 +0000 Subject: [PATCH 05/11] chore(deps): bump golang.org/x/text from 0.3.3 to 0.3.4 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.3.3 to 0.3.4. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.3.3...v0.3.4) Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 4112c69..9c46198 100644 --- a/go.mod +++ b/go.mod @@ -15,9 +15,9 @@ require ( github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/sirupsen/logrus v1.7.0 github.com/stretchr/testify v1.6.1 - golang.org/x/net v0.0.0-20200904194848-62affa334b73 + golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 - golang.org/x/text v0.3.3 + golang.org/x/text v0.3.4 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect gopkg.in/square/go-jose.v2 v2.5.1 ) diff --git a/go.sum b/go.sum index b2b0f45..6eedcb0 100644 --- a/go.sum +++ b/go.sum @@ -126,8 +126,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -141,8 +139,6 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -280,6 +276,8 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= From 2370409a55fbfe17706eaa1af8b60bf535e43a31 Mon Sep 17 00:00:00 2001 From: Fabi <38692350+fgerschwiler@users.noreply.github.com> Date: Tue, 3 Nov 2020 08:07:02 +0100 Subject: [PATCH 06/11] fix: allow additional scopes (#69) * feat: allow additional scopes * fix: mocks and tests * fix: restrict additional scopes * fix: restrict additional scopes * fix: remove comments * fix: remove comments --- example/internal/mock/storage.go | 14 ++++-- pkg/op/authrequest.go | 2 +- pkg/op/client.go | 6 +-- pkg/op/mock/client.go | 2 +- pkg/op/mock/client.mock.go | 84 ++++++++++++++++---------------- pkg/op/mock/storage.mock.impl.go | 15 ++++-- pkg/op/token.go | 31 +++--------- 7 files changed, 75 insertions(+), 79 deletions(-) diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index 9671ec7..aee9802 100644 --- a/example/internal/mock/storage.go +++ b/example/internal/mock/storage.go @@ -284,10 +284,18 @@ func (c *ConfClient) AllowedScopes() []string { return nil } -func (c *ConfClient) AssertAdditionalIdTokenScopes() bool { - return false +func (c *ConfClient) RestrictAdditionalIdTokenScopes() func(scopes []string) []string { + return func(scopes []string) []string { + return scopes + } } -func (c *ConfClient) AssertAdditionalAccessTokenScopes() bool { +func (c *ConfClient) RestrictAdditionalAccessTokenScopes() func(scopes []string) []string { + return func(scopes []string) []string { + return scopes + } +} + +func (c *ConfClient) IsScopeAllowed(scope string) bool { return false } diff --git a/pkg/op/authrequest.go b/pkg/op/authrequest.go index 4d6118c..9e320f8 100644 --- a/pkg/op/authrequest.go +++ b/pkg/op/authrequest.go @@ -121,7 +121,7 @@ func ValidateAuthReqScopes(client Client, scopes []string) ([]string, error) { scope == oidc.ScopePhone || scope == oidc.ScopeAddress || scope == oidc.ScopeOfflineAccess) && - !utils.Contains(client.AllowedScopes(), scope) { + !client.IsScopeAllowed(scope) { scopes[i] = scopes[len(scopes)-1] scopes[len(scopes)-1] = "" scopes = scopes[:len(scopes)-1] diff --git a/pkg/op/client.go b/pkg/op/client.go index 790933e..ceca8b0 100644 --- a/pkg/op/client.go +++ b/pkg/op/client.go @@ -34,9 +34,9 @@ type Client interface { AccessTokenType() AccessTokenType IDTokenLifetime() time.Duration DevMode() bool - AllowedScopes() []string - AssertAdditionalIdTokenScopes() bool - AssertAdditionalAccessTokenScopes() bool + RestrictAdditionalIdTokenScopes() func(scopes []string) []string + RestrictAdditionalAccessTokenScopes() func(scopes []string) []string + IsScopeAllowed(scope string) bool } func ContainsResponseType(types []oidc.ResponseType, responseType oidc.ResponseType) bool { diff --git a/pkg/op/mock/client.go b/pkg/op/mock/client.go index 12c00cc..b7ac3e8 100644 --- a/pkg/op/mock/client.go +++ b/pkg/op/mock/client.go @@ -26,7 +26,7 @@ func NewClientExpectAny(t *testing.T, appType op.ApplicationType) op.Client { func(id string) string { return "login?id=" + id }) - m.EXPECT().AllowedScopes().AnyTimes().Return(nil) + m.EXPECT().IsScopeAllowed(gomock.Any()).AnyTimes().Return(false) return c } diff --git a/pkg/op/mock/client.mock.go b/pkg/op/mock/client.mock.go index 0780623..df80bd0 100644 --- a/pkg/op/mock/client.mock.go +++ b/pkg/op/mock/client.mock.go @@ -49,20 +49,6 @@ func (mr *MockClientMockRecorder) AccessTokenType() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccessTokenType", reflect.TypeOf((*MockClient)(nil).AccessTokenType)) } -// AllowedScopes mocks base method -func (m *MockClient) AllowedScopes() []string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AllowedScopes") - ret0, _ := ret[0].([]string) - return ret0 -} - -// AllowedScopes indicates an expected call of AllowedScopes -func (mr *MockClientMockRecorder) AllowedScopes() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AllowedScopes", reflect.TypeOf((*MockClient)(nil).AllowedScopes)) -} - // ApplicationType mocks base method func (m *MockClient) ApplicationType() op.ApplicationType { m.ctrl.T.Helper() @@ -77,34 +63,6 @@ func (mr *MockClientMockRecorder) ApplicationType() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplicationType", reflect.TypeOf((*MockClient)(nil).ApplicationType)) } -// AssertAdditionalAccessTokenScopes mocks base method -func (m *MockClient) AssertAdditionalAccessTokenScopes() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AssertAdditionalAccessTokenScopes") - ret0, _ := ret[0].(bool) - return ret0 -} - -// AssertAdditionalAccessTokenScopes indicates an expected call of AssertAdditionalAccessTokenScopes -func (mr *MockClientMockRecorder) AssertAdditionalAccessTokenScopes() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssertAdditionalAccessTokenScopes", reflect.TypeOf((*MockClient)(nil).AssertAdditionalAccessTokenScopes)) -} - -// AssertAdditionalIdTokenScopes mocks base method -func (m *MockClient) AssertAdditionalIdTokenScopes() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AssertAdditionalIdTokenScopes") - ret0, _ := ret[0].(bool) - return ret0 -} - -// AssertAdditionalIdTokenScopes indicates an expected call of AssertAdditionalIdTokenScopes -func (mr *MockClientMockRecorder) AssertAdditionalIdTokenScopes() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AssertAdditionalIdTokenScopes", reflect.TypeOf((*MockClient)(nil).AssertAdditionalIdTokenScopes)) -} - // AuthMethod mocks base method func (m *MockClient) AuthMethod() op.AuthMethod { m.ctrl.T.Helper() @@ -161,6 +119,20 @@ func (mr *MockClientMockRecorder) IDTokenLifetime() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IDTokenLifetime", reflect.TypeOf((*MockClient)(nil).IDTokenLifetime)) } +// IsScopeAllowed mocks base method +func (m *MockClient) IsScopeAllowed(arg0 string) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsScopeAllowed", arg0) + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsScopeAllowed indicates an expected call of IsScopeAllowed +func (mr *MockClientMockRecorder) IsScopeAllowed(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsScopeAllowed", reflect.TypeOf((*MockClient)(nil).IsScopeAllowed), arg0) +} + // LoginURL mocks base method func (m *MockClient) LoginURL(arg0 string) string { m.ctrl.T.Helper() @@ -216,3 +188,31 @@ func (mr *MockClientMockRecorder) ResponseTypes() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResponseTypes", reflect.TypeOf((*MockClient)(nil).ResponseTypes)) } + +// RestrictAdditionalAccessTokenScopes mocks base method +func (m *MockClient) RestrictAdditionalAccessTokenScopes() func([]string) []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RestrictAdditionalAccessTokenScopes") + ret0, _ := ret[0].(func([]string) []string) + return ret0 +} + +// RestrictAdditionalAccessTokenScopes indicates an expected call of RestrictAdditionalAccessTokenScopes +func (mr *MockClientMockRecorder) RestrictAdditionalAccessTokenScopes() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RestrictAdditionalAccessTokenScopes", reflect.TypeOf((*MockClient)(nil).RestrictAdditionalAccessTokenScopes)) +} + +// RestrictAdditionalIdTokenScopes mocks base method +func (m *MockClient) RestrictAdditionalIdTokenScopes() func([]string) []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RestrictAdditionalIdTokenScopes") + ret0, _ := ret[0].(func([]string) []string) + return ret0 +} + +// RestrictAdditionalIdTokenScopes indicates an expected call of RestrictAdditionalIdTokenScopes +func (mr *MockClientMockRecorder) RestrictAdditionalIdTokenScopes() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RestrictAdditionalIdTokenScopes", reflect.TypeOf((*MockClient)(nil).RestrictAdditionalIdTokenScopes)) +} diff --git a/pkg/op/mock/storage.mock.impl.go b/pkg/op/mock/storage.mock.impl.go index de9dee9..92d5ad7 100644 --- a/pkg/op/mock/storage.mock.impl.go +++ b/pkg/op/mock/storage.mock.impl.go @@ -171,9 +171,16 @@ func (c *ConfClient) DevMode() bool { func (c *ConfClient) AllowedScopes() []string { return nil } -func (c *ConfClient) AssertAdditionalIdTokenScopes() bool { - return false -} -func (c *ConfClient) AssertAdditionalAccessTokenScopes() bool { +func (c *ConfClient) RestrictAdditionalIdTokenScopes() func(scopes []string) []string { + return func(scopes []string) []string { + return scopes + } +} +func (c *ConfClient) RestrictAdditionalAccessTokenScopes() func(scopes []string) []string { + return func(scopes []string) []string { + return scopes + } +} +func (c *ConfClient) IsScopeAllowed(scope string) bool { return false } diff --git a/pkg/op/token.go b/pkg/op/token.go index 2d66ef5..4fd4c0a 100644 --- a/pkg/op/token.go +++ b/pkg/op/token.go @@ -31,7 +31,7 @@ func CreateTokenResponse(ctx context.Context, authReq AuthRequest, client Client return nil, err } } - idToken, err := CreateIDToken(ctx, creator.Issuer(), authReq, client.IDTokenLifetime(), accessToken, code, creator.Storage(), creator.Signer(), client.AssertAdditionalIdTokenScopes()) + idToken, err := CreateIDToken(ctx, creator.Issuer(), authReq, client.IDTokenLifetime(), accessToken, code, creator.Storage(), creator.Signer(), client.RestrictAdditionalIdTokenScopes()) if err != nil { return nil, err } @@ -84,8 +84,9 @@ func CreateBearerToken(tokenID, subject string, crypto Crypto) (string, error) { func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, exp time.Time, id string, signer Signer, client Client, storage Storage) (string, error) { claims := oidc.NewAccessTokenClaims(issuer, tokenRequest.GetSubject(), tokenRequest.GetAudience(), exp, id) - if client != nil && client.AssertAdditionalAccessTokenScopes() { - privateClaims, err := storage.GetPrivateClaimsFromScopes(ctx, tokenRequest.GetSubject(), client.GetID(), removeUserinfoScopes(tokenRequest.GetScopes())) + if client != nil { + restrictedScopes := client.RestrictAdditionalAccessTokenScopes()(tokenRequest.GetScopes()) + privateClaims, err := storage.GetPrivateClaimsFromScopes(ctx, tokenRequest.GetSubject(), client.GetID(), removeUserinfoScopes(restrictedScopes)) if err != nil { return "", err } @@ -94,11 +95,10 @@ func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, ex return utils.Sign(claims, signer.Signer()) } -func CreateIDToken(ctx context.Context, issuer string, authReq AuthRequest, validity time.Duration, accessToken, code string, storage Storage, signer Signer, additonalScopes bool) (string, error) { +func CreateIDToken(ctx context.Context, issuer string, authReq AuthRequest, validity time.Duration, accessToken, code string, storage Storage, signer Signer, restictAdditionalScopesFunc func([]string) []string) (string, error) { exp := time.Now().UTC().Add(validity) claims := oidc.NewIDTokenClaims(issuer, authReq.GetSubject(), authReq.GetAudience(), exp, authReq.GetAuthTime(), authReq.GetNonce(), authReq.GetACR(), authReq.GetAMR(), authReq.GetClientID()) - scopes := authReq.GetScopes() - + scopes := restictAdditionalScopesFunc(authReq.GetScopes()) if accessToken != "" { atHash, err := oidc.ClaimHash(accessToken, signer.SignatureAlgorithm()) if err != nil { @@ -107,9 +107,6 @@ func CreateIDToken(ctx context.Context, issuer string, authReq AuthRequest, vali claims.SetAccessTokenHash(atHash) scopes = removeUserinfoScopes(scopes) } - if !additonalScopes { - scopes = removeAdditionalScopes(scopes) - } if len(scopes) > 0 { userInfo, err := storage.GetUserinfoFromScopes(ctx, authReq.GetSubject(), authReq.GetClientID(), scopes) if err != nil { @@ -142,19 +139,3 @@ func removeUserinfoScopes(scopes []string) []string { } return scopes } - -func removeAdditionalScopes(scopes []string) []string { - for i := len(scopes) - 1; i >= 0; i-- { - if !(scopes[i] == oidc.ScopeOpenID || - scopes[i] == oidc.ScopeProfile || - scopes[i] == oidc.ScopeEmail || - scopes[i] == oidc.ScopeAddress || - scopes[i] == oidc.ScopePhone) { - - scopes[i] = scopes[len(scopes)-1] - scopes[len(scopes)-1] = "" - scopes = scopes[:len(scopes)-1] - } - } - return scopes -} From 13b14734b91deeeaeca058dd531141c99f8195d2 Mon Sep 17 00:00:00 2001 From: Fabi <38692350+fgerschwiler@users.noreply.github.com> Date: Mon, 16 Nov 2020 08:26:19 +0100 Subject: [PATCH 07/11] fix: append client id to aud (#71) * fix: append client id to aud * fix: append client id to aud * Update pkg/oidc/token.go Co-authored-by: Livio Amstutz Co-authored-by: Livio Amstutz --- pkg/oidc/token.go | 15 ++++++++++++++- pkg/op/token.go | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pkg/oidc/token.go b/pkg/oidc/token.go index 99f18c7..bd84e64 100644 --- a/pkg/oidc/token.go +++ b/pkg/oidc/token.go @@ -48,8 +48,11 @@ func EmptyAccessTokenClaims() AccessTokenClaims { return new(accessTokenClaims) } -func NewAccessTokenClaims(issuer, subject string, audience []string, expiration time.Time, id string) AccessTokenClaims { +func NewAccessTokenClaims(issuer, subject string, audience []string, expiration time.Time, id, clientID string) AccessTokenClaims { now := time.Now().UTC() + if len(audience) == 0 { + audience = append(audience, clientID) + } return &accessTokenClaims{ Issuer: issuer, Subject: subject, @@ -201,6 +204,7 @@ func EmptyIDTokenClaims() IDTokenClaims { } func NewIDTokenClaims(issuer, subject string, audience []string, expiration, authTime time.Time, nonce string, acr string, amr []string, clientID string) IDTokenClaims { + audience = AppendClientIDToAudience(clientID, audience) return &idTokenClaims{ Issuer: issuer, Audience: audience, @@ -441,3 +445,12 @@ func ClaimHash(claim string, sigAlgorithm jose.SignatureAlgorithm) (string, erro return utils.HashString(hash, claim, true), nil } + +func AppendClientIDToAudience(clientID string, audience []string) []string { + for _, aud := range audience { + if aud == clientID { + return audience + } + } + return append(audience, clientID) +} diff --git a/pkg/op/token.go b/pkg/op/token.go index 4fd4c0a..057ab5b 100644 --- a/pkg/op/token.go +++ b/pkg/op/token.go @@ -83,7 +83,7 @@ func CreateBearerToken(tokenID, subject string, crypto Crypto) (string, error) { } func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, exp time.Time, id string, signer Signer, client Client, storage Storage) (string, error) { - claims := oidc.NewAccessTokenClaims(issuer, tokenRequest.GetSubject(), tokenRequest.GetAudience(), exp, id) + claims := oidc.NewAccessTokenClaims(issuer, tokenRequest.GetSubject(), tokenRequest.GetAudience(), exp, id, client.GetID()) if client != nil { restrictedScopes := client.RestrictAdditionalAccessTokenScopes()(tokenRequest.GetScopes()) privateClaims, err := storage.GetPrivateClaimsFromScopes(ctx, tokenRequest.GetSubject(), client.GetID(), removeUserinfoScopes(restrictedScopes)) From f5d0e64ff1e1b7dbbdbe844bc8113021aaf215bc Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Tue, 24 Nov 2020 15:56:12 +0100 Subject: [PATCH 08/11] chore(example): dynamic scopes in example (#72) --- example/client/app/app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/client/app/app.go b/example/client/app/app.go index 1c9c469..ad00adb 100644 --- a/example/client/app/app.go +++ b/example/client/app/app.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "net/http" "os" + "strings" "time" "github.com/google/uuid" @@ -28,11 +29,11 @@ func main() { clientSecret := os.Getenv("CLIENT_SECRET") issuer := os.Getenv("ISSUER") port := os.Getenv("PORT") + scopes := strings.Split(os.Getenv("SCOPES"), " ") ctx := context.Background() redirectURI := fmt.Sprintf("http://localhost:%v%v", port, callbackPath) - scopes := []string{oidc.ScopeOpenID, oidc.ScopeProfile, oidc.ScopeEmail, oidc.ScopeAddress} cookieHandler := utils.NewCookieHandler(key, key, utils.WithUnsecure()) provider, err := rp.NewRelayingPartyOIDC(issuer, clientID, clientSecret, redirectURI, scopes, rp.WithPKCE(cookieHandler), From 24120554e57c31f924e40b8617cf0c1d360c2fe6 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Thu, 26 Nov 2020 15:41:53 +0100 Subject: [PATCH 09/11] feat: add clock skew and option to put userinfo (profile, email, phone, address) into id_token --- example/internal/mock/storage.go | 8 ++++++++ pkg/oidc/token.go | 10 +++++----- pkg/op/client.go | 2 ++ pkg/op/mock/client.mock.go | 28 ++++++++++++++++++++++++++++ pkg/op/mock/storage.mock.impl.go | 8 ++++++++ pkg/op/token.go | 18 ++++++++++-------- 6 files changed, 61 insertions(+), 13 deletions(-) diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index aee9802..497c1b0 100644 --- a/example/internal/mock/storage.go +++ b/example/internal/mock/storage.go @@ -299,3 +299,11 @@ func (c *ConfClient) RestrictAdditionalAccessTokenScopes() func(scopes []string) func (c *ConfClient) IsScopeAllowed(scope string) bool { return false } + +func (c *ConfClient) UserInfoInIDToken() bool { + return false +} + +func (c *ConfClient) ClockSkew() time.Duration { + return 0 +} diff --git a/pkg/oidc/token.go b/pkg/oidc/token.go index bd84e64..ff8f33e 100644 --- a/pkg/oidc/token.go +++ b/pkg/oidc/token.go @@ -48,8 +48,8 @@ func EmptyAccessTokenClaims() AccessTokenClaims { return new(accessTokenClaims) } -func NewAccessTokenClaims(issuer, subject string, audience []string, expiration time.Time, id, clientID string) AccessTokenClaims { - now := time.Now().UTC() +func NewAccessTokenClaims(issuer, subject string, audience []string, expiration time.Time, id, clientID string, skew time.Duration) AccessTokenClaims { + now := time.Now().UTC().Add(-skew) if len(audience) == 0 { audience = append(audience, clientID) } @@ -203,14 +203,14 @@ func EmptyIDTokenClaims() IDTokenClaims { return new(idTokenClaims) } -func NewIDTokenClaims(issuer, subject string, audience []string, expiration, authTime time.Time, nonce string, acr string, amr []string, clientID string) IDTokenClaims { +func NewIDTokenClaims(issuer, subject string, audience []string, expiration, authTime time.Time, nonce string, acr string, amr []string, clientID string, skew time.Duration) IDTokenClaims { audience = AppendClientIDToAudience(clientID, audience) return &idTokenClaims{ Issuer: issuer, Audience: audience, Expiration: Time(expiration), - IssuedAt: Time(time.Now().UTC()), - AuthTime: Time(authTime), + IssuedAt: Time(time.Now().UTC().Add(-skew)), + AuthTime: Time(authTime.Add(-skew)), Nonce: nonce, AuthenticationContextClassReference: acr, AuthenticationMethodsReferences: amr, diff --git a/pkg/op/client.go b/pkg/op/client.go index ceca8b0..06fbcc3 100644 --- a/pkg/op/client.go +++ b/pkg/op/client.go @@ -37,6 +37,8 @@ type Client interface { RestrictAdditionalIdTokenScopes() func(scopes []string) []string RestrictAdditionalAccessTokenScopes() func(scopes []string) []string IsScopeAllowed(scope string) bool + UserInfoInIDToken() bool + ClockSkew() time.Duration } func ContainsResponseType(types []oidc.ResponseType, responseType oidc.ResponseType) bool { diff --git a/pkg/op/mock/client.mock.go b/pkg/op/mock/client.mock.go index df80bd0..5a89c34 100644 --- a/pkg/op/mock/client.mock.go +++ b/pkg/op/mock/client.mock.go @@ -77,6 +77,20 @@ func (mr *MockClientMockRecorder) AuthMethod() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthMethod", reflect.TypeOf((*MockClient)(nil).AuthMethod)) } +// ClockSkew mocks base method +func (m *MockClient) ClockSkew() time.Duration { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ClockSkew") + ret0, _ := ret[0].(time.Duration) + return ret0 +} + +// ClockSkew indicates an expected call of ClockSkew +func (mr *MockClientMockRecorder) ClockSkew() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClockSkew", reflect.TypeOf((*MockClient)(nil).ClockSkew)) +} + // DevMode mocks base method func (m *MockClient) DevMode() bool { m.ctrl.T.Helper() @@ -216,3 +230,17 @@ func (mr *MockClientMockRecorder) RestrictAdditionalIdTokenScopes() *gomock.Call mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RestrictAdditionalIdTokenScopes", reflect.TypeOf((*MockClient)(nil).RestrictAdditionalIdTokenScopes)) } + +// UserInfoInIDToken mocks base method +func (m *MockClient) UserInfoInIDToken() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UserInfoInIDToken") + ret0, _ := ret[0].(bool) + return ret0 +} + +// UserInfoInIDToken indicates an expected call of UserInfoInIDToken +func (mr *MockClientMockRecorder) UserInfoInIDToken() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserInfoInIDToken", reflect.TypeOf((*MockClient)(nil).UserInfoInIDToken)) +} diff --git a/pkg/op/mock/storage.mock.impl.go b/pkg/op/mock/storage.mock.impl.go index 92d5ad7..3accdef 100644 --- a/pkg/op/mock/storage.mock.impl.go +++ b/pkg/op/mock/storage.mock.impl.go @@ -184,3 +184,11 @@ func (c *ConfClient) RestrictAdditionalAccessTokenScopes() func(scopes []string) func (c *ConfClient) IsScopeAllowed(scope string) bool { return false } + +func (c *ConfClient) UserInfoInIDToken() bool { + return false +} + +func (c *ConfClient) ClockSkew() time.Duration { + return 0 +} diff --git a/pkg/op/token.go b/pkg/op/token.go index 057ab5b..cc6e11b 100644 --- a/pkg/op/token.go +++ b/pkg/op/token.go @@ -31,7 +31,7 @@ func CreateTokenResponse(ctx context.Context, authReq AuthRequest, client Client return nil, err } } - idToken, err := CreateIDToken(ctx, creator.Issuer(), authReq, client.IDTokenLifetime(), accessToken, code, creator.Storage(), creator.Signer(), client.RestrictAdditionalIdTokenScopes()) + idToken, err := CreateIDToken(ctx, creator.Issuer(), authReq, client.IDTokenLifetime(), accessToken, code, creator.Storage(), creator.Signer(), client) if err != nil { return nil, err } @@ -69,7 +69,7 @@ func CreateAccessToken(ctx context.Context, tokenRequest TokenRequest, accessTok if err != nil { return "", 0, err } - validity = exp.Sub(time.Now().UTC()) + validity = exp.Add(client.ClockSkew()).Sub(time.Now().UTC()) if accessTokenType == AccessTokenTypeJWT { token, err = CreateJWT(ctx, creator.Issuer(), tokenRequest, exp, id, creator.Signer(), client, creator.Storage()) return @@ -83,7 +83,7 @@ func CreateBearerToken(tokenID, subject string, crypto Crypto) (string, error) { } func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, exp time.Time, id string, signer Signer, client Client, storage Storage) (string, error) { - claims := oidc.NewAccessTokenClaims(issuer, tokenRequest.GetSubject(), tokenRequest.GetAudience(), exp, id, client.GetID()) + claims := oidc.NewAccessTokenClaims(issuer, tokenRequest.GetSubject(), tokenRequest.GetAudience(), exp, id, client.GetID(), client.ClockSkew()) if client != nil { restrictedScopes := client.RestrictAdditionalAccessTokenScopes()(tokenRequest.GetScopes()) privateClaims, err := storage.GetPrivateClaimsFromScopes(ctx, tokenRequest.GetSubject(), client.GetID(), removeUserinfoScopes(restrictedScopes)) @@ -95,17 +95,19 @@ func CreateJWT(ctx context.Context, issuer string, tokenRequest TokenRequest, ex return utils.Sign(claims, signer.Signer()) } -func CreateIDToken(ctx context.Context, issuer string, authReq AuthRequest, validity time.Duration, accessToken, code string, storage Storage, signer Signer, restictAdditionalScopesFunc func([]string) []string) (string, error) { - exp := time.Now().UTC().Add(validity) - claims := oidc.NewIDTokenClaims(issuer, authReq.GetSubject(), authReq.GetAudience(), exp, authReq.GetAuthTime(), authReq.GetNonce(), authReq.GetACR(), authReq.GetAMR(), authReq.GetClientID()) - scopes := restictAdditionalScopesFunc(authReq.GetScopes()) +func CreateIDToken(ctx context.Context, issuer string, authReq AuthRequest, validity time.Duration, accessToken, code string, storage Storage, signer Signer, client Client) (string, error) { + exp := time.Now().UTC().Add(client.ClockSkew()).Add(validity) + claims := oidc.NewIDTokenClaims(issuer, authReq.GetSubject(), authReq.GetAudience(), exp, authReq.GetAuthTime(), authReq.GetNonce(), authReq.GetACR(), authReq.GetAMR(), authReq.GetClientID(), client.ClockSkew()) + scopes := client.RestrictAdditionalIdTokenScopes()(authReq.GetScopes()) if accessToken != "" { atHash, err := oidc.ClaimHash(accessToken, signer.SignatureAlgorithm()) if err != nil { return "", err } claims.SetAccessTokenHash(atHash) - scopes = removeUserinfoScopes(scopes) + if !client.UserInfoInIDToken() { + scopes = removeUserinfoScopes(scopes) + } } if len(scopes) > 0 { userInfo, err := storage.GetUserinfoFromScopes(ctx, authReq.GetSubject(), authReq.GetClientID(), scopes) From 36800145d67eabd72780e45b45242c5a5509d346 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Thu, 26 Nov 2020 16:12:27 +0100 Subject: [PATCH 10/11] renaming --- example/internal/mock/storage.go | 2 +- pkg/op/client.go | 2 +- pkg/op/mock/client.mock.go | 28 ++++++++++++++-------------- pkg/op/mock/storage.mock.impl.go | 2 +- pkg/op/token.go | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index 497c1b0..8c1ab38 100644 --- a/example/internal/mock/storage.go +++ b/example/internal/mock/storage.go @@ -300,7 +300,7 @@ func (c *ConfClient) IsScopeAllowed(scope string) bool { return false } -func (c *ConfClient) UserInfoInIDToken() bool { +func (c *ConfClient) IDTokenUserinfoClaimsAssertion() bool { return false } diff --git a/pkg/op/client.go b/pkg/op/client.go index 06fbcc3..6d0891c 100644 --- a/pkg/op/client.go +++ b/pkg/op/client.go @@ -37,7 +37,7 @@ type Client interface { RestrictAdditionalIdTokenScopes() func(scopes []string) []string RestrictAdditionalAccessTokenScopes() func(scopes []string) []string IsScopeAllowed(scope string) bool - UserInfoInIDToken() bool + IDTokenUserinfoClaimsAssertion() bool ClockSkew() time.Duration } diff --git a/pkg/op/mock/client.mock.go b/pkg/op/mock/client.mock.go index 5a89c34..1a15624 100644 --- a/pkg/op/mock/client.mock.go +++ b/pkg/op/mock/client.mock.go @@ -133,6 +133,20 @@ func (mr *MockClientMockRecorder) IDTokenLifetime() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IDTokenLifetime", reflect.TypeOf((*MockClient)(nil).IDTokenLifetime)) } +// IDTokenUserinfoClaimsAssertion mocks base method +func (m *MockClient) IDTokenUserinfoClaimsAssertion() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IDTokenUserinfoClaimsAssertion") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IDTokenUserinfoClaimsAssertion indicates an expected call of IDTokenUserinfoClaimsAssertion +func (mr *MockClientMockRecorder) IDTokenUserinfoClaimsAssertion() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IDTokenUserinfoClaimsAssertion", reflect.TypeOf((*MockClient)(nil).IDTokenUserinfoClaimsAssertion)) +} + // IsScopeAllowed mocks base method func (m *MockClient) IsScopeAllowed(arg0 string) bool { m.ctrl.T.Helper() @@ -230,17 +244,3 @@ func (mr *MockClientMockRecorder) RestrictAdditionalIdTokenScopes() *gomock.Call mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RestrictAdditionalIdTokenScopes", reflect.TypeOf((*MockClient)(nil).RestrictAdditionalIdTokenScopes)) } - -// UserInfoInIDToken mocks base method -func (m *MockClient) UserInfoInIDToken() bool { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UserInfoInIDToken") - ret0, _ := ret[0].(bool) - return ret0 -} - -// UserInfoInIDToken indicates an expected call of UserInfoInIDToken -func (mr *MockClientMockRecorder) UserInfoInIDToken() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UserInfoInIDToken", reflect.TypeOf((*MockClient)(nil).UserInfoInIDToken)) -} diff --git a/pkg/op/mock/storage.mock.impl.go b/pkg/op/mock/storage.mock.impl.go index 3accdef..29d0d15 100644 --- a/pkg/op/mock/storage.mock.impl.go +++ b/pkg/op/mock/storage.mock.impl.go @@ -185,7 +185,7 @@ func (c *ConfClient) IsScopeAllowed(scope string) bool { return false } -func (c *ConfClient) UserInfoInIDToken() bool { +func (c *ConfClient) IDTokenUserinfoClaimsAssertion() bool { return false } diff --git a/pkg/op/token.go b/pkg/op/token.go index cc6e11b..fe6658a 100644 --- a/pkg/op/token.go +++ b/pkg/op/token.go @@ -105,7 +105,7 @@ func CreateIDToken(ctx context.Context, issuer string, authReq AuthRequest, vali return "", err } claims.SetAccessTokenHash(atHash) - if !client.UserInfoInIDToken() { + if !client.IDTokenUserinfoClaimsAssertion() { scopes = removeUserinfoScopes(scopes) } } From 27f3bc0f4a5e34c92ab650f67757604139d1630b Mon Sep 17 00:00:00 2001 From: Fabi <38692350+fgerschwiler@users.noreply.github.com> Date: Mon, 30 Nov 2020 11:21:09 +0100 Subject: [PATCH 11/11] fix: change callbackpath (#74) * fix: append client id to aud * handle new callback path Co-authored-by: Livio Amstutz --- example/server/default/default.go | 2 +- pkg/op/op.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/server/default/default.go b/example/server/default/default.go index d5922d4..7edaf2e 100644 --- a/example/server/default/default.go +++ b/example/server/default/default.go @@ -68,5 +68,5 @@ func HandleLogin(w http.ResponseWriter, r *http.Request) { func HandleCallback(w http.ResponseWriter, r *http.Request) { r.ParseForm() client := r.FormValue("client") - http.Redirect(w, r, "/authorize/"+client, http.StatusFound) + http.Redirect(w, r, "/authorize/callback?id="+client, http.StatusFound) } diff --git a/pkg/op/op.go b/pkg/op/op.go index 3d2fe41..d16848e 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -76,7 +76,7 @@ func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router router.HandleFunc(readinessEndpoint, readyHandler(o.Probes())) router.HandleFunc(oidc.DiscoveryEndpoint, discoveryHandler(o, o.Signer())) router.Handle(o.AuthorizationEndpoint().Relative(), intercept(authorizeHandler(o))) - router.Handle(o.AuthorizationEndpoint().Relative()+"/{id}", intercept(authorizeCallbackHandler(o))) + router.NewRoute().Path(o.AuthorizationEndpoint().Relative()+"/callback").Queries("id", "{id}").Handler(intercept(authorizeCallbackHandler(o))) router.Handle(o.TokenEndpoint().Relative(), intercept(tokenHandler(o))) router.HandleFunc(o.UserinfoEndpoint().Relative(), userinfoHandler(o)) router.Handle(o.EndSessionEndpoint().Relative(), intercept(endSessionHandler(o)))