From a5302e3dbbac5b2d771f0db9e106cbbda0b184f0 Mon Sep 17 00:00:00 2001 From: Andy Lo-A-Foe Date: Fri, 19 May 2023 11:29:30 +0200 Subject: [PATCH] Dynamic Scopes support #2960 Signed-off-by: Andy Lo-A-Foe --- cmd/dex/config.go | 2 ++ cmd/dex/serve.go | 4 ++++ server/handlers.go | 11 ++++++++++- server/oauth2.go | 13 +++++++++++-- server/server.go | 6 +++++- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/cmd/dex/config.go b/cmd/dex/config.go index 7bb7fbb780..ed995d97ec 100644 --- a/cmd/dex/config.go +++ b/cmd/dex/config.go @@ -137,6 +137,8 @@ type OAuth2 struct { AlwaysShowLoginScreen bool `json:"alwaysShowLoginScreen"` // This is the connector that can be used for password grant PasswordConnector string `json:"passwordConnector"` + // List of additional scope prefixes to allow + AllowedScopePrefixes []string `json:"allowedScopePrefixes"` } // Web is the config format for the HTTP server. diff --git a/cmd/dex/serve.go b/cmd/dex/serve.go index c8fb95eb16..e819a71886 100644 --- a/cmd/dex/serve.go +++ b/cmd/dex/serve.go @@ -263,6 +263,9 @@ func runServe(options serveOptions) error { if len(c.Web.AllowedOrigins) > 0 { logger.Infof("config allowed origins: %s", c.Web.AllowedOrigins) } + if len(c.OAuth2.AllowedScopePrefixes) > 0 { + logger.Infof("config allowed scope prefixes: %s", strings.Join(c.OAuth2.AllowedScopePrefixes, ",")) + } // explicitly convert to UTC. now := func() time.Time { return time.Now().UTC() } @@ -275,6 +278,7 @@ func runServe(options serveOptions) error { AlwaysShowLoginScreen: c.OAuth2.AlwaysShowLoginScreen, PasswordConnector: c.OAuth2.PasswordConnector, AllowedOrigins: c.Web.AllowedOrigins, + AllowedScopePrefixes: c.OAuth2.AllowedScopePrefixes, Issuer: c.Issuer, Storage: s, Web: c.Frontend, diff --git a/server/handlers.go b/server/handlers.go index 08004c6d0e..d2c568769f 100755 --- a/server/handlers.go +++ b/server/handlers.go @@ -1115,7 +1115,16 @@ func (s *Server) handlePasswordGrant(w http.ResponseWriter, r *http.Request, cli default: peerID, ok := parseCrossClientScope(scope) if !ok { - unrecognized = append(unrecognized, scope) + var recognized bool + for _, prefix := range s.allowedScopePrefixes { + if strings.HasPrefix(scope, prefix) { + recognized = true + break + } + } + if !recognized { + unrecognized = append(unrecognized, scope) + } continue } diff --git a/server/oauth2.go b/server/oauth2.go index bb0058a74a..d19ac7618a 100644 --- a/server/oauth2.go +++ b/server/oauth2.go @@ -93,7 +93,7 @@ func tokenErr(w http.ResponseWriter, typ, description string, statusCode int) er return nil } -//nolint +// nolint const ( errInvalidRequest = "invalid_request" errUnauthorizedClient = "unauthorized_client" @@ -491,7 +491,16 @@ func (s *Server) parseAuthorizationRequest(r *http.Request) (*storage.AuthReques default: peerID, ok := parseCrossClientScope(scope) if !ok { - unrecognized = append(unrecognized, scope) + var recognized bool + for _, prefix := range s.allowedScopePrefixes { + if strings.HasPrefix(scope, prefix) { + recognized = true + break + } + } + if !recognized { + unrecognized = append(unrecognized, scope) + } continue } diff --git a/server/server.go b/server/server.go index f23eb54b7c..212902f3e9 100755 --- a/server/server.go +++ b/server/server.go @@ -104,7 +104,8 @@ type Config struct { PrometheusRegistry *prometheus.Registry - HealthChecker gosundheit.Health + HealthChecker gosundheit.Health + AllowedScopePrefixes []string } // WebConfig holds the server's frontend templates and asset configuration. @@ -173,6 +174,8 @@ type Server struct { supportedGrantTypes []string + allowedScopePrefixes []string + now func() time.Time idTokensValidFor time.Duration @@ -268,6 +271,7 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy) storage: newKeyCacher(c.Storage, now), supportedResponseTypes: supportedRes, supportedGrantTypes: supportedGrant, + allowedScopePrefixes: c.AllowedScopePrefixes, idTokensValidFor: value(c.IDTokensValidFor, 24*time.Hour), authRequestsValidFor: value(c.AuthRequestsValidFor, 24*time.Hour), deviceRequestsValidFor: value(c.DeviceRequestsValidFor, 5*time.Minute),