diff --git a/example/go.sum b/example/go.sum index 4f9df56..bf4723b 100644 --- a/example/go.sum +++ b/example/go.sum @@ -22,6 +22,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 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= @@ -98,6 +100,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index fa57df0..6857d4c 100644 --- a/example/internal/mock/storage.go +++ b/example/internal/mock/storage.go @@ -8,5 +8,38 @@ type Storage struct { } func (s *Storage) CreateAuthRequest(authReq *oidc.AuthRequest) error { + authReq.ID = "id" return nil } +func (s *Storage) GetClientByClientID(string) (oidc.Client, error) { + return &ConfClient{}, nil +} +func (s *Storage) AuthRequestByCode(oidc.Client, string, string) (*oidc.AuthRequest, error) { + return &oidc.AuthRequest{ID: "id"}, nil +} +func (s *Storage) AuthorizeClientIDSecret(string, string) (oidc.Client, error) { + return &ConfClient{}, nil +} +func (s *Storage) AuthorizeClientIDCodeVerifier(string, string) (oidc.Client, error) { + return &ConfClient{}, nil +} +func (s *Storage) DeleteAuthRequestAndCode(string, string) error { + return nil +} + +type ConfClient struct{} + +func (c *ConfClient) Type() oidc.ClientType { + return oidc.ClientTypeConfidential +} +func (c *ConfClient) RedirectURIs() []string { + return []string{ + "https://registered.com/callback", + "http://localhost:9999/callback", + "custom://callback", + } +} + +func (c *ConfClient) LoginURL(id string) string { + return "login?id=" + id +} diff --git a/pkg/oidc/authorization.go b/pkg/oidc/authorization.go index 2da734f..e3c2d24 100644 --- a/pkg/oidc/authorization.go +++ b/pkg/oidc/authorization.go @@ -8,6 +8,8 @@ import ( ) const ( + ScopeOpenID = "openid" + ResponseTypeCode ResponseType = "code" ResponseTypeIDToken ResponseType = "id_token token" ResponseTypeIDTokenOnly ResponseType = "id_token" @@ -21,6 +23,8 @@ const ( PromptLogin = "login" PromptConsent = "consent" PromptSelectAccount = "select_account" + + GrantTypeCode GrantType = "authorization_code" ) var displayValues = map[string]Display{ @@ -34,6 +38,7 @@ var displayValues = map[string]Display{ //https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest // type AuthRequest struct { + ID string Scopes Scopes `schema:"scope"` ResponseType ResponseType `schema:"response_type"` ClientID string `schema:"client_id"` @@ -53,6 +58,49 @@ type AuthRequest struct { ACRValues []string `schema:"acr_values"` } +type TokenRequest interface { + // GrantType GrantType `schema:"grant_type"` + GrantType() GrantType +} + +type TokenRequestType GrantType + +type AccessTokenRequest struct { + Code string `schema:"code"` + RedirectURI string `schema:"redirect_uri"` + ClientID string `schema:"client_id"` + ClientSecret string `schema:"client_secret"` + CodeVerifier string `schema:"code_verifier"` +} + +func (a *AccessTokenRequest) GrantType() GrantType { + return GrantTypeCode +} + +type AccessTokenResponse struct { + AccessToken string `json:"access_token,omitempty"` + TokenType string `json:"token_type,omitempty"` + RefreshToken string `json:"refresh_token,omitempty"` + ExpiresIn uint64 `json:"expires_in,omitempty"` + IDToken string `json:"id_token,omitempty"` +} + +// func (a AccessTokenRequest) UnmarshalText(text []byte) error { +// fmt.Println(string(text)) +// return nil +// } + +type TokenExchangeRequest struct { + subjectToken string `schema:"subject_token"` + subjectTokenType string `schema:"subject_token_type"` + actorToken string `schema:"actor_token"` + actorTokenType string `schema:"actor_token_type"` + resource []string `schema:"resource"` + audience []string `schema:"audience"` + Scope []string `schema:"scope"` + requestedTokenType string `schema:"requested_token_type"` +} + // func (a *AuthRequest) UnmarshalText(text []byte) error { // // var f formAuthRequest // log.Println(string(text)) @@ -115,3 +163,5 @@ func (l *Locales) UnmarshalText(text []byte) error { } return nil } + +type GrantType string diff --git a/pkg/oidc/client.go b/pkg/oidc/client.go new file mode 100644 index 0000000..c156175 --- /dev/null +++ b/pkg/oidc/client.go @@ -0,0 +1,18 @@ +package oidc + +type Client interface { + RedirectURIs() []string + Type() ClientType + LoginURL(string) string +} + +type ClientType int + +func (c ClientType) IsConvidential() bool { + return c == ClientTypeConfidential +} + +const ( + ClientTypeConfidential ClientType = iota + ClientTypePublic +) diff --git a/pkg/op/authrequest.go b/pkg/op/authrequest.go index 6c4ba51..1c78740 100644 --- a/pkg/op/authrequest.go +++ b/pkg/op/authrequest.go @@ -10,7 +10,7 @@ import ( str_utils "github.com/caos/utils/strings" ) -func ParseAuthRequest(w http.ResponseWriter, r *http.Request) (*oidc.AuthRequest, error) { +func Authorize(w http.ResponseWriter, r *http.Request, storage Storage) (*oidc.AuthRequest, error) { err := r.ParseForm() if err != nil { return nil, errors.New("Unimplemented") //TODO: impl @@ -22,25 +22,53 @@ func ParseAuthRequest(w http.ResponseWriter, r *http.Request) (*oidc.AuthRequest d.IgnoreUnknownKeys(true) err = d.Decode(authReq, r.Form) - return authReq, err + if err != nil { + return nil, err + } + if err = ValidateAuthRequest(authReq, storage); err != nil { + return nil, err + } + err = storage.CreateAuthRequest(authReq) + if err != nil { + //TODO: return err + } + client, err := storage.GetClientByClientID(authReq.ClientID) + if err != nil { + return nil, err + } + RedirectToLogin(authReq, client, w, r) + return nil, nil } -func ValidateAuthRequest(authRequest *oidc.AuthRequest, storage Storage) error { - - if err := ValidateRedirectURI(authRequest.RedirectURI, authRequest.ClientID, storage); err != nil { +func ValidateAuthRequest(authReq *oidc.AuthRequest, storage Storage) error { + if err := ValidateAuthReqScopes(authReq.Scopes); err != nil { return err } + if err := ValidateAuthReqRedirectURI(authReq.RedirectURI, authReq.ClientID, storage); err != nil { + return err + } + return nil return errors.New("Unimplemented") //TODO: impl https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.3.1.2.2 // if NeedsExistingSession(authRequest) { // session, err := storage.CheckSession(authRequest) // if err != nil { - // //TODO: return err + // //TODO: return err< // } // } } -func ValidateRedirectURI(uri, client_id string, storage Storage) error { +func ValidateAuthReqScopes(scopes []string) error { + if len(scopes) == 0 { + return errors.New("scope missing") + } + if !str_utils.Contains(scopes, oidc.ScopeOpenID) { + return errors.New("scope openid missing") + } + return nil +} + +func ValidateAuthReqRedirectURI(uri, client_id string, storage Storage) error { if uri == "" { return errors.New("redirect_uri must not be empty") //TODO: } @@ -53,3 +81,8 @@ func ValidateRedirectURI(uri, client_id string, storage Storage) error { } return nil } + +func RedirectToLogin(authReq *oidc.AuthRequest, client oidc.Client, w http.ResponseWriter, r *http.Request) { + login := client.LoginURL(authReq.ID) + http.Redirect(w, r, login, http.StatusFound) +} diff --git a/pkg/op/authrequest_test.go b/pkg/op/authrequest_test.go index 72338b6..c01f8eb 100644 --- a/pkg/op/authrequest_test.go +++ b/pkg/op/authrequest_test.go @@ -1,4 +1,4 @@ -package op_test +package op import ( "testing" @@ -51,7 +51,7 @@ func TestValidateAuthRequest(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := op.ValidateAuthRequest(tt.args.authRequest, tt.args.storage); (err != nil) != tt.wantErr { + if err := ValidateAuthRequest(tt.args.authRequest, tt.args.storage); (err != nil) != tt.wantErr { t.Errorf("ValidateAuthRequest() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -102,7 +102,7 @@ func TestValidateRedirectURI(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := op.ValidateRedirectURI(tt.args.uri, tt.args.clientID, tt.args.storage); (err != nil) != tt.wantErr { + if err := ValidateAuthReqRedirectURI(tt.args.uri, tt.args.clientID, tt.args.storage); (err != nil) != tt.wantErr { t.Errorf("ValidateRedirectURI() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/pkg/op/default_op.go b/pkg/op/default_op.go index 8f98cf5..c547f3e 100644 --- a/pkg/op/default_op.go +++ b/pkg/op/default_op.go @@ -1,6 +1,7 @@ package op import ( + "encoding/json" "errors" "net/http" "net/url" @@ -180,22 +181,67 @@ func (p *DefaultOP) HandleDiscovery(w http.ResponseWriter, r *http.Request) { } func (p *DefaultOP) HandleAuthorize(w http.ResponseWriter, r *http.Request) { - authRequest, err := ParseAuthRequest(w, r) + _, err := Authorize(w, r, p.storage) if err != nil { - //TODO: return err + http.Error(w, err.Error(), 400) } - err = ValidateAuthRequest(authRequest, p.storage) - if err != nil { - //TODO: return err - } - // err = p.storage.CreateAuthRequest(authRequest) + // authRequest, err := ParseAuthRequest(w, r) // if err != nil { // //TODO: return err // } - //TODO: redirect? + // err = ValidateAuthRequest(authRequest, p.storage) + // if err != nil { + // http.Error(w, err.Error(), 400) + // return + // //TODO: return err + // } + // // err = p.storage.CreateAuthRequest(authRequest) + // // if err != nil { + // // //TODO: return err + // // } + // var client oidc.Client + // RedirectToLogin(authRequest, client, w, r) } func (p *DefaultOP) HandleExchange(w http.ResponseWriter, r *http.Request) { + reqType := r.FormValue("grant_type") + if reqType == "" { + //return errors.New("grant_type missing") //TODO: impl + } + if reqType == string(oidc.GrantTypeCode) { + token, err := CodeExchange(w, r, p.storage) + if err != nil { + + } + b, _ := json.Marshal(token) + w.Write(b) + return + } + p.handleTokenExchange(w, r) +} + +// func (p *DefaultOP) handleCodeExchange(w http.ResponseWriter, r *http.Request) { +// tokenRequest, err := ParseAccessTokenRequest(w, r) +// if err != nil { +// //TODO: return err +// } +// err = ValidateAccessTokenRequest(tokenRequest, p.storage) +// if err != nil { +// //TODO: return err +// } +// b, _ := json.Marshal(tokenRequest) +// w.Write(b) +// } + +func (p *DefaultOP) handleTokenExchange(w http.ResponseWriter, r *http.Request) { + tokenRequest, err := ParseTokenExchangeRequest(w, r) + if err != nil { + //TODO: return err + } + err = ValidateTokenExchangeRequest(tokenRequest, p.storage) + if err != nil { + //TODO: return err + } } func (p *DefaultOP) HandleUserinfo(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/op/go.mod b/pkg/op/go.mod index 79c738e..c99e2a5 100644 --- a/pkg/op/go.mod +++ b/pkg/op/go.mod @@ -21,4 +21,5 @@ require ( github.com/gorilla/mux v1.7.3 github.com/gorilla/schema v1.1.0 github.com/stretchr/testify v1.4.0 + golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 ) diff --git a/pkg/op/mock/storage.mock.go b/pkg/op/mock/storage.mock.go index 0f803f6..a6276b8 100644 --- a/pkg/op/mock/storage.mock.go +++ b/pkg/op/mock/storage.mock.go @@ -6,7 +6,6 @@ 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" ) @@ -34,6 +33,51 @@ func (m *MockStorage) EXPECT() *MockStorageMockRecorder { return m.recorder } +// AuthRequestByCode mocks base method +func (m *MockStorage) AuthRequestByCode(arg0 oidc.Client, arg1, arg2 string) (*oidc.AuthRequest, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AuthRequestByCode", arg0, arg1, arg2) + ret0, _ := ret[0].(*oidc.AuthRequest) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AuthRequestByCode indicates an expected call of AuthRequestByCode +func (mr *MockStorageMockRecorder) AuthRequestByCode(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthRequestByCode", reflect.TypeOf((*MockStorage)(nil).AuthRequestByCode), arg0, arg1, arg2) +} + +// AuthorizeClientIDCodeVerifier mocks base method +func (m *MockStorage) AuthorizeClientIDCodeVerifier(arg0, arg1 string) (oidc.Client, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AuthorizeClientIDCodeVerifier", arg0, arg1) + ret0, _ := ret[0].(oidc.Client) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AuthorizeClientIDCodeVerifier indicates an expected call of AuthorizeClientIDCodeVerifier +func (mr *MockStorageMockRecorder) AuthorizeClientIDCodeVerifier(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthorizeClientIDCodeVerifier", reflect.TypeOf((*MockStorage)(nil).AuthorizeClientIDCodeVerifier), arg0, arg1) +} + +// AuthorizeClientIDSecret mocks base method +func (m *MockStorage) AuthorizeClientIDSecret(arg0, arg1 string) (oidc.Client, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AuthorizeClientIDSecret", arg0, arg1) + ret0, _ := ret[0].(oidc.Client) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// AuthorizeClientIDSecret indicates an expected call of AuthorizeClientIDSecret +func (mr *MockStorageMockRecorder) AuthorizeClientIDSecret(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AuthorizeClientIDSecret", reflect.TypeOf((*MockStorage)(nil).AuthorizeClientIDSecret), arg0, arg1) +} + // CreateAuthRequest mocks base method func (m *MockStorage) CreateAuthRequest(arg0 *oidc.AuthRequest) error { m.ctrl.T.Helper() @@ -48,11 +92,25 @@ func (mr *MockStorageMockRecorder) CreateAuthRequest(arg0 interface{}) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateAuthRequest", reflect.TypeOf((*MockStorage)(nil).CreateAuthRequest), arg0) } +// DeleteAuthRequestAndCode mocks base method +func (m *MockStorage) DeleteAuthRequestAndCode(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteAuthRequestAndCode", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteAuthRequestAndCode indicates an expected call of DeleteAuthRequestAndCode +func (mr *MockStorageMockRecorder) DeleteAuthRequestAndCode(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAuthRequestAndCode", reflect.TypeOf((*MockStorage)(nil).DeleteAuthRequestAndCode), arg0, arg1) +} + // GetClientByClientID mocks base method -func (m *MockStorage) GetClientByClientID(arg0 string) (op.Client, error) { +func (m *MockStorage) GetClientByClientID(arg0 string) (oidc.Client, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetClientByClientID", arg0) - ret0, _ := ret[0].(op.Client) + ret0, _ := ret[0].(oidc.Client) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/pkg/op/mock/sotrage.mock.impl.go b/pkg/op/mock/storage.mock.impl.go similarity index 57% rename from pkg/op/mock/sotrage.mock.impl.go rename to pkg/op/mock/storage.mock.impl.go index 4611956..f4c002c 100644 --- a/pkg/op/mock/sotrage.mock.impl.go +++ b/pkg/op/mock/storage.mock.impl.go @@ -5,6 +5,7 @@ import ( "github.com/golang/mock/gomock" + "github.com/caos/oidc/pkg/oidc" "github.com/caos/oidc/pkg/op" ) @@ -18,6 +19,14 @@ func NewMockStorageExpectValidClientID(t *testing.T) op.Storage { return m } +func NewMockStorageAny(t *testing.T) op.Storage { + m := NewStorage(t) + mockS := m.(*MockStorage) + mockS.EXPECT().GetClientByClientID(gomock.Any()).AnyTimes().Return(&ConfClient{}, nil) + mockS.EXPECT().AuthorizeClientIDSecret(gomock.Any(), gomock.Any()).AnyTimes().Return(&ConfClient{}, nil) + return m +} + func ExpectValidClientID(s op.Storage) { mockS := s.(*MockStorage) mockS.EXPECT().GetClientByClientID(gomock.Any()).Return(&ConfClient{}, nil) @@ -25,8 +34,8 @@ func ExpectValidClientID(s op.Storage) { type ConfClient struct{} -func (c *ConfClient) Type() op.ClientType { - return op.ClientTypeConfidential +func (c *ConfClient) Type() oidc.ClientType { + return oidc.ClientTypeConfidential } func (c *ConfClient) RedirectURIs() []string { return []string{ @@ -35,3 +44,7 @@ func (c *ConfClient) RedirectURIs() []string { "custom://callback", } } + +func (c *ConfClient) LoginURL(id string) string { + return "login?id=" + id +} diff --git a/pkg/op/storage.go b/pkg/op/storage.go index 2872703..388bb22 100644 --- a/pkg/op/storage.go +++ b/pkg/op/storage.go @@ -4,21 +4,9 @@ import "github.com/caos/oidc/pkg/oidc" type Storage interface { CreateAuthRequest(*oidc.AuthRequest) error - GetClientByClientID(string) (Client, error) + GetClientByClientID(string) (oidc.Client, error) + AuthRequestByCode(oidc.Client, string, string) (*oidc.AuthRequest, error) + AuthorizeClientIDSecret(string, string) (oidc.Client, error) + AuthorizeClientIDCodeVerifier(string, string) (oidc.Client, error) + DeleteAuthRequestAndCode(string, string) error } - -type Client interface { - RedirectURIs() []string - Type() ClientType -} - -type ClientType int - -func (c ClientType) IsConvidential() bool { - return c == ClientTypeConfidential -} - -const ( - ClientTypeConfidential ClientType = iota - ClientTypePublic -) diff --git a/pkg/op/tokenrequest.go b/pkg/op/tokenrequest.go new file mode 100644 index 0000000..b80b4f8 --- /dev/null +++ b/pkg/op/tokenrequest.go @@ -0,0 +1,100 @@ +package op + +import ( + "errors" + "net/http" + + "github.com/gorilla/schema" + + "github.com/caos/oidc/pkg/oidc" +) + +// func ParseTokenRequest(w http.ResponseWriter, r *http.Request) (oidc.TokenRequest, error) { +// reqType := r.FormValue("grant_type") +// if reqType == "" { +// return nil, errors.New("grant_type missing") //TODO: impl +// } +// if reqType == string(oidc.GrantTypeCode) { +// return ParseAccessTokenRequest(w, r) +// } +// return ParseTokenExchangeRequest(w, r) +// } + +func CodeExchange(w http.ResponseWriter, r *http.Request, storage Storage) (*oidc.AccessTokenResponse, error) { + err := r.ParseForm() + if err != nil { + return nil, errors.New("Unimplemented") //TODO: impl + } + tokenReq := new(oidc.AccessTokenRequest) + + //TODO: + d := schema.NewDecoder() + d.IgnoreUnknownKeys(true) + + err = d.Decode(tokenReq, r.Form) + if err != nil { + return nil, err + } + if tokenReq.Code == "" { + return nil, errors.New("code missing") + } + + client, err := AuthorizeClient(r, tokenReq, storage) + if err != nil { + return nil, err + } + authReq, err := storage.AuthRequestByCode(client, tokenReq.Code, tokenReq.RedirectURI) + if err != nil { + + } + err = storage.DeleteAuthRequestAndCode(authReq.ID, tokenReq.Code) + if err != nil { + + } + accessToken, err := CreateAccessToken() + if err != nil { + + } + idToken, err := CreateIDToken() + if err != nil { + + } + + return &oidc.AccessTokenResponse{ + AccessToken: accessToken, + IDToken: idToken, + }, nil +} + +func CreateAccessToken() (string, error) { + return "", nil +} +func CreateIDToken() (string, error) { + return "", nil +} + +func AuthorizeClient(r *http.Request, tokenReq *oidc.AccessTokenRequest, storage Storage) (oidc.Client, error) { + if tokenReq.ClientID == "" { + clientID, clientSecret, ok := r.BasicAuth() + if ok { + return storage.AuthorizeClientIDSecret(clientID, clientSecret) + } + + } + if tokenReq.ClientSecret != "" { + return storage.AuthorizeClientIDSecret(tokenReq.ClientID, tokenReq.ClientSecret) + } + if tokenReq.CodeVerifier != "" { + return storage.AuthorizeClientIDCodeVerifier(tokenReq.ClientID, tokenReq.CodeVerifier) + } + return nil, errors.New("Unimplemented") //TODO: impl +} + +func ParseTokenExchangeRequest(w http.ResponseWriter, r *http.Request) (oidc.TokenRequest, error) { + return nil, errors.New("Unimplemented") //TODO: impl +} + +func ValidateTokenExchangeRequest(tokenReq oidc.TokenRequest, storage Storage) error { + + return errors.New("Unimplemented") //TODO: impl +}