From 576db48c1132749241fc757dcbe65f9c52089e3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jul 2020 04:02:20 +0000 Subject: [PATCH 01/10] chore(deps): bump github.com/golang/mock from 1.4.3 to 1.4.4 Bumps [github.com/golang/mock](https://github.com/golang/mock) from 1.4.3 to 1.4.4. - [Release notes](https://github.com/golang/mock/releases) - [Changelog](https://github.com/golang/mock/blob/master/.goreleaser.yml) - [Commits](https://github.com/golang/mock/compare/v1.4.3...v1.4.4) Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 24a1b57..445a27e 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.13 require ( github.com/caos/logging v0.0.0-20191210002624-b3260f690a6a - github.com/golang/mock v1.4.3 + github.com/golang/mock v1.4.4 github.com/google/go-cmp v0.4.1 // indirect github.com/google/go-github/v31 v31.0.0 github.com/google/uuid v1.1.1 diff --git a/go.sum b/go.sum index 5af7d7e..16d3dac 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= From c6e22dff69d1e94e8f199fdc09e89d48a72820dc Mon Sep 17 00:00:00 2001 From: Fabi <38692350+fgerschwiler@users.noreply.github.com> Date: Thu, 6 Aug 2020 13:10:49 +0200 Subject: [PATCH 02/10] feat: dev mode on client, check client configuration (#41) * fix: tests * fix: tests * fix: tests --- example/internal/mock/storage.go | 13 +++- pkg/op/authrequest.go | 43 ++++++----- pkg/op/authrequest_test.go | 123 ++++++++++++++++++++++++------ pkg/op/client.go | 18 ++++- pkg/op/config_test.go | 2 +- pkg/op/mock/client.go | 11 +++ pkg/op/mock/client.mock.go | 41 ++++++++-- pkg/op/mock/configuration.mock.go | 14 ---- pkg/op/mock/storage.mock.impl.go | 17 ++++- pkg/op/tokenrequest.go | 4 +- 10 files changed, 215 insertions(+), 71 deletions(-) diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index 5fb823b..7e216de 100644 --- a/example/internal/mock/storage.go +++ b/example/internal/mock/storage.go @@ -195,7 +195,7 @@ func (s *AuthStorage) GetClientByClientID(_ context.Context, id string) (op.Clie authMethod = op.AuthMethodNone accessTokenType = op.AccessTokenTypeJWT } - return &ConfClient{ID: id, applicationType: appType, authMethod: authMethod, accessTokenType: accessTokenType}, nil + return &ConfClient{ID: id, applicationType: appType, authMethod: authMethod, accessTokenType: accessTokenType, devMode: false}, nil } func (s *AuthStorage) AuthorizeClientIDSecret(_ context.Context, id string, _ string) error { @@ -232,8 +232,10 @@ func (s *AuthStorage) GetUserinfoFromScopes(_ context.Context, _ string, _ []str type ConfClient struct { applicationType op.ApplicationType authMethod op.AuthMethod + responseTypes []oidc.ResponseType ID string accessTokenType op.AccessTokenType + devMode bool } func (c *ConfClient) GetID() string { @@ -262,7 +264,7 @@ func (c *ConfClient) ApplicationType() op.ApplicationType { return c.applicationType } -func (c *ConfClient) GetAuthMethod() op.AuthMethod { +func (c *ConfClient) AuthMethod() op.AuthMethod { return c.authMethod } @@ -272,3 +274,10 @@ func (c *ConfClient) IDTokenLifetime() time.Duration { func (c *ConfClient) AccessTokenType() op.AccessTokenType { return c.accessTokenType } +func (c *ConfClient) ResponseTypes() []oidc.ResponseType { + return c.responseTypes +} + +func (c *ConfClient) DevMode() bool { + return c.devMode +} diff --git a/pkg/op/authrequest.go b/pkg/op/authrequest.go index 9eb6504..41a7b44 100644 --- a/pkg/op/authrequest.go +++ b/pkg/op/authrequest.go @@ -65,13 +65,17 @@ func Authorize(w http.ResponseWriter, r *http.Request, authorizer Authorizer) { } func ValidateAuthRequest(ctx context.Context, authReq *oidc.AuthRequest, storage Storage, verifier rp.Verifier) (string, error) { + client, err := storage.GetClientByClientID(ctx, authReq.ClientID) + if err != nil { + return "", ErrServerError(err.Error()) + } if err := ValidateAuthReqScopes(authReq.Scopes); err != nil { return "", err } - if err := ValidateAuthReqRedirectURI(ctx, authReq.RedirectURI, authReq.ClientID, authReq.ResponseType, storage); err != nil { + if err := ValidateAuthReqRedirectURI(client, authReq.RedirectURI, authReq.ResponseType); err != nil { return "", err } - if err := ValidateAuthReqResponseType(authReq.ResponseType); err != nil { + if err := ValidateAuthReqResponseType(client, authReq.ResponseType); err != nil { return "", err } return ValidateAuthReqIDTokenHint(ctx, authReq.IDTokenHint, verifier) @@ -79,24 +83,24 @@ func ValidateAuthRequest(ctx context.Context, authReq *oidc.AuthRequest, storage func ValidateAuthReqScopes(scopes []string) error { if len(scopes) == 0 { - return ErrInvalidRequest("Unforuntately, the scope of your request is missing. Please ensure your scope value is not 0, and try again. If you have any questions, you may contact the administrator of the application.") + return ErrInvalidRequest("The scope of your request is missing. Please ensure some scopes are requested. If you have any questions, you may contact the administrator of the application.") } if !utils.Contains(scopes, oidc.ScopeOpenID) { - return ErrInvalidRequest("Unfortunately, the scope openid of your request is missing. Please ensure your scope openid is complete and accurate, and try again. If you have any questions, you may contact the administrator of the application.") + return ErrInvalidRequest("The scope openid is missing in your request. Please ensure the scope openid is added to the request. If you have any questions, you may contact the administrator of the application.") } return nil } -func ValidateAuthReqRedirectURI(ctx context.Context, uri, client_id string, responseType oidc.ResponseType, storage OPStorage) error { +func ValidateAuthReqRedirectURI(client Client, uri string, responseType oidc.ResponseType) error { if uri == "" { - return ErrInvalidRequestRedirectURI("Unfortunately, the client's redirect_uri is missing. Please ensure your redirect_uri is included in the request, and try again. If you have any questions, you may contact the administrator of the application.") - } - client, err := storage.GetClientByClientID(ctx, client_id) - if err != nil { - return ErrServerError(err.Error()) + return ErrInvalidRequestRedirectURI("The redirect_uri is missing in the request. Please ensure it is added to the request. If you have any questions, you may contact the administrator of the application.") } + if !utils.Contains(client.RedirectURIs(), uri) { - return ErrInvalidRequestRedirectURI("Unfortunately, the redirect_uri is missing in the client configuration. Please ensure your redirect_uri is added in the client configuration, and try again. If you have any questions, you may contact the administrator of the application.") + return ErrInvalidRequestRedirectURI("The requested redirect_uri is missing in the client configuration. If you have any questions, you may contact the administrator of the application.") + } + if client.DevMode() { + return nil } if strings.HasPrefix(uri, "https://") { return nil @@ -105,24 +109,27 @@ func ValidateAuthReqRedirectURI(ctx context.Context, uri, client_id string, resp if strings.HasPrefix(uri, "http://") && IsConfidentialType(client) { return nil } - if client.ApplicationType() == ApplicationTypeNative { + if !strings.HasPrefix(uri, "http://") && client.ApplicationType() == ApplicationTypeNative { return nil } - return ErrInvalidRequest("Unfortunately, this client's redirect_uri is http and is not allowed. If you have any questions, you may contact the administrator of the application.") + return ErrInvalidRequest("This client's redirect_uri is http and is not allowed. If you have any questions, you may contact the administrator of the application.") } else { if client.ApplicationType() != ApplicationTypeNative { - return ErrInvalidRequestRedirectURI("Unfortunately, http is only allowed for native applications. Please change your redirect uri configuration and try again. If you have any questions, you may contact the administrator of the application.") + return ErrInvalidRequestRedirectURI("Http is only allowed for native applications. Please change your redirect uri try again. If you have any questions, you may contact the administrator of the application.") } if !(strings.HasPrefix(uri, "http://localhost:") || strings.HasPrefix(uri, "http://localhost/")) { - return ErrInvalidRequestRedirectURI("Unfortunately, http is only allowed for localhost url. Please change your redirect uri configuration and try again. If you have any questions, you may contact the administrator of the application at:") + return ErrInvalidRequestRedirectURI("Http is only allowed for localhost uri. Please change your redirect uri try again. If you have any questions, you may contact the administrator of the application at:") } } return nil } -func ValidateAuthReqResponseType(responseType oidc.ResponseType) error { +func ValidateAuthReqResponseType(client Client, responseType oidc.ResponseType) error { if responseType == "" { - return ErrInvalidRequest("Unfortunately, a response type is missing in your request. Please ensure the response type is complete and accurate, and try again. If you have any questions, you may contact the administrator of the application.") + return ErrInvalidRequest("The response type is missing in your request. If you have any questions, you may contact the administrator of the application.") + } + if !ContainsResponseType(client.ResponseTypes(), responseType) { + return ErrInvalidRequest("The requested response type is missing in the client configuration. If you have any questions, you may contact the administrator of the application.") } return nil } @@ -133,7 +140,7 @@ func ValidateAuthReqIDTokenHint(ctx context.Context, idTokenHint string, verifie } claims, err := verifier.Verify(ctx, "", idTokenHint) if err != nil { - return "", ErrInvalidRequest("Unfortunately, the id_token_hint is invalid. Please ensure the id_token_hint is complete and accurate, and try again. If you have any questions, you may contact the administrator of the application.") + return "", ErrInvalidRequest("The id_token_hint is invalid. If you have any questions, you may contact the administrator of the application.") } return claims.Subject, nil } diff --git a/pkg/op/authrequest_test.go b/pkg/op/authrequest_test.go index dca72fa..1b31fad 100644 --- a/pkg/op/authrequest_test.go +++ b/pkg/op/authrequest_test.go @@ -84,27 +84,27 @@ func TestValidateAuthRequest(t *testing.T) { // } { "scope missing fails", - args{&oidc.AuthRequest{}, nil, nil}, + args{&oidc.AuthRequest{}, mock.NewMockStorageExpectValidClientID(t), nil}, true, }, { "scope openid missing fails", - args{&oidc.AuthRequest{Scopes: []string{"profile"}}, nil, nil}, + args{&oidc.AuthRequest{Scopes: []string{"profile"}}, mock.NewMockStorageExpectValidClientID(t), nil}, true, }, { "response_type missing fails", - args{&oidc.AuthRequest{Scopes: []string{"openid"}}, nil, nil}, + args{&oidc.AuthRequest{Scopes: []string{"openid"}}, mock.NewMockStorageExpectValidClientID(t), nil}, true, }, { "client_id missing fails", - args{&oidc.AuthRequest{Scopes: []string{"openid"}, ResponseType: oidc.ResponseTypeCode}, nil, nil}, + args{&oidc.AuthRequest{Scopes: []string{"openid"}, ResponseType: oidc.ResponseTypeCode}, mock.NewMockStorageExpectValidClientID(t), nil}, true, }, { "redirect_uri missing fails", - args{&oidc.AuthRequest{Scopes: []string{"openid"}, ResponseType: oidc.ResponseTypeCode, ClientID: "client_id"}, nil, nil}, + args{&oidc.AuthRequest{Scopes: []string{"openid"}, ResponseType: oidc.ResponseTypeCode, ClientID: "client_id"}, mock.NewMockStorageExpectValidClientID(t), nil}, true, }, } @@ -149,9 +149,8 @@ func TestValidateAuthReqScopes(t *testing.T) { func TestValidateAuthReqRedirectURI(t *testing.T) { type args struct { uri string - clientID string + client op.Client responseType oidc.ResponseType - storage op.OPStorage } tests := []struct { name string @@ -160,74 +159,150 @@ func TestValidateAuthReqRedirectURI(t *testing.T) { }{ { "empty fails", - args{"", "", oidc.ResponseTypeCode, nil}, + args{"", + mock.NewClientWithConfig(t, []string{"https://registered.com/callback"}, op.ApplicationTypeWeb, nil, false), + oidc.ResponseTypeCode}, true, }, { "unregistered fails", - args{"https://unregistered.com/callback", "web_client", oidc.ResponseTypeCode, mock.NewMockStorageExpectValidClientID(t)}, - true, - }, - { - "storage error fails", - args{"https://registered.com/callback", "non_client", oidc.ResponseTypeIDToken, mock.NewMockStorageExpectInvalidClientID(t)}, + args{"https://unregistered.com/callback", + mock.NewClientWithConfig(t, []string{"https://registered.com/callback"}, op.ApplicationTypeWeb, nil, false), + oidc.ResponseTypeCode}, true, }, { "code flow registered http not confidential fails", - args{"http://registered.com/callback", "useragent_client", oidc.ResponseTypeCode, mock.NewMockStorageExpectValidClientID(t)}, + args{"http://registered.com/callback", + mock.NewClientWithConfig(t, []string{"http://registered.com/callback"}, op.ApplicationTypeUserAgent, nil, false), + oidc.ResponseTypeCode}, true, }, { "code flow registered http confidential ok", - args{"http://registered.com/callback", "web_client", oidc.ResponseTypeCode, mock.NewMockStorageExpectValidClientID(t)}, + args{"http://registered.com/callback", + mock.NewClientWithConfig(t, []string{"http://registered.com/callback"}, op.ApplicationTypeWeb, nil, false), + oidc.ResponseTypeCode}, false, }, { "code flow registered custom not native fails", - args{"custom://callback", "useragent_client", oidc.ResponseTypeCode, mock.NewMockStorageExpectValidClientID(t)}, + args{"custom://callback", + mock.NewClientWithConfig(t, []string{"custom://callback"}, op.ApplicationTypeUserAgent, nil, false), + oidc.ResponseTypeCode}, true, }, { "code flow registered custom native ok", - args{"http://registered.com/callback", "native_client", oidc.ResponseTypeCode, mock.NewMockStorageExpectValidClientID(t)}, + args{"custom://callback", + mock.NewClientWithConfig(t, []string{"custom://callback"}, op.ApplicationTypeNative, nil, false), + oidc.ResponseTypeCode}, + false, + }, + { + "code flow dev mode http ok", + args{"http://registered.com/callback", + mock.NewClientWithConfig(t, []string{"http://registered.com/callback"}, op.ApplicationTypeNative, nil, true), + oidc.ResponseTypeCode}, false, }, { "implicit flow registered ok", - args{"https://registered.com/callback", "useragent_client", oidc.ResponseTypeIDToken, mock.NewMockStorageExpectValidClientID(t)}, + args{"https://registered.com/callback", + mock.NewClientWithConfig(t, []string{"https://registered.com/callback"}, op.ApplicationTypeUserAgent, nil, false), + oidc.ResponseTypeIDToken}, false, }, + { + "implicit flow unregistered fails", + args{"https://unregistered.com/callback", + mock.NewClientWithConfig(t, []string{"https://registered.com/callback"}, op.ApplicationTypeUserAgent, nil, false), + oidc.ResponseTypeIDToken}, + true, + }, { "implicit flow registered http localhost native ok", - args{"http://localhost:9999/callback", "native_client", oidc.ResponseTypeIDToken, mock.NewMockStorageExpectValidClientID(t)}, + args{"http://localhost:9999/callback", + mock.NewClientWithConfig(t, []string{"http://localhost:9999/callback"}, op.ApplicationTypeNative, nil, false), + oidc.ResponseTypeIDToken}, false, }, { "implicit flow registered http localhost user agent fails", - args{"http://localhost:9999/callback", "useragent_client", oidc.ResponseTypeIDToken, mock.NewMockStorageExpectValidClientID(t)}, + args{"http://localhost:9999/callback", + mock.NewClientWithConfig(t, []string{"http://localhost:9999/callback"}, op.ApplicationTypeUserAgent, nil, false), + oidc.ResponseTypeIDToken}, true, }, { "implicit flow http non localhost fails", - args{"http://registered.com/callback", "native_client", oidc.ResponseTypeIDToken, mock.NewMockStorageExpectValidClientID(t)}, + args{"http://registered.com/callback", + mock.NewClientWithConfig(t, []string{"http://registered.com/callback"}, op.ApplicationTypeNative, nil, false), + oidc.ResponseTypeIDToken}, true, }, { "implicit flow custom fails", - args{"custom://callback", "native_client", oidc.ResponseTypeIDToken, mock.NewMockStorageExpectValidClientID(t)}, + args{"custom://callback", + mock.NewClientWithConfig(t, []string{"custom://callback"}, op.ApplicationTypeNative, nil, false), + oidc.ResponseTypeIDToken}, true, }, + { + "implicit flow dev mode http ok", + args{"http://registered.com/callback", + mock.NewClientWithConfig(t, []string{"http://registered.com/callback"}, op.ApplicationTypeNative, nil, true), + oidc.ResponseTypeIDToken}, + false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := op.ValidateAuthReqRedirectURI(nil, tt.args.uri, tt.args.clientID, tt.args.responseType, tt.args.storage); (err != nil) != tt.wantErr { + if err := op.ValidateAuthReqRedirectURI(tt.args.client, tt.args.uri, tt.args.responseType); (err != nil) != tt.wantErr { t.Errorf("ValidateRedirectURI() error = %v, wantErr %v", err.Error(), tt.wantErr) } }) } } +func TestValidateAuthReqResponseType(t *testing.T) { + type args struct { + responseType oidc.ResponseType + client op.Client + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + "empty response type", + args{"", + mock.NewClientWithConfig(t, nil, op.ApplicationTypeNative, []oidc.ResponseType{oidc.ResponseTypeCode}, true)}, + true, + }, + { + "response type missing in client config", + args{oidc.ResponseTypeIDToken, + mock.NewClientWithConfig(t, nil, op.ApplicationTypeNative, []oidc.ResponseType{oidc.ResponseTypeCode}, true)}, + true, + }, + { + "valid response type", + args{oidc.ResponseTypeCode, + mock.NewClientWithConfig(t, nil, op.ApplicationTypeNative, []oidc.ResponseType{oidc.ResponseTypeCode}, true)}, + false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := op.ValidateAuthReqResponseType(tt.args.client, tt.args.responseType); (err != nil) != tt.wantErr { + t.Errorf("ValidateAuthReqScopes() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + func TestRedirectToLogin(t *testing.T) { type args struct { authReqID string diff --git a/pkg/op/client.go b/pkg/op/client.go index a61e31d..9e8a7dc 100644 --- a/pkg/op/client.go +++ b/pkg/op/client.go @@ -1,6 +1,9 @@ package op -import "time" +import ( + "github.com/caos/oidc/pkg/oidc" + "time" +) const ( ApplicationTypeWeb ApplicationType = iota @@ -16,16 +19,27 @@ type Client interface { RedirectURIs() []string PostLogoutRedirectURIs() []string ApplicationType() ApplicationType - GetAuthMethod() AuthMethod + AuthMethod() AuthMethod + ResponseTypes() []oidc.ResponseType LoginURL(string) string AccessTokenType() AccessTokenType IDTokenLifetime() time.Duration + DevMode() bool } func IsConfidentialType(c Client) bool { return c.ApplicationType() == ApplicationTypeWeb } +func ContainsResponseType(types []oidc.ResponseType, responseType oidc.ResponseType) bool { + for _, t := range types { + if t == responseType { + return true + } + } + return false +} + type ApplicationType int type AuthMethod string diff --git a/pkg/op/config_test.go b/pkg/op/config_test.go index 56cf2eb..348872f 100644 --- a/pkg/op/config_test.go +++ b/pkg/op/config_test.go @@ -54,7 +54,7 @@ func TestValidateIssuer(t *testing.T) { false, }, { - "localhost with http ok", + "localhost with http fails", args{"http://localhost:9999"}, true, }, diff --git a/pkg/op/mock/client.go b/pkg/op/mock/client.go index 242eb13..b0d0dca 100644 --- a/pkg/op/mock/client.go +++ b/pkg/op/mock/client.go @@ -1,6 +1,7 @@ package mock import ( + "github.com/caos/oidc/pkg/oidc" "testing" gomock "github.com/golang/mock/gomock" @@ -27,3 +28,13 @@ func NewClientExpectAny(t *testing.T, appType op.ApplicationType) op.Client { }) return c } + +func NewClientWithConfig(t *testing.T, uri []string, appType op.ApplicationType, responseTypes []oidc.ResponseType, devMode bool) op.Client { + c := NewClient(t) + m := c.(*MockClient) + m.EXPECT().RedirectURIs().AnyTimes().Return(uri) + m.EXPECT().ApplicationType().AnyTimes().Return(appType) + m.EXPECT().ResponseTypes().AnyTimes().Return(responseTypes) + m.EXPECT().DevMode().AnyTimes().Return(devMode) + return c +} diff --git a/pkg/op/mock/client.mock.go b/pkg/op/mock/client.mock.go index e2f1c11..4007347 100644 --- a/pkg/op/mock/client.mock.go +++ b/pkg/op/mock/client.mock.go @@ -5,6 +5,7 @@ package mock import ( + oidc "github.com/caos/oidc/pkg/oidc" op "github.com/caos/oidc/pkg/op" gomock "github.com/golang/mock/gomock" reflect "reflect" @@ -62,18 +63,32 @@ func (mr *MockClientMockRecorder) ApplicationType() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplicationType", reflect.TypeOf((*MockClient)(nil).ApplicationType)) } -// GetAuthMethod mocks base method -func (m *MockClient) GetAuthMethod() op.AuthMethod { +// AuthMethod mocks base method +func (m *MockClient) AuthMethod() op.AuthMethod { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAuthMethod") + ret := m.ctrl.Call(m, "AuthMethod") ret0, _ := ret[0].(op.AuthMethod) return ret0 } -// GetAuthMethod indicates an expected call of GetAuthMethod -func (mr *MockClientMockRecorder) GetAuthMethod() *gomock.Call { +// AuthMethod indicates an expected call of AuthMethod +func (mr *MockClientMockRecorder) AuthMethod() *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAuthMethod", reflect.TypeOf((*MockClient)(nil).GetAuthMethod)) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthMethod", reflect.TypeOf((*MockClient)(nil).AuthMethod)) +} + +// DevMode mocks base method +func (m *MockClient) DevMode() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DevMode") + ret0, _ := ret[0].(bool) + return ret0 +} + +// DevMode indicates an expected call of DevMode +func (mr *MockClientMockRecorder) DevMode() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DevMode", reflect.TypeOf((*MockClient)(nil).DevMode)) } // GetID mocks base method @@ -145,3 +160,17 @@ func (mr *MockClientMockRecorder) RedirectURIs() *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RedirectURIs", reflect.TypeOf((*MockClient)(nil).RedirectURIs)) } + +// ResponseTypes mocks base method +func (m *MockClient) ResponseTypes() []oidc.ResponseType { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ResponseTypes") + ret0, _ := ret[0].([]oidc.ResponseType) + return ret0 +} + +// ResponseTypes indicates an expected call of ResponseTypes +func (mr *MockClientMockRecorder) ResponseTypes() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResponseTypes", reflect.TypeOf((*MockClient)(nil).ResponseTypes)) +} diff --git a/pkg/op/mock/configuration.mock.go b/pkg/op/mock/configuration.mock.go index c6174ff..b196508 100644 --- a/pkg/op/mock/configuration.mock.go +++ b/pkg/op/mock/configuration.mock.go @@ -103,20 +103,6 @@ func (mr *MockConfigurationMockRecorder) KeysEndpoint() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeysEndpoint", reflect.TypeOf((*MockConfiguration)(nil).KeysEndpoint)) } -// Port mocks base method -func (m *MockConfiguration) Port() string { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Port") - ret0, _ := ret[0].(string) - return ret0 -} - -// Port indicates an expected call of Port -func (mr *MockConfigurationMockRecorder) Port() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Port", reflect.TypeOf((*MockConfiguration)(nil).Port)) -} - // TokenEndpoint mocks base method func (m *MockConfiguration) TokenEndpoint() op.Endpoint { m.ctrl.T.Helper() diff --git a/pkg/op/mock/storage.mock.impl.go b/pkg/op/mock/storage.mock.impl.go index c9c63c6..6fd2760 100644 --- a/pkg/op/mock/storage.mock.impl.go +++ b/pkg/op/mock/storage.mock.impl.go @@ -3,6 +3,7 @@ package mock import ( "context" "errors" + "github.com/caos/oidc/pkg/oidc" "testing" "time" @@ -66,21 +67,25 @@ func ExpectValidClientID(s op.Storage) { var appType op.ApplicationType var authMethod op.AuthMethod var accessTokenType op.AccessTokenType + var responseTypes []oidc.ResponseType switch id { case "web_client": appType = op.ApplicationTypeWeb authMethod = op.AuthMethodBasic accessTokenType = op.AccessTokenTypeBearer + responseTypes = []oidc.ResponseType{oidc.ResponseTypeCode} case "native_client": appType = op.ApplicationTypeNative authMethod = op.AuthMethodNone accessTokenType = op.AccessTokenTypeBearer + responseTypes = []oidc.ResponseType{oidc.ResponseTypeCode} case "useragent_client": appType = op.ApplicationTypeUserAgent authMethod = op.AuthMethodBasic accessTokenType = op.AccessTokenTypeJWT + responseTypes = []oidc.ResponseType{oidc.ResponseTypeIDToken} } - return &ConfClient{id: id, appType: appType, authMethod: authMethod, accessTokenType: accessTokenType}, nil + return &ConfClient{id: id, appType: appType, authMethod: authMethod, accessTokenType: accessTokenType, responseTypes: responseTypes}, nil }) } @@ -116,6 +121,8 @@ type ConfClient struct { appType op.ApplicationType authMethod op.AuthMethod accessTokenType op.AccessTokenType + responseTypes []oidc.ResponseType + devMode bool } func (c *ConfClient) RedirectURIs() []string { @@ -138,7 +145,7 @@ func (c *ConfClient) ApplicationType() op.ApplicationType { return c.appType } -func (c *ConfClient) GetAuthMethod() op.AuthMethod { +func (c *ConfClient) AuthMethod() op.AuthMethod { return c.authMethod } @@ -155,3 +162,9 @@ func (c *ConfClient) IDTokenLifetime() time.Duration { func (c *ConfClient) AccessTokenType() op.AccessTokenType { return c.accessTokenType } +func (c *ConfClient) ResponseTypes() []oidc.ResponseType { + return c.responseTypes +} +func (c *ConfClient) DevMode() bool { + return c.devMode +} diff --git a/pkg/op/tokenrequest.go b/pkg/op/tokenrequest.go index 5ef4b22..f924531 100644 --- a/pkg/op/tokenrequest.go +++ b/pkg/op/tokenrequest.go @@ -80,11 +80,11 @@ func AuthorizeClient(ctx context.Context, tokenReq *oidc.AccessTokenRequest, exc if err != nil { return nil, nil, err } - if client.GetAuthMethod() == AuthMethodNone { + if client.AuthMethod() == AuthMethodNone { authReq, err := AuthorizeCodeChallenge(ctx, tokenReq, exchanger) return authReq, client, err } - if client.GetAuthMethod() == AuthMethodPost && !exchanger.AuthMethodPostSupported() { + if client.AuthMethod() == AuthMethodPost && !exchanger.AuthMethodPostSupported() { return nil, nil, errors.New("basic not supported") } err = AuthorizeClientIDSecret(ctx, tokenReq.ClientID, tokenReq.ClientSecret, exchanger.Storage()) From 5a8e69978f2cf41578c2342e8695a90c9bb7252c Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Thu, 6 Aug 2020 13:45:16 +0200 Subject: [PATCH 03/10] chore(workflow): semantic release (#42) * chore: change semantic releasing * fix release.yml --- .github/workflows/release.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 42c3ab0..37a842c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,10 @@ jobs: uses: actions/checkout@v1 with: fetch-depth: 1 - - name: Create Version - uses: caos/semantic-release@v0.2.4 - + - name: Semantic Release + uses: cycjimmy/semantic-release-action@v2 + with: + dry_run: false + semantic_version: 17.0.4 + extra_plugins: | + @semantic-release/exec@5.0.0 From c88e6b4ab31bd2e784d9f555b895a83ae43f98db Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 10 Aug 2020 15:49:32 +0200 Subject: [PATCH 04/10] fix: explicit allow Origin from request --- pkg/op/op.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/op/op.go b/pkg/op/op.go index 732a933..a6561dd 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -35,12 +35,16 @@ var DefaultInterceptor = func(h http.HandlerFunc) http.HandlerFunc { }) } +var allowAllOrigins = func(_ string) bool { + return true +} + func CreateRouter(o OpenIDProvider, h HttpInterceptor) *mux.Router { if h == nil { h = DefaultInterceptor } router := mux.NewRouter() - router.Use(handlers.CORS()) + router.Use(handlers.CORS(handlers.AllowedOriginValidator(allowAllOrigins))) router.HandleFunc(healthzEndpoint, Healthz) router.HandleFunc(readinessEndpoint, o.HandleReady) router.HandleFunc(oidc.DiscoveryEndpoint, o.HandleDiscovery) From 57cf8ee9c79cc3e3abc86eaf2fadde7c41b81ef1 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Thu, 20 Aug 2020 16:27:51 +0200 Subject: [PATCH 05/10] fix: add code_challenge_methods_supported to discovery endpoint (#43) * fix: add code_challenge_methods_supported to discovery endpoint * fix mock --- pkg/oidc/discovery.go | 1 + pkg/op/config.go | 1 + pkg/op/default_op.go | 7 +++++++ pkg/op/discovery.go | 9 +++++++++ pkg/op/mock/configuration.mock.go | 14 ++++++++++++++ 5 files changed, 32 insertions(+) diff --git a/pkg/oidc/discovery.go b/pkg/oidc/discovery.go index 5d2875e..9333ca9 100644 --- a/pkg/oidc/discovery.go +++ b/pkg/oidc/discovery.go @@ -20,5 +20,6 @@ type DiscoveryConfiguration struct { SubjectTypesSupported []string `json:"subject_types_supported,omitempty"` IDTokenSigningAlgValuesSupported []string `json:"id_token_signing_alg_values_supported,omitempty"` TokenEndpointAuthMethodsSupported []string `json:"token_endpoint_auth_methods_supported,omitempty"` + CodeChallengeMethodsSupported []string `json:"code_challenge_methods_supported,omitempty"` ClaimsSupported []string `json:"claims_supported,omitempty"` } diff --git a/pkg/op/config.go b/pkg/op/config.go index c52609a..b3df943 100644 --- a/pkg/op/config.go +++ b/pkg/op/config.go @@ -16,6 +16,7 @@ type Configuration interface { KeysEndpoint() Endpoint AuthMethodPostSupported() bool + CodeMethodS256Supported() bool } func ValidateIssuer(issuer string) error { diff --git a/pkg/op/default_op.go b/pkg/op/default_op.go index a16d4d3..732df21 100644 --- a/pkg/op/default_op.go +++ b/pkg/op/default_op.go @@ -26,6 +26,8 @@ const ( AuthMethodBasic AuthMethod = "client_secret_basic" AuthMethodPost = "client_secret_post" AuthMethodNone = "none" + + CodeMethodS256 = "S256" ) var ( @@ -58,6 +60,7 @@ type Config struct { Issuer string CryptoKey [32]byte DefaultLogoutRedirectURI string + CodeMethodS256 bool // ScopesSupported: oidc.SupportedScopes, // ResponseTypesSupported: responseTypes, // GrantTypesSupported: oidc.SupportedGrantTypes, @@ -222,6 +225,10 @@ func (p *DefaultOP) AuthMethodPostSupported() bool { return true //TODO: config } +func (p *DefaultOP) CodeMethodS256Supported() bool { + return p.config.CodeMethodS256 +} + func (p *DefaultOP) HttpHandler() http.Handler { return p.http } diff --git a/pkg/op/discovery.go b/pkg/op/discovery.go index fd6e0a6..54c473b 100644 --- a/pkg/op/discovery.go +++ b/pkg/op/discovery.go @@ -28,6 +28,7 @@ func CreateDiscoveryConfig(c Configuration, s Signer) *oidc.DiscoveryConfigurati IDTokenSigningAlgValuesSupported: SigAlgorithms(s), SubjectTypesSupported: SubjectTypes(c), TokenEndpointAuthMethodsSupported: AuthMethods(c), + CodeChallengeMethodsSupported: CodeChallengeMethods(c), } } @@ -117,3 +118,11 @@ func AuthMethods(c Configuration) []string { } return authMethods } + +func CodeChallengeMethods(c Configuration) []string { + codeMethods := make([]string, 0, 1) + if c.CodeMethodS256Supported() { + codeMethods = append(codeMethods, CodeMethodS256) + } + return codeMethods +} diff --git a/pkg/op/mock/configuration.mock.go b/pkg/op/mock/configuration.mock.go index b196508..88e9aa7 100644 --- a/pkg/op/mock/configuration.mock.go +++ b/pkg/op/mock/configuration.mock.go @@ -61,6 +61,20 @@ func (mr *MockConfigurationMockRecorder) AuthorizationEndpoint() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthorizationEndpoint", reflect.TypeOf((*MockConfiguration)(nil).AuthorizationEndpoint)) } +// CodeMethodS256Supported mocks base method +func (m *MockConfiguration) CodeMethodS256Supported() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CodeMethodS256Supported") + ret0, _ := ret[0].(bool) + return ret0 +} + +// CodeMethodS256Supported indicates an expected call of CodeMethodS256Supported +func (mr *MockConfigurationMockRecorder) CodeMethodS256Supported() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CodeMethodS256Supported", reflect.TypeOf((*MockConfiguration)(nil).CodeMethodS256Supported)) +} + // EndSessionEndpoint mocks base method func (m *MockConfiguration) EndSessionEndpoint() op.Endpoint { m.ctrl.T.Helper() From 6e71c17f1d68b8e7f2070ea108eb681ad1e070c2 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 24 Aug 2020 07:52:22 +0200 Subject: [PATCH 06/10] pass origin into GetUserinfoFromToken --- example/internal/mock/storage.go | 2 +- pkg/op/mock/storage.mock.go | 8 ++++---- pkg/op/op.go | 2 +- pkg/op/storage.go | 2 +- pkg/op/userinfo.go | 6 ++++-- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index 7e216de..faa62f0 100644 --- a/example/internal/mock/storage.go +++ b/example/internal/mock/storage.go @@ -202,7 +202,7 @@ func (s *AuthStorage) AuthorizeClientIDSecret(_ context.Context, id string, _ st return nil } -func (s *AuthStorage) GetUserinfoFromToken(ctx context.Context, _ string) (*oidc.Userinfo, error) { +func (s *AuthStorage) GetUserinfoFromToken(ctx context.Context, _, _ string) (*oidc.Userinfo, error) { return s.GetUserinfoFromScopes(ctx, "", []string{}) } func (s *AuthStorage) GetUserinfoFromScopes(_ context.Context, _ string, _ []string) (*oidc.Userinfo, error) { diff --git a/pkg/op/mock/storage.mock.go b/pkg/op/mock/storage.mock.go index ac8ba27..9432616 100644 --- a/pkg/op/mock/storage.mock.go +++ b/pkg/op/mock/storage.mock.go @@ -184,18 +184,18 @@ func (mr *MockStorageMockRecorder) GetUserinfoFromScopes(arg0, arg1, arg2 interf } // GetUserinfoFromToken mocks base method -func (m *MockStorage) GetUserinfoFromToken(arg0 context.Context, arg1 string) (*oidc.Userinfo, error) { +func (m *MockStorage) GetUserinfoFromToken(arg0 context.Context, arg1, arg2 string) (*oidc.Userinfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUserinfoFromToken", arg0, arg1) + ret := m.ctrl.Call(m, "GetUserinfoFromToken", arg0, arg1, arg2) ret0, _ := ret[0].(*oidc.Userinfo) ret1, _ := ret[1].(error) return ret0, ret1 } // GetUserinfoFromToken indicates an expected call of GetUserinfoFromToken -func (mr *MockStorageMockRecorder) GetUserinfoFromToken(arg0, arg1 interface{}) *gomock.Call { +func (mr *MockStorageMockRecorder) GetUserinfoFromToken(arg0, arg1, arg2 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserinfoFromToken", reflect.TypeOf((*MockStorage)(nil).GetUserinfoFromToken), arg0, arg1) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUserinfoFromToken", reflect.TypeOf((*MockStorage)(nil).GetUserinfoFromToken), arg0, arg1, arg2) } // Health mocks base method diff --git a/pkg/op/op.go b/pkg/op/op.go index a6561dd..1812a10 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -44,7 +44,7 @@ func CreateRouter(o OpenIDProvider, h HttpInterceptor) *mux.Router { h = DefaultInterceptor } router := mux.NewRouter() - router.Use(handlers.CORS(handlers.AllowedOriginValidator(allowAllOrigins))) + router.Use(handlers.CORS(handlers.AllowedOriginValidator(allowAllOrigins), handlers.AllowedHeaders([]string{"content-type"}))) router.HandleFunc(healthzEndpoint, Healthz) router.HandleFunc(readinessEndpoint, o.HandleReady) router.HandleFunc(oidc.DiscoveryEndpoint, o.HandleDiscovery) diff --git a/pkg/op/storage.go b/pkg/op/storage.go index e3ef5ff..17023c1 100644 --- a/pkg/op/storage.go +++ b/pkg/op/storage.go @@ -29,7 +29,7 @@ type OPStorage interface { GetClientByClientID(context.Context, string) (Client, error) AuthorizeClientIDSecret(context.Context, string, string) error GetUserinfoFromScopes(context.Context, string, []string) (*oidc.Userinfo, error) - GetUserinfoFromToken(context.Context, string) (*oidc.Userinfo, error) + GetUserinfoFromToken(context.Context, string, string) (*oidc.Userinfo, error) } type Storage interface { diff --git a/pkg/op/userinfo.go b/pkg/op/userinfo.go index 69746c7..8f55b15 100644 --- a/pkg/op/userinfo.go +++ b/pkg/op/userinfo.go @@ -5,9 +5,10 @@ import ( "net/http" "strings" + "github.com/gorilla/schema" + "github.com/caos/oidc/pkg/oidc" "github.com/caos/oidc/pkg/utils" - "github.com/gorilla/schema" ) type UserinfoProvider interface { @@ -27,8 +28,9 @@ func Userinfo(w http.ResponseWriter, r *http.Request, userinfoProvider UserinfoP http.Error(w, "access token missing", http.StatusUnauthorized) return } - info, err := userinfoProvider.Storage().GetUserinfoFromToken(r.Context(), tokenID) + info, err := userinfoProvider.Storage().GetUserinfoFromToken(r.Context(), tokenID, r.Header.Get("origin")) if err != nil { + w.WriteHeader(http.StatusForbidden) utils.MarshalJSON(w, err) return } From d02653e75dc8213916eda87e9f1618db6b4fb469 Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Mon, 24 Aug 2020 16:08:07 +0200 Subject: [PATCH 07/10] fix: add authorization to cors (#48) --- pkg/op/op.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/op/op.go b/pkg/op/op.go index 1812a10..fda9315 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -44,7 +44,11 @@ func CreateRouter(o OpenIDProvider, h HttpInterceptor) *mux.Router { h = DefaultInterceptor } router := mux.NewRouter() - router.Use(handlers.CORS(handlers.AllowedOriginValidator(allowAllOrigins), handlers.AllowedHeaders([]string{"content-type"}))) + router.Use(handlers.CORS( + handlers.AllowCredentials(), + handlers.AllowedHeaders([]string{"authorization", "content-type"}), + handlers.AllowedOriginValidator(allowAllOrigins), + )) router.HandleFunc(healthzEndpoint, Healthz) router.HandleFunc(readinessEndpoint, o.HandleReady) router.HandleFunc(oidc.DiscoveryEndpoint, o.HandleDiscovery) From c828290ef1d5e9657eedc2ff3b838109748b945d Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Fri, 28 Aug 2020 14:51:38 +0200 Subject: [PATCH 08/10] fix: improve interceptor handling (#49) --- pkg/op/default_op.go | 30 +++++++++++++++--------------- pkg/op/op.go | 38 +++++++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/pkg/op/default_op.go b/pkg/op/default_op.go index 732df21..a42da6a 100644 --- a/pkg/op/default_op.go +++ b/pkg/op/default_op.go @@ -42,18 +42,18 @@ var ( ) type DefaultOP struct { - config *Config - endpoints *endpoints - storage Storage - signer Signer - verifier rp.Verifier - crypto Crypto - http http.Handler - decoder *schema.Decoder - encoder *schema.Encoder - interceptor HttpInterceptor - retry func(int) (bool, int) - timer <-chan time.Time + config *Config + endpoints *endpoints + storage Storage + signer Signer + verifier rp.Verifier + crypto Crypto + http http.Handler + decoder *schema.Decoder + encoder *schema.Encoder + interceptors []HttpInterceptor + retry func(int) (bool, int) + timer <-chan time.Time } type Config struct { @@ -132,9 +132,9 @@ func WithCustomKeysEndpoint(endpoint Endpoint) DefaultOPOpts { } } -func WithHttpInterceptor(h HttpInterceptor) DefaultOPOpts { +func WithHttpInterceptors(interceptors ...HttpInterceptor) DefaultOPOpts { return func(o *DefaultOP) error { - o.interceptor = h + o.interceptors = append(o.interceptors, interceptors...) return nil } } @@ -185,7 +185,7 @@ func NewDefaultOP(ctx context.Context, config *Config, storage Storage, opOpts . p.verifier = rp.NewDefaultVerifier(config.Issuer, "", p, rp.WithIgnoreAudience(), rp.WithIgnoreExpiration()) - p.http = CreateRouter(p, p.interceptor) + p.http = CreateRouter(p, p.interceptors...) p.decoder = schema.NewDecoder() p.decoder.IgnoreUnknownKeys(true) diff --git a/pkg/op/op.go b/pkg/op/op.go index fda9315..624a8a1 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -27,22 +27,14 @@ type OpenIDProvider interface { HttpHandler() http.Handler } -type HttpInterceptor func(http.HandlerFunc) http.HandlerFunc - -var DefaultInterceptor = func(h http.HandlerFunc) http.HandlerFunc { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - h(w, r) - }) -} +type HttpInterceptor func(http.Handler) http.Handler var allowAllOrigins = func(_ string) bool { return true } -func CreateRouter(o OpenIDProvider, h HttpInterceptor) *mux.Router { - if h == nil { - h = DefaultInterceptor - } +func CreateRouter(o OpenIDProvider, interceptors ...HttpInterceptor) *mux.Router { + intercept := buildInterceptor(interceptors...) router := mux.NewRouter() router.Use(handlers.CORS( handlers.AllowCredentials(), @@ -52,11 +44,27 @@ func CreateRouter(o OpenIDProvider, h HttpInterceptor) *mux.Router { router.HandleFunc(healthzEndpoint, Healthz) router.HandleFunc(readinessEndpoint, o.HandleReady) router.HandleFunc(oidc.DiscoveryEndpoint, o.HandleDiscovery) - router.HandleFunc(o.AuthorizationEndpoint().Relative(), h(o.HandleAuthorize)) - router.HandleFunc(o.AuthorizationEndpoint().Relative()+"/{id}", h(o.HandleAuthorizeCallback)) - router.HandleFunc(o.TokenEndpoint().Relative(), h(o.HandleExchange)) + router.Handle(o.AuthorizationEndpoint().Relative(), intercept(o.HandleAuthorize)) + router.Handle(o.AuthorizationEndpoint().Relative()+"/{id}", intercept(o.HandleAuthorizeCallback)) + router.Handle(o.TokenEndpoint().Relative(), intercept(o.HandleExchange)) router.HandleFunc(o.UserinfoEndpoint().Relative(), o.HandleUserinfo) - router.HandleFunc(o.EndSessionEndpoint().Relative(), h(o.HandleEndSession)) + router.Handle(o.EndSessionEndpoint().Relative(), intercept(o.HandleEndSession)) router.HandleFunc(o.KeysEndpoint().Relative(), o.HandleKeys) return router } + +func buildInterceptor(interceptors ...HttpInterceptor) func(http.HandlerFunc) http.Handler { + return func(handlerFunc http.HandlerFunc) http.Handler { + handler := handlerFuncToHandler(handlerFunc) + for i := len(interceptors) - 1; i >= 0; i-- { + handler = interceptors[i](handler) + } + return handler + } +} + +func handlerFuncToHandler(handlerFunc http.HandlerFunc) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + handlerFunc(w, r) + }) +} From c7a15ae970ca5cd820716a46f4bf93827b875bc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 07:40:22 +0200 Subject: [PATCH 09/10] chore(deps): bump github.com/google/uuid from 1.1.1 to 1.1.2 (#50) Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.1.1 to 1.1.2. - [Release notes](https://github.com/google/uuid/releases) - [Commits](https://github.com/google/uuid/compare/v1.1.1...v1.1.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 445a27e..a8ea3ed 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/golang/mock v1.4.4 github.com/google/go-cmp v0.4.1 // indirect github.com/google/go-github/v31 v31.0.0 - github.com/google/uuid v1.1.1 + github.com/google/uuid v1.1.2 github.com/gorilla/handlers v1.4.2 github.com/gorilla/mux v1.7.4 github.com/gorilla/schema v1.1.0 diff --git a/go.sum b/go.sum index 16d3dac..3a4693e 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg= github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= From 2794ff12d58a1ae883823e45cddab46582ffbf3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 07:40:34 +0200 Subject: [PATCH 10/10] chore(deps): bump github.com/gorilla/mux from 1.7.4 to 1.8.0 (#46) Bumps [github.com/gorilla/mux](https://github.com/gorilla/mux) from 1.7.4 to 1.8.0. - [Release notes](https://github.com/gorilla/mux/releases) - [Commits](https://github.com/gorilla/mux/compare/v1.7.4...v1.8.0) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index a8ea3ed..a012b5c 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/google/go-github/v31 v31.0.0 github.com/google/uuid v1.1.2 github.com/gorilla/handlers v1.4.2 - github.com/gorilla/mux v1.7.4 + github.com/gorilla/mux v1.8.0 github.com/gorilla/schema v1.1.0 github.com/gorilla/securecookie v1.1.1 github.com/kr/pretty v0.1.0 // indirect diff --git a/go.sum b/go.sum index 3a4693e..c1fe1d3 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YAR github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=