diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index 5fb823b6..7e216deb 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 9eb6504b..41a7b441 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 dca72faa..1b31fad7 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 a61e31d7..9e8a7dca 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 56cf2eb9..348872ff 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 242eb13d..b0d0dcac 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 e2f1c113..4007347a 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 c6174ff1..b1965083 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 c9c63c62..6fd27602 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 5ef4b221..f9245310 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())