fix: tests

This commit is contained in:
Fabiennne 2020-08-06 09:21:25 +02:00
parent 3507057c66
commit 4eb2c4e270
10 changed files with 175 additions and 71 deletions

View file

@ -195,7 +195,7 @@ func (s *AuthStorage) GetClientByClientID(_ context.Context, id string) (op.Clie
authMethod = op.AuthMethodNone authMethod = op.AuthMethodNone
accessTokenType = op.AccessTokenTypeJWT 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 { 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 { type ConfClient struct {
applicationType op.ApplicationType applicationType op.ApplicationType
authMethod op.AuthMethod authMethod op.AuthMethod
responseTypes []oidc.ResponseType
ID string ID string
accessTokenType op.AccessTokenType accessTokenType op.AccessTokenType
devMode bool
} }
func (c *ConfClient) GetID() string { func (c *ConfClient) GetID() string {
@ -262,7 +264,7 @@ func (c *ConfClient) ApplicationType() op.ApplicationType {
return c.applicationType return c.applicationType
} }
func (c *ConfClient) GetAuthMethod() op.AuthMethod { func (c *ConfClient) AuthMethod() op.AuthMethod {
return c.authMethod return c.authMethod
} }
@ -272,3 +274,10 @@ func (c *ConfClient) IDTokenLifetime() time.Duration {
func (c *ConfClient) AccessTokenType() op.AccessTokenType { func (c *ConfClient) AccessTokenType() op.AccessTokenType {
return c.accessTokenType return c.accessTokenType
} }
func (c *ConfClient) ResponseTypes() []oidc.ResponseType {
return c.responseTypes
}
func (c *ConfClient) DevMode() bool {
return c.devMode
}

View file

@ -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) { 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 { if err := ValidateAuthReqScopes(authReq.Scopes); err != nil {
return "", err 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 return "", err
} }
if err := ValidateAuthReqResponseType(authReq.ResponseType); err != nil { if err := ValidateAuthReqResponseType(client, authReq.ResponseType); err != nil {
return "", err return "", err
} }
return ValidateAuthReqIDTokenHint(ctx, authReq.IDTokenHint, verifier) return ValidateAuthReqIDTokenHint(ctx, authReq.IDTokenHint, verifier)
@ -79,24 +83,24 @@ func ValidateAuthRequest(ctx context.Context, authReq *oidc.AuthRequest, storage
func ValidateAuthReqScopes(scopes []string) error { func ValidateAuthReqScopes(scopes []string) error {
if len(scopes) == 0 { 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) { 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 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 == "" { 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.") 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.")
}
client, err := storage.GetClientByClientID(ctx, client_id)
if err != nil {
return ErrServerError(err.Error())
} }
if !utils.Contains(client.RedirectURIs(), uri) { 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://") { if strings.HasPrefix(uri, "https://") {
return nil return nil
@ -105,24 +109,27 @@ func ValidateAuthReqRedirectURI(ctx context.Context, uri, client_id string, resp
if strings.HasPrefix(uri, "http://") && IsConfidentialType(client) { if strings.HasPrefix(uri, "http://") && IsConfidentialType(client) {
return nil return nil
} }
if client.ApplicationType() == ApplicationTypeNative { if !strings.HasPrefix(uri, "http://") && client.ApplicationType() == ApplicationTypeNative {
return nil 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 { } else {
if client.ApplicationType() != ApplicationTypeNative { 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/")) { 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 return nil
} }
func ValidateAuthReqResponseType(responseType oidc.ResponseType) error { func ValidateAuthReqResponseType(client Client, responseType oidc.ResponseType) error {
if responseType == "" { 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 return nil
} }
@ -133,7 +140,7 @@ func ValidateAuthReqIDTokenHint(ctx context.Context, idTokenHint string, verifie
} }
claims, err := verifier.Verify(ctx, "", idTokenHint) claims, err := verifier.Verify(ctx, "", idTokenHint)
if err != nil { 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 return claims.Subject, nil
} }

View file

@ -84,27 +84,27 @@ func TestValidateAuthRequest(t *testing.T) {
// } // }
{ {
"scope missing fails", "scope missing fails",
args{&oidc.AuthRequest{}, nil, nil}, args{&oidc.AuthRequest{}, mock.NewMockStorageExpectValidClientID(t), nil},
true, true,
}, },
{ {
"scope openid missing fails", "scope openid missing fails",
args{&oidc.AuthRequest{Scopes: []string{"profile"}}, nil, nil}, args{&oidc.AuthRequest{Scopes: []string{"profile"}}, mock.NewMockStorageExpectValidClientID(t), nil},
true, true,
}, },
{ {
"response_type missing fails", "response_type missing fails",
args{&oidc.AuthRequest{Scopes: []string{"openid"}}, nil, nil}, args{&oidc.AuthRequest{Scopes: []string{"openid"}}, mock.NewMockStorageExpectValidClientID(t), nil},
true, true,
}, },
{ {
"client_id missing fails", "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, true,
}, },
{ {
"redirect_uri missing fails", "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, true,
}, },
} }
@ -149,9 +149,8 @@ func TestValidateAuthReqScopes(t *testing.T) {
func TestValidateAuthReqRedirectURI(t *testing.T) { func TestValidateAuthReqRedirectURI(t *testing.T) {
type args struct { type args struct {
uri string uri string
clientID string client op.Client
responseType oidc.ResponseType responseType oidc.ResponseType
storage op.OPStorage
} }
tests := []struct { tests := []struct {
name string name string
@ -160,68 +159,106 @@ func TestValidateAuthReqRedirectURI(t *testing.T) {
}{ }{
{ {
"empty fails", "empty fails",
args{"", "", oidc.ResponseTypeCode, nil}, args{"",
mock.NewClientWithConfig(t, []string{"https://registered.com/callback"}, op.ApplicationTypeWeb, false),
oidc.ResponseTypeCode},
true, true,
}, },
{ {
"unregistered fails", "unregistered fails",
args{"https://unregistered.com/callback", "web_client", oidc.ResponseTypeCode, mock.NewMockStorageExpectValidClientID(t)}, args{"https://unregistered.com/callback",
true, mock.NewClientWithConfig(t, []string{"https://registered.com/callback"}, op.ApplicationTypeWeb, false),
}, oidc.ResponseTypeCode},
{
"storage error fails",
args{"https://registered.com/callback", "non_client", oidc.ResponseTypeIDToken, mock.NewMockStorageExpectInvalidClientID(t)},
true, true,
}, },
{ {
"code flow registered http not confidential fails", "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, false),
oidc.ResponseTypeCode},
true, true,
}, },
{ {
"code flow registered http confidential ok", "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, false),
oidc.ResponseTypeCode},
false, false,
}, },
{ {
"code flow registered custom not native fails", "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, false),
oidc.ResponseTypeCode},
true, true,
}, },
{ {
"code flow registered custom native ok", "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, 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, true),
oidc.ResponseTypeCode},
false, false,
}, },
{ {
"implicit flow registered ok", "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, false),
oidc.ResponseTypeIDToken},
false, false,
}, },
{
"implicit flow unregistered ok",
args{"https://unregistered.com/callback",
mock.NewClientWithConfig(t, []string{"https://registered.com/callback"}, op.ApplicationTypeUserAgent, false),
oidc.ResponseTypeIDToken},
true,
},
{ {
"implicit flow registered http localhost native ok", "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, false),
oidc.ResponseTypeIDToken},
false, false,
}, },
{ {
"implicit flow registered http localhost user agent fails", "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, false),
oidc.ResponseTypeIDToken},
true, true,
}, },
{ {
"implicit flow http non localhost fails", "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, false),
oidc.ResponseTypeIDToken},
true, true,
}, },
{ {
"implicit flow custom fails", "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, false),
oidc.ResponseTypeIDToken},
true, true,
}, },
{
"implicit flow dev mode http ok",
args{"http://registered.com/callback",
mock.NewClientWithConfig(t, []string{"http://registered.com/callback"}, op.ApplicationTypeNative, true),
oidc.ResponseTypeIDToken},
false,
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { 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) t.Errorf("ValidateRedirectURI() error = %v, wantErr %v", err.Error(), tt.wantErr)
} }
}) })

View file

@ -1,6 +1,9 @@
package op package op
import "time" import (
"github.com/caos/oidc/pkg/oidc"
"time"
)
const ( const (
ApplicationTypeWeb ApplicationType = iota ApplicationTypeWeb ApplicationType = iota
@ -16,16 +19,27 @@ type Client interface {
RedirectURIs() []string RedirectURIs() []string
PostLogoutRedirectURIs() []string PostLogoutRedirectURIs() []string
ApplicationType() ApplicationType ApplicationType() ApplicationType
GetAuthMethod() AuthMethod AuthMethod() AuthMethod
ResponseTypes() []oidc.ResponseType
LoginURL(string) string LoginURL(string) string
AccessTokenType() AccessTokenType AccessTokenType() AccessTokenType
IDTokenLifetime() time.Duration IDTokenLifetime() time.Duration
DevMode() bool
} }
func IsConfidentialType(c Client) bool { func IsConfidentialType(c Client) bool {
return c.ApplicationType() == ApplicationTypeWeb 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 ApplicationType int
type AuthMethod string type AuthMethod string

View file

@ -54,7 +54,7 @@ func TestValidateIssuer(t *testing.T) {
false, false,
}, },
{ {
"localhost with http ok", "localhost with http fails",
args{"http://localhost:9999"}, args{"http://localhost:9999"},
true, true,
}, },

View file

@ -27,3 +27,12 @@ func NewClientExpectAny(t *testing.T, appType op.ApplicationType) op.Client {
}) })
return c return c
} }
func NewClientWithConfig(t *testing.T, uri []string, appType op.ApplicationType, devMode bool) op.Client {
c := NewClient(t)
m := c.(*MockClient)
m.EXPECT().RedirectURIs().AnyTimes().Return(uri)
m.EXPECT().ApplicationType().AnyTimes().Return(appType)
m.EXPECT().DevMode().AnyTimes().Return(devMode)
return c
}

View file

@ -5,6 +5,7 @@
package mock package mock
import ( import (
oidc "github.com/caos/oidc/pkg/oidc"
op "github.com/caos/oidc/pkg/op" op "github.com/caos/oidc/pkg/op"
gomock "github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
reflect "reflect" 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)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplicationType", reflect.TypeOf((*MockClient)(nil).ApplicationType))
} }
// GetAuthMethod mocks base method // AuthMethod mocks base method
func (m *MockClient) GetAuthMethod() op.AuthMethod { func (m *MockClient) AuthMethod() op.AuthMethod {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetAuthMethod") ret := m.ctrl.Call(m, "AuthMethod")
ret0, _ := ret[0].(op.AuthMethod) ret0, _ := ret[0].(op.AuthMethod)
return ret0 return ret0
} }
// GetAuthMethod indicates an expected call of GetAuthMethod // AuthMethod indicates an expected call of AuthMethod
func (mr *MockClientMockRecorder) GetAuthMethod() *gomock.Call { func (mr *MockClientMockRecorder) AuthMethod() *gomock.Call {
mr.mock.ctrl.T.Helper() 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 // GetID mocks base method
@ -145,3 +160,17 @@ func (mr *MockClientMockRecorder) RedirectURIs() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RedirectURIs", reflect.TypeOf((*MockClient)(nil).RedirectURIs)) 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))
}

View file

@ -103,20 +103,6 @@ func (mr *MockConfigurationMockRecorder) KeysEndpoint() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeysEndpoint", reflect.TypeOf((*MockConfiguration)(nil).KeysEndpoint)) 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 // TokenEndpoint mocks base method
func (m *MockConfiguration) TokenEndpoint() op.Endpoint { func (m *MockConfiguration) TokenEndpoint() op.Endpoint {
m.ctrl.T.Helper() m.ctrl.T.Helper()

View file

@ -3,6 +3,7 @@ package mock
import ( import (
"context" "context"
"errors" "errors"
"github.com/caos/oidc/pkg/oidc"
"testing" "testing"
"time" "time"
@ -66,21 +67,25 @@ func ExpectValidClientID(s op.Storage) {
var appType op.ApplicationType var appType op.ApplicationType
var authMethod op.AuthMethod var authMethod op.AuthMethod
var accessTokenType op.AccessTokenType var accessTokenType op.AccessTokenType
var responseTypes []oidc.ResponseType
switch id { switch id {
case "web_client": case "web_client":
appType = op.ApplicationTypeWeb appType = op.ApplicationTypeWeb
authMethod = op.AuthMethodBasic authMethod = op.AuthMethodBasic
accessTokenType = op.AccessTokenTypeBearer accessTokenType = op.AccessTokenTypeBearer
responseTypes = []oidc.ResponseType{oidc.ResponseTypeCode}
case "native_client": case "native_client":
appType = op.ApplicationTypeNative appType = op.ApplicationTypeNative
authMethod = op.AuthMethodNone authMethod = op.AuthMethodNone
accessTokenType = op.AccessTokenTypeBearer accessTokenType = op.AccessTokenTypeBearer
responseTypes = []oidc.ResponseType{oidc.ResponseTypeCode}
case "useragent_client": case "useragent_client":
appType = op.ApplicationTypeUserAgent appType = op.ApplicationTypeUserAgent
authMethod = op.AuthMethodBasic authMethod = op.AuthMethodBasic
accessTokenType = op.AccessTokenTypeJWT 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 appType op.ApplicationType
authMethod op.AuthMethod authMethod op.AuthMethod
accessTokenType op.AccessTokenType accessTokenType op.AccessTokenType
responseTypes []oidc.ResponseType
devMode bool
} }
func (c *ConfClient) RedirectURIs() []string { func (c *ConfClient) RedirectURIs() []string {
@ -138,7 +145,7 @@ func (c *ConfClient) ApplicationType() op.ApplicationType {
return c.appType return c.appType
} }
func (c *ConfClient) GetAuthMethod() op.AuthMethod { func (c *ConfClient) AuthMethod() op.AuthMethod {
return c.authMethod return c.authMethod
} }
@ -155,3 +162,9 @@ func (c *ConfClient) IDTokenLifetime() time.Duration {
func (c *ConfClient) AccessTokenType() op.AccessTokenType { func (c *ConfClient) AccessTokenType() op.AccessTokenType {
return c.accessTokenType return c.accessTokenType
} }
func (c *ConfClient) ResponseTypes() []oidc.ResponseType {
return c.responseTypes
}
func (c *ConfClient) DevMode() bool {
return c.devMode
}

View file

@ -80,11 +80,11 @@ func AuthorizeClient(ctx context.Context, tokenReq *oidc.AccessTokenRequest, exc
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if client.GetAuthMethod() == AuthMethodNone { if client.AuthMethod() == AuthMethodNone {
authReq, err := AuthorizeCodeChallenge(ctx, tokenReq, exchanger) authReq, err := AuthorizeCodeChallenge(ctx, tokenReq, exchanger)
return authReq, client, err return authReq, client, err
} }
if client.GetAuthMethod() == AuthMethodPost && !exchanger.AuthMethodPostSupported() { if client.AuthMethod() == AuthMethodPost && !exchanger.AuthMethodPostSupported() {
return nil, nil, errors.New("basic not supported") return nil, nil, errors.New("basic not supported")
} }
err = AuthorizeClientIDSecret(ctx, tokenReq.ClientID, tokenReq.ClientSecret, exchanger.Storage()) err = AuthorizeClientIDSecret(ctx, tokenReq.ClientID, tokenReq.ClientSecret, exchanger.Storage())