git.iko.soy/typeable/oauth2-proxy
on master help sign in
Use `nickname` claim as User for GitLab
11c2177Nick Meves
CHANGELOG.md+4
@@ -13,9 +13,13 @@
13
13
14## Breaking Changes
14## Breaking Changes
15
15
16+- [#1239](https://github.com/oauth2-proxy/oauth2-proxy/pull/1239) GitLab groups sent in the `X-Forwarded-Groups` header
17+ to the upstream server will no longer be prefixed with `group:`
18+
16## Changes since v7.1.3
19## Changes since v7.1.3
17
20
18- [#1337](https://github.com/oauth2-proxy/oauth2-proxy/pull/1337) Changing user field type to text when using htpasswd (@pburgisser)
21- [#1337](https://github.com/oauth2-proxy/oauth2-proxy/pull/1337) Changing user field type to text when using htpasswd (@pburgisser)
22+- [#1239](https://github.com/oauth2-proxy/oauth2-proxy/pull/1239) Base GitLab provider implementation on OIDCProvider (@NickMeves)
19- [#1276](https://github.com/oauth2-proxy/oauth2-proxy/pull/1276) Update crypto and switched to new github.com/golang-jwt/jwt (@JVecsei)
23- [#1276](https://github.com/oauth2-proxy/oauth2-proxy/pull/1276) Update crypto and switched to new github.com/golang-jwt/jwt (@JVecsei)
20- [#1264](https://github.com/oauth2-proxy/oauth2-proxy/pull/1264) Update go-oidc to v3 (@NickMeves)
24- [#1264](https://github.com/oauth2-proxy/oauth2-proxy/pull/1264) Update go-oidc to v3 (@NickMeves)
21- [#1233](https://github.com/oauth2-proxy/oauth2-proxy/pull/1233) Extend email-domain validation with sub-domain capability (@morarucostel)
25- [#1233](https://github.com/oauth2-proxy/oauth2-proxy/pull/1233) Extend email-domain validation with sub-domain capability (@morarucostel)
providers/gitlab.go+13−4
@@ -15,6 +15,7 @@ import (
15const (
15const (
16 gitlabProviderName = "GitLab"
16 gitlabProviderName = "GitLab"
17 gitlabDefaultScope = "openid email"
17 gitlabDefaultScope = "openid email"
18+ gitlabUserClaim = "nickname"
18)
19)
19
20
20// GitLabProvider represents a GitLab based Identity Provider
21// GitLabProvider represents a GitLab based Identity Provider
@@ -29,6 +30,7 @@ var _ Provider = (*GitLabProvider)(nil)
29// NewGitLabProvider initiates a new GitLabProvider
30// NewGitLabProvider initiates a new GitLabProvider
30func NewGitLabProvider(p *ProviderData) *GitLabProvider {
31func NewGitLabProvider(p *ProviderData) *GitLabProvider {
31 p.ProviderName = gitlabProviderName
32 p.ProviderName = gitlabProviderName
33+ p.UserClaim = gitlabUserClaim
32 if p.Scope == "" {
34 if p.Scope == "" {
33 p.Scope = gitlabDefaultScope
35 p.Scope = gitlabDefaultScope
34 }
36 }
@@ -119,17 +121,24 @@ func (p *GitLabProvider) EnrichSession(ctx context.Context, s *sessions.SessionS
119 return fmt.Errorf("user email is not verified")
121 return fmt.Errorf("user email is not verified")
120 }
122 }
121
123
124+ if userinfo.Nickname != "" {
122− s.User = userinfo.Username
125+ s.User = userinfo.Nickname
126+ }
127+ if userinfo.Email != "" {
123− s.Email = userinfo.Email
128+ s.Email = userinfo.Email
129+ }
124− s.Groups = append(s.Groups, userinfo.Groups...)
130+ if len(userinfo.Groups) > 0 {
131+ s.Groups = userinfo.Groups
132+ }
125
133
134+ // Add projects as `project:blah` to s.Groups
126 p.addProjectsToSession(ctx, s)
135 p.addProjectsToSession(ctx, s)
127
136
128 return nil
137 return nil
129}
138}
130
139
131type gitlabUserinfo struct {
140type gitlabUserinfo struct {
132− Username string `json:"nickname"`
141+ Nickname string `json:"nickname"`
133 Email string `json:"email"`
142 Email string `json:"email"`
134 EmailVerified bool `json:"email_verified"`
143 EmailVerified bool `json:"email_verified"`
135 Groups []string `json:"groups"`
144 Groups []string `json:"groups"`
providers/provider_data.go+12
@@ -41,6 +41,7 @@ type ProviderData struct {
41
41
42 // Common OIDC options for any OIDC-based providers to consume
42 // Common OIDC options for any OIDC-based providers to consume
43 AllowUnverifiedEmail bool
43 AllowUnverifiedEmail bool
44+ UserClaim string
44 EmailClaim string
45 EmailClaim string
45 GroupsClaim string
46 GroupsClaim string
46 Verifier *oidc.IDTokenVerifier
47 Verifier *oidc.IDTokenVerifier
@@ -156,6 +157,17 @@ func (p *ProviderData) buildSessionFromClaims(idToken *oidc.IDToken) (*sessions.
156 ss.Email = claims.Email
157 ss.Email = claims.Email
157 ss.Groups = claims.Groups
158 ss.Groups = claims.Groups
158
159
160+ // Allow specialized providers that embed OIDCProvider to control the User
161+ // claim. Not exposed as a configuration flag to generic OIDC provider
162+ // users (yet).
163+ if p.UserClaim != "" {
164+ user, ok := claims.raw[p.UserClaim].(string)
165+ if !ok {
166+ return nil, fmt.Errorf("unable to extract custom UserClaim (%s)", p.UserClaim)
167+ }
168+ ss.User = user
169+ }
170+
159 // TODO (@NickMeves) Deprecate for dynamic claim to session mapping
171 // TODO (@NickMeves) Deprecate for dynamic claim to session mapping
160 if pref, ok := claims.raw["preferred_username"].(string); ok {
172 if pref, ok := claims.raw["preferred_username"].(string); ok {
161 ss.PreferredUsername = pref
173 ss.PreferredUsername = pref
providers/provider_data_test.go+23
@@ -211,6 +211,7 @@ func TestProviderData_buildSessionFromClaims(t *testing.T) {
211 testCases := map[string]struct {
211 testCases := map[string]struct {
212 IDToken idTokenClaims
212 IDToken idTokenClaims
213 AllowUnverified bool
213 AllowUnverified bool
214+ UserClaim string
214 EmailClaim string
215 EmailClaim string
215 GroupsClaim string
216 GroupsClaim string
216 ExpectedError error
217 ExpectedError error
@@ -259,6 +260,27 @@ func TestProviderData_buildSessionFromClaims(t *testing.T) {
259 PreferredUsername: "Complex Claim",
260 PreferredUsername: "Complex Claim",
260 },
261 },
261 },
262 },
263+ "User Claim Switched": {
264+ IDToken: defaultIDToken,
265+ AllowUnverified: true,
266+ UserClaim: "phone_number",
267+ EmailClaim: "email",
268+ GroupsClaim: "groups",
269+ ExpectedSession: &sessions.SessionState{
270+ User: "+4798765432",
271+ Email: "janed@me.com",
272+ Groups: []string{"test:a", "test:b"},
273+ PreferredUsername: "Jane Dobbs",
274+ },
275+ },
276+ "User Claim Invalid": {
277+ IDToken: defaultIDToken,
278+ AllowUnverified: true,
279+ UserClaim: "groups",
280+ EmailClaim: "email",
281+ GroupsClaim: "groups",
282+ ExpectedError: errors.New("unable to extract custom UserClaim (groups)"),
283+ },
262 "Email Claim Switched": {
284 "Email Claim Switched": {
263 IDToken: unverifiedIDToken,
285 IDToken: unverifiedIDToken,
264 AllowUnverified: true,
286 AllowUnverified: true,
@@ -332,6 +354,7 @@ func TestProviderData_buildSessionFromClaims(t *testing.T) {
332 ),
354 ),
333 }
355 }
334 provider.AllowUnverifiedEmail = tc.AllowUnverified
356 provider.AllowUnverifiedEmail = tc.AllowUnverified
357+ provider.UserClaim = tc.UserClaim
335 provider.EmailClaim = tc.EmailClaim
358 provider.EmailClaim = tc.EmailClaim
336 provider.GroupsClaim = tc.GroupsClaim
359 provider.GroupsClaim = tc.GroupsClaim
337
360