make userName configurable
This commit is contained in:
		| @@ -71,7 +71,11 @@ connectors: | |||||||
|     # Default: sub |     # Default: sub | ||||||
|     # Claims list at https://openid.net/specs/openid-connect-core-1_0.html#Claims |     # Claims list at https://openid.net/specs/openid-connect-core-1_0.html#Claims | ||||||
|     # |     # | ||||||
|     # userIdKey: nickname |     # userIDKey: nickname | ||||||
|  |      | ||||||
|  |     # The set claim is used as user name. | ||||||
|  |     # Default: name | ||||||
|  |     # userNameKey: nickname | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| [oidc-doc]: openid-connect.md | [oidc-doc]: openid-connect.md | ||||||
|   | |||||||
| @@ -47,6 +47,9 @@ type Config struct { | |||||||
|  |  | ||||||
| 	// Configurable key which contains the user id claim | 	// Configurable key which contains the user id claim | ||||||
| 	UserIDKey string `json:"userIDKey"` | 	UserIDKey string `json:"userIDKey"` | ||||||
|  |  | ||||||
|  | 	// Configurable key which contains the user name claim | ||||||
|  | 	UserNameKey string `json:"userNameKey"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // Domains that don't support basic auth. golang.org/x/oauth2 has an internal | // Domains that don't support basic auth. golang.org/x/oauth2 has an internal | ||||||
| @@ -131,6 +134,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e | |||||||
| 		insecureSkipEmailVerified: c.InsecureSkipEmailVerified, | 		insecureSkipEmailVerified: c.InsecureSkipEmailVerified, | ||||||
| 		getUserInfo:               c.GetUserInfo, | 		getUserInfo:               c.GetUserInfo, | ||||||
| 		userIDKey:                 c.UserIDKey, | 		userIDKey:                 c.UserIDKey, | ||||||
|  | 		userNameKey:               c.UserNameKey, | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -151,6 +155,7 @@ type oidcConnector struct { | |||||||
| 	insecureSkipEmailVerified bool | 	insecureSkipEmailVerified bool | ||||||
| 	getUserInfo               bool | 	getUserInfo               bool | ||||||
| 	userIDKey                 string | 	userIDKey                 string | ||||||
|  | 	userNameKey               string | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *oidcConnector) Close() error { | func (c *oidcConnector) Close() error { | ||||||
| @@ -209,9 +214,13 @@ func (c *oidcConnector) HandleCallback(s connector.Scopes, r *http.Request) (ide | |||||||
| 		return identity, fmt.Errorf("oidc: failed to decode claims: %v", err) | 		return identity, fmt.Errorf("oidc: failed to decode claims: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	name, found := claims["name"].(string) | 	userNameKey := "name" | ||||||
|  | 	if c.userNameKey != "" { | ||||||
|  | 		userNameKey = c.userNameKey | ||||||
|  | 	} | ||||||
|  | 	name, found := claims[userNameKey].(string) | ||||||
| 	if !found { | 	if !found { | ||||||
| 		return identity, errors.New("missing \"name\" claim") | 		return identity, fmt.Errorf("missing \"%s\" claim", userNameKey) | ||||||
| 	} | 	} | ||||||
| 	email, found := claims["email"].(string) | 	email, found := claims["email"].(string) | ||||||
| 	if !found { | 	if !found { | ||||||
|   | |||||||
| @@ -47,14 +47,18 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name                      string | 		name                      string | ||||||
| 		userIDKey                 string | 		userIDKey                 string | ||||||
|  | 		userNameKey               string | ||||||
| 		insecureSkipEmailVerified bool | 		insecureSkipEmailVerified bool | ||||||
| 		expectUserID              string | 		expectUserID              string | ||||||
|  | 		expectUserName            string | ||||||
| 		token                     map[string]interface{} | 		token                     map[string]interface{} | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			name:         "simpleCase", | 			name:           "simpleCase", | ||||||
| 			userIDKey:    "", // not configured | 			userIDKey:      "", // not configured | ||||||
| 			expectUserID: "subvalue", | 			userNameKey:    "", // not configured | ||||||
|  | 			expectUserID:   "subvalue", | ||||||
|  | 			expectUserName: "namevalue", | ||||||
| 			token: map[string]interface{}{ | 			token: map[string]interface{}{ | ||||||
| 				"sub":            "subvalue", | 				"sub":            "subvalue", | ||||||
| 				"name":           "namevalue", | 				"name":           "namevalue", | ||||||
| @@ -66,6 +70,7 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 			name:                      "email_verified not in claims, configured to be skipped", | 			name:                      "email_verified not in claims, configured to be skipped", | ||||||
| 			insecureSkipEmailVerified: true, | 			insecureSkipEmailVerified: true, | ||||||
| 			expectUserID:              "subvalue", | 			expectUserID:              "subvalue", | ||||||
|  | 			expectUserName:            "namevalue", | ||||||
| 			token: map[string]interface{}{ | 			token: map[string]interface{}{ | ||||||
| 				"sub":   "subvalue", | 				"sub":   "subvalue", | ||||||
| 				"name":  "namevalue", | 				"name":  "namevalue", | ||||||
| @@ -73,9 +78,10 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			name:         "withUserIDKey", | 			name:           "withUserIDKey", | ||||||
| 			userIDKey:    "name", | 			userIDKey:      "name", | ||||||
| 			expectUserID: "namevalue", | 			expectUserID:   "namevalue", | ||||||
|  | 			expectUserName: "namevalue", | ||||||
| 			token: map[string]interface{}{ | 			token: map[string]interface{}{ | ||||||
| 				"sub":            "subvalue", | 				"sub":            "subvalue", | ||||||
| 				"name":           "namevalue", | 				"name":           "namevalue", | ||||||
| @@ -83,6 +89,18 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 				"email_verified": true, | 				"email_verified": true, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:           "withUserNameKey", | ||||||
|  | 			userNameKey:    "user_name", | ||||||
|  | 			expectUserID:   "subvalue", | ||||||
|  | 			expectUserName: "username", | ||||||
|  | 			token: map[string]interface{}{ | ||||||
|  | 				"sub":            "subvalue", | ||||||
|  | 				"user_name":      "username", | ||||||
|  | 				"email":          "emailvalue", | ||||||
|  | 				"email_verified": true, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, tc := range tests { | 	for _, tc := range tests { | ||||||
| @@ -100,6 +118,7 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 				Scopes:                    []string{"groups"}, | 				Scopes:                    []string{"groups"}, | ||||||
| 				RedirectURI:               fmt.Sprintf("%s/callback", serverURL), | 				RedirectURI:               fmt.Sprintf("%s/callback", serverURL), | ||||||
| 				UserIDKey:                 tc.userIDKey, | 				UserIDKey:                 tc.userIDKey, | ||||||
|  | 				UserNameKey:               tc.userNameKey, | ||||||
| 				InsecureSkipEmailVerified: tc.insecureSkipEmailVerified, | 				InsecureSkipEmailVerified: tc.insecureSkipEmailVerified, | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @@ -119,7 +138,7 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			expectEquals(t, identity.UserID, tc.expectUserID) | 			expectEquals(t, identity.UserID, tc.expectUserID) | ||||||
| 			expectEquals(t, identity.Username, "namevalue") | 			expectEquals(t, identity.Username, tc.expectUserName) | ||||||
| 			expectEquals(t, identity.Email, "emailvalue") | 			expectEquals(t, identity.Email, "emailvalue") | ||||||
| 			expectEquals(t, identity.EmailVerified, true) | 			expectEquals(t, identity.EmailVerified, true) | ||||||
| 		}) | 		}) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user