Use nickname claim as User for GitLab

Previously this was only done in the `EnrichSession` stage
which would've missed Bearer usages & `RefreshSession`
would've overriden the User to the Subject.
This commit is contained in:
Nick Meves 2021-06-19 14:22:44 -07:00
parent c84a5a418f
commit 11c2177f18
4 changed files with 52 additions and 4 deletions

View File

@ -13,9 +13,13 @@
## Breaking Changes
- [#1239](https://github.com/oauth2-proxy/oauth2-proxy/pull/1239) GitLab groups sent in the `X-Forwarded-Groups` header
to the upstream server will no longer be prefixed with `group:`
## Changes since v7.1.3
- [#1337](https://github.com/oauth2-proxy/oauth2-proxy/pull/1337) Changing user field type to text when using htpasswd (@pburgisser)
- [#1239](https://github.com/oauth2-proxy/oauth2-proxy/pull/1239) Base GitLab provider implementation on OIDCProvider (@NickMeves)
- [#1276](https://github.com/oauth2-proxy/oauth2-proxy/pull/1276) Update crypto and switched to new github.com/golang-jwt/jwt (@JVecsei)
- [#1264](https://github.com/oauth2-proxy/oauth2-proxy/pull/1264) Update go-oidc to v3 (@NickMeves)
- [#1233](https://github.com/oauth2-proxy/oauth2-proxy/pull/1233) Extend email-domain validation with sub-domain capability (@morarucostel)

View File

@ -15,6 +15,7 @@ import (
const (
gitlabProviderName = "GitLab"
gitlabDefaultScope = "openid email"
gitlabUserClaim = "nickname"
)
// GitLabProvider represents a GitLab based Identity Provider
@ -29,6 +30,7 @@ var _ Provider = (*GitLabProvider)(nil)
// NewGitLabProvider initiates a new GitLabProvider
func NewGitLabProvider(p *ProviderData) *GitLabProvider {
p.ProviderName = gitlabProviderName
p.UserClaim = gitlabUserClaim
if p.Scope == "" {
p.Scope = gitlabDefaultScope
}
@ -119,17 +121,24 @@ func (p *GitLabProvider) EnrichSession(ctx context.Context, s *sessions.SessionS
return fmt.Errorf("user email is not verified")
}
s.User = userinfo.Username
s.Email = userinfo.Email
s.Groups = append(s.Groups, userinfo.Groups...)
if userinfo.Nickname != "" {
s.User = userinfo.Nickname
}
if userinfo.Email != "" {
s.Email = userinfo.Email
}
if len(userinfo.Groups) > 0 {
s.Groups = userinfo.Groups
}
// Add projects as `project:blah` to s.Groups
p.addProjectsToSession(ctx, s)
return nil
}
type gitlabUserinfo struct {
Username string `json:"nickname"`
Nickname string `json:"nickname"`
Email string `json:"email"`
EmailVerified bool `json:"email_verified"`
Groups []string `json:"groups"`

View File

@ -41,6 +41,7 @@ type ProviderData struct {
// Common OIDC options for any OIDC-based providers to consume
AllowUnverifiedEmail bool
UserClaim string
EmailClaim string
GroupsClaim string
Verifier *oidc.IDTokenVerifier
@ -156,6 +157,17 @@ func (p *ProviderData) buildSessionFromClaims(idToken *oidc.IDToken) (*sessions.
ss.Email = claims.Email
ss.Groups = claims.Groups
// Allow specialized providers that embed OIDCProvider to control the User
// claim. Not exposed as a configuration flag to generic OIDC provider
// users (yet).
if p.UserClaim != "" {
user, ok := claims.raw[p.UserClaim].(string)
if !ok {
return nil, fmt.Errorf("unable to extract custom UserClaim (%s)", p.UserClaim)
}
ss.User = user
}
// TODO (@NickMeves) Deprecate for dynamic claim to session mapping
if pref, ok := claims.raw["preferred_username"].(string); ok {
ss.PreferredUsername = pref

View File

@ -211,6 +211,7 @@ func TestProviderData_buildSessionFromClaims(t *testing.T) {
testCases := map[string]struct {
IDToken idTokenClaims
AllowUnverified bool
UserClaim string
EmailClaim string
GroupsClaim string
ExpectedError error
@ -259,6 +260,27 @@ func TestProviderData_buildSessionFromClaims(t *testing.T) {
PreferredUsername: "Complex Claim",
},
},
"User Claim Switched": {
IDToken: defaultIDToken,
AllowUnverified: true,
UserClaim: "phone_number",
EmailClaim: "email",
GroupsClaim: "groups",
ExpectedSession: &sessions.SessionState{
User: "+4798765432",
Email: "janed@me.com",
Groups: []string{"test:a", "test:b"},
PreferredUsername: "Jane Dobbs",
},
},
"User Claim Invalid": {
IDToken: defaultIDToken,
AllowUnverified: true,
UserClaim: "groups",
EmailClaim: "email",
GroupsClaim: "groups",
ExpectedError: errors.New("unable to extract custom UserClaim (groups)"),
},
"Email Claim Switched": {
IDToken: unverifiedIDToken,
AllowUnverified: true,
@ -332,6 +354,7 @@ func TestProviderData_buildSessionFromClaims(t *testing.T) {
),
}
provider.AllowUnverifiedEmail = tc.AllowUnverified
provider.UserClaim = tc.UserClaim
provider.EmailClaim = tc.EmailClaim
provider.GroupsClaim = tc.GroupsClaim