From 803fdbf3c8609de6288f0b06a3f7b7c61f9d38cd Mon Sep 17 00:00:00 2001 From: Vladimir Dronnikov Date: Thu, 14 Mar 2024 15:25:56 +0000 Subject: [PATCH] draft scopes claim --- oauthproxy.go | 2 ++ pkg/apis/middleware/session.go | 4 ++++ pkg/apis/options/providers.go | 14 ++++++++++++++ pkg/apis/sessions/session_state.go | 13 ++++++++++++- providers/oidc.go | 2 ++ providers/provider_data.go | 4 ++++ providers/providers.go | 2 ++ 7 files changed, 40 insertions(+), 1 deletion(-) diff --git a/oauthproxy.go b/oauthproxy.go index 2aec2078..8f43e625 100644 --- a/oauthproxy.go +++ b/oauthproxy.go @@ -720,11 +720,13 @@ func (p *OAuthProxy) UserInfo(rw http.ResponseWriter, req *http.Request) { Email string `json:"email"` Groups []string `json:"groups,omitempty"` PreferredUsername string `json:"preferredUsername,omitempty"` + Name string `json:"name"` }{ User: session.User, Email: session.Email, Groups: session.Groups, PreferredUsername: session.PreferredUsername, + Name: session.Name, } if err := json.NewEncoder(rw).Encode(userInfo); err != nil { diff --git a/pkg/apis/middleware/session.go b/pkg/apis/middleware/session.go index 9fcd974b..694d33f6 100644 --- a/pkg/apis/middleware/session.go +++ b/pkg/apis/middleware/session.go @@ -24,7 +24,9 @@ func CreateTokenToSessionFunc(verify VerifyFunc) TokenToSessionFunc { Email string `json:"email"` Verified *bool `json:"email_verified"` PreferredUsername string `json:"preferred_username"` + Name string `json:"name"` Groups []string `json:"groups"` + Scopes []string `json:"scopes"` } idToken, err := verify(ctx, token) @@ -49,6 +51,8 @@ func CreateTokenToSessionFunc(verify VerifyFunc) TokenToSessionFunc { User: claims.Subject, Groups: claims.Groups, PreferredUsername: claims.PreferredUsername, + Name: claims.Name, + Scopes: claims.Scopes, AccessToken: token, IDToken: token, RefreshToken: "", diff --git a/pkg/apis/options/providers.go b/pkg/apis/options/providers.go index f4e2839d..34fcbbe6 100644 --- a/pkg/apis/options/providers.go +++ b/pkg/apis/options/providers.go @@ -4,8 +4,14 @@ const ( // OIDCEmailClaim is the generic email claim used by the OIDC provider. OIDCEmailClaim = "email" + // OIDCNameClaim is the generic name claim used by the OIDC provider. + OIDCNameClaim = "name" + // OIDCGroupsClaim is the generic groups claim used by the OIDC provider. OIDCGroupsClaim = "groups" + + // OIDCScopesClaim is the generic scopes claim used by the OIDC provider. + OIDCScopesClaim = "scopes" ) // OIDCAudienceClaims is the generic audience claim list used by the OIDC provider. @@ -228,9 +234,15 @@ type OIDCOptions struct { // EmailClaim indicates which claim contains the user email, // default set to 'email' EmailClaim string `json:"emailClaim,omitempty"` + // NameClaim indicates which claim contains the user name, + // default set to 'name' + NameClaim string `json:"nameClaim,omitempty"` // GroupsClaim indicates which claim contains the user groups // default set to 'groups' GroupsClaim string `json:"groupsClaim,omitempty"` + // ScopesClaim indicates which claim contains the user scopes + // default set to 'scopes' + ScopesClaim string `json:"scopesClaim,omitempty"` // UserIDClaim indicates which claim contains the user ID // default set to 'email' UserIDClaim string `json:"userIDClaim,omitempty"` @@ -264,7 +276,9 @@ func providerDefaults() Providers { SkipDiscovery: false, UserIDClaim: OIDCEmailClaim, // Deprecated: Use OIDCEmailClaim EmailClaim: OIDCEmailClaim, + NameClaim: OIDCNameClaim, GroupsClaim: OIDCGroupsClaim, + ScopesClaim: OIDCScopesClaim, AudienceClaims: OIDCAudienceClaims, ExtraAudiences: []string{}, }, diff --git a/pkg/apis/sessions/session_state.go b/pkg/apis/sessions/session_state.go index b5e4fc83..b7397495 100644 --- a/pkg/apis/sessions/session_state.go +++ b/pkg/apis/sessions/session_state.go @@ -28,6 +28,8 @@ type SessionState struct { User string `msgpack:"u,omitempty"` Groups []string `msgpack:"g,omitempty"` PreferredUsername string `msgpack:"pu,omitempty"` + Name string `msgpack:"dn,omitempty"` + Scopes []string `msgpack:"s,omitempty"` // Internal helpers, not serialized Clock clock.Clock `msgpack:"-"` @@ -101,7 +103,7 @@ func (s *SessionState) Age() time.Duration { // String constructs a summary of the session state func (s *SessionState) String() string { - o := fmt.Sprintf("Session{email:%s user:%s PreferredUsername:%s", s.Email, s.User, s.PreferredUsername) + o := fmt.Sprintf("Session{email:%s user:%s PreferredUsername:%s Name:%s", s.Email, s.User, s.PreferredUsername, s.Name) if s.AccessToken != "" { o += " token:true" } @@ -120,6 +122,9 @@ func (s *SessionState) String() string { if len(s.Groups) > 0 { o += fmt.Sprintf(" groups:%v", s.Groups) } + if len(s.Scopes) > 0 { + o += fmt.Sprintf(" scopes:%v", s.Scopes) + } return o + "}" } @@ -148,6 +153,12 @@ func (s *SessionState) GetClaim(claim string) []string { return groups case "preferred_username": return []string{s.PreferredUsername} + case "name": + return []string{s.Name} + case "scopes": + scopes := make([]string, len(s.Scopes)) + copy(scopes, s.Scopes) + return scopes default: return []string{} } diff --git a/providers/oidc.go b/providers/oidc.go index 43b5227e..d7f334b1 100644 --- a/providers/oidc.go +++ b/providers/oidc.go @@ -178,7 +178,9 @@ func (p *OIDCProvider) redeemRefreshToken(ctx context.Context, s *sessions.Sessi s.Email = newSession.Email s.User = newSession.User s.Groups = newSession.Groups + s.Scopes = newSession.Scopes s.PreferredUsername = newSession.PreferredUsername + s.Name = newSession.Name } s.AccessToken = newSession.AccessToken diff --git a/providers/provider_data.go b/providers/provider_data.go index 3c59c6da..68c36829 100644 --- a/providers/provider_data.go +++ b/providers/provider_data.go @@ -46,7 +46,9 @@ type ProviderData struct { AllowUnverifiedEmail bool UserClaim string EmailClaim string + NameClaim string GroupsClaim string + ScopesClaim string Verifier internaloidc.IDTokenVerifier SkipClaimsFromProfileURL bool @@ -260,6 +262,8 @@ func (p *ProviderData) buildSessionFromClaims(rawIDToken, accessToken string) (* {p.GroupsClaim, &ss.Groups}, // TODO (@NickMeves) Deprecate for dynamic claim to session mapping {"preferred_username", &ss.PreferredUsername}, + {p.NameClaim, &ss.Name}, + {p.ScopesClaim, &ss.Scopes}, } { if _, err := extractor.GetClaimInto(c.claim, c.dst); err != nil { return nil, err diff --git a/providers/providers.go b/providers/providers.go index 503b3559..c8ab2dbf 100644 --- a/providers/providers.go +++ b/providers/providers.go @@ -137,7 +137,9 @@ func newProviderDataFromConfig(providerConfig options.Provider) (*ProviderData, // Make the OIDC options available to all providers that support it p.AllowUnverifiedEmail = providerConfig.OIDCConfig.InsecureAllowUnverifiedEmail p.EmailClaim = providerConfig.OIDCConfig.EmailClaim + p.NameClaim = providerConfig.OIDCConfig.NameClaim p.GroupsClaim = providerConfig.OIDCConfig.GroupsClaim + p.ScopesClaim = providerConfig.OIDCConfig.ScopesClaim p.SkipClaimsFromProfileURL = providerConfig.SkipClaimsFromProfileURL // Set PKCE enabled or disabled based on discovery and force options