From 3082234dae89762542109da8315c682dafd96bcc Mon Sep 17 00:00:00 2001 From: Livio Amstutz Date: Tue, 3 Dec 2019 09:48:30 +0100 Subject: [PATCH] keys and more --- example/internal/mock/storage.go | 25 ++++++++++++++++++++++++- example/server/default/default.go | 2 +- pkg/op/config.go | 1 + pkg/op/default_op.go | 10 ++++++++++ pkg/op/discovery.go | 2 +- pkg/op/keys.go | 19 +++++++++++++++++++ pkg/op/mock/storage.mock.go | 15 +++++++++++++++ pkg/op/op.go | 2 ++ pkg/op/storage.go | 1 + 9 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 pkg/op/keys.go diff --git a/example/internal/mock/storage.go b/example/internal/mock/storage.go index a2fb779..f272f77 100644 --- a/example/internal/mock/storage.go +++ b/example/internal/mock/storage.go @@ -1,6 +1,8 @@ package mock import ( + "crypto/rand" + "crypto/rsa" "errors" "time" @@ -11,6 +13,19 @@ import ( ) type Storage struct { + key *rsa.PrivateKey +} + +func NewStorage() op.Storage { + reader := rand.Reader + bitSize := 2048 + key, err := rsa.GenerateKey(reader, bitSize) + if err != nil { + panic(err) + } + return &Storage{ + key: key, + } } type AuthRequest struct { @@ -113,7 +128,15 @@ func (s *Storage) AuthRequestByID(id string) (op.AuthRequest, error) { } func (s *Storage) GetSigningKey() (*jose.SigningKey, error) { - return &jose.SigningKey{Algorithm: jose.HS256, Key: []byte("test")}, nil + return &jose.SigningKey{Algorithm: jose.RS256, Key: s.key}, nil +} +func (s *Storage) GetKeySet() (jose.JSONWebKeySet, error) { + pubkey := s.key.Public() + return jose.JSONWebKeySet{ + Keys: []jose.JSONWebKey{ + jose.JSONWebKey{Key: pubkey, Use: "sig", Algorithm: "RS256"}, + }, + }, nil } type ConfClient struct { diff --git a/example/server/default/default.go b/example/server/default/default.go index 17ea0e9..f7b97f3 100644 --- a/example/server/default/default.go +++ b/example/server/default/default.go @@ -15,7 +15,7 @@ func main() { Port: "9998", } - storage := &mock.Storage{} + storage := mock.NewStorage() handler, err := op.NewDefaultOP(config, storage, op.WithCustomTokenEndpoint("test")) if err != nil { log.Fatal(err) diff --git a/pkg/op/config.go b/pkg/op/config.go index 151265e..7d7c853 100644 --- a/pkg/op/config.go +++ b/pkg/op/config.go @@ -11,6 +11,7 @@ type Configuration interface { AuthorizationEndpoint() Endpoint TokenEndpoint() Endpoint UserinfoEndpoint() Endpoint + KeysEndpoint() Endpoint Port() string } diff --git a/pkg/op/default_op.go b/pkg/op/default_op.go index 55874da..db39fe8 100644 --- a/pkg/op/default_op.go +++ b/pkg/op/default_op.go @@ -14,6 +14,7 @@ const ( defaulTokenEndpoint = "oauth/token" defaultIntrospectEndpoint = "introspect" defaultUserinfoEndpoint = "userinfo" + defaultKeysEndpoint = "keys" ) var ( @@ -22,6 +23,7 @@ var ( Token: defaulTokenEndpoint, IntrospectionEndpoint: defaultIntrospectEndpoint, Userinfo: defaultUserinfoEndpoint, + JwksURI: defaultKeysEndpoint, } DefaultIDTokenValidity = time.Duration(5 * time.Minute) ) @@ -146,6 +148,10 @@ func (p *DefaultOP) UserinfoEndpoint() Endpoint { return Endpoint(p.endpoints.Userinfo) } +func (p *DefaultOP) KeysEndpoint() Endpoint { + return Endpoint(p.endpoints.JwksURI) +} + func (p *DefaultOP) Port() string { return p.config.Port } @@ -186,6 +192,10 @@ func (p *DefaultOP) IDTokenValidity() time.Duration { // return AuthRequestError // } +func (p *DefaultOP) HandleKeys(w http.ResponseWriter, r *http.Request) { + Keys(w, r, p) +} + func (p *DefaultOP) HandleAuthorize(w http.ResponseWriter, r *http.Request) { Authorize(w, r, p) } diff --git a/pkg/op/discovery.go b/pkg/op/discovery.go index 41ad770..a3db9be 100644 --- a/pkg/op/discovery.go +++ b/pkg/op/discovery.go @@ -20,7 +20,7 @@ func CreateDiscoveryConfig(c Configuration) *oidc.DiscoveryConfiguration { UserinfoEndpoint: c.UserinfoEndpoint().Absolute(c.Issuer()), // EndSessionEndpoint: c.TokenEndpoint().Absolute(c.Issuer())(c.EndSessionEndpoint), // CheckSessionIframe: c.TokenEndpoint().Absolute(c.Issuer())(c.CheckSessionIframe), - // JwksURI: c.TokenEndpoint().Absolute(c.Issuer())(c.JwksURI), + JwksURI: c.KeysEndpoint().Absolute(c.Issuer()), // ScopesSupported: oidc.SupportedScopes, // ResponseTypesSupported: responseTypes, // GrantTypesSupported: oidc.SupportedGrantTypes, diff --git a/pkg/op/keys.go b/pkg/op/keys.go new file mode 100644 index 0000000..018b040 --- /dev/null +++ b/pkg/op/keys.go @@ -0,0 +1,19 @@ +package op + +import ( + "net/http" + + "github.com/caos/oidc/pkg/utils" +) + +type KeyProvider interface { + Storage() Storage +} + +func Keys(w http.ResponseWriter, r *http.Request, k KeyProvider) { + keySet, err := k.Storage().GetKeySet() + if err != nil { + + } + utils.MarshalJSON(w, keySet) +} diff --git a/pkg/op/mock/storage.mock.go b/pkg/op/mock/storage.mock.go index 3c7bc1d..9dfc096 100644 --- a/pkg/op/mock/storage.mock.go +++ b/pkg/op/mock/storage.mock.go @@ -139,6 +139,21 @@ func (mr *MockStorageMockRecorder) GetClientByClientID(arg0 interface{}) *gomock return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClientByClientID", reflect.TypeOf((*MockStorage)(nil).GetClientByClientID), arg0) } +// GetKeySet mocks base method +func (m *MockStorage) GetKeySet() (go_jose_v2.JSONWebKeySet, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetKeySet") + ret0, _ := ret[0].(go_jose_v2.JSONWebKeySet) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetKeySet indicates an expected call of GetKeySet +func (mr *MockStorageMockRecorder) GetKeySet() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetKeySet", reflect.TypeOf((*MockStorage)(nil).GetKeySet)) +} + // GetSigningKey mocks base method func (m *MockStorage) GetSigningKey() (*go_jose_v2.SigningKey, error) { m.ctrl.T.Helper() diff --git a/pkg/op/op.go b/pkg/op/op.go index 35769b9..d5d96ab 100644 --- a/pkg/op/op.go +++ b/pkg/op/op.go @@ -18,6 +18,7 @@ type OpenIDProvider interface { HandleAuthorizeCallback(w http.ResponseWriter, r *http.Request) HandleExchange(w http.ResponseWriter, r *http.Request) HandleUserinfo(w http.ResponseWriter, r *http.Request) + HandleKeys(w http.ResponseWriter, r *http.Request) // Storage() Storage HttpHandler() *http.Server } @@ -29,6 +30,7 @@ func CreateRouter(o OpenIDProvider) *mux.Router { router.HandleFunc(o.AuthorizationEndpoint().Relative()+"/{id}", o.HandleAuthorizeCallback) router.HandleFunc(o.TokenEndpoint().Relative(), o.HandleExchange) router.HandleFunc(o.UserinfoEndpoint().Relative(), o.HandleUserinfo) + router.HandleFunc(o.KeysEndpoint().Relative(), o.HandleKeys) return router } diff --git a/pkg/op/storage.go b/pkg/op/storage.go index 08f37e0..3dc06ad 100644 --- a/pkg/op/storage.go +++ b/pkg/op/storage.go @@ -17,6 +17,7 @@ type Storage interface { AuthorizeClientIDCodeVerifier(string, string) (Client, error) DeleteAuthRequestAndCode(string, string) error GetSigningKey() (*jose.SigningKey, error) + GetKeySet() (jose.JSONWebKeySet, error) } type AuthRequest interface {