Allow preferred_username claim to be set for Crowd connector (#1684)
* Add atlassiancrowd connector to list in readme * Add TestIdentityFromCrowdUser * Set preferred_username claim when configured * Add preferredUsernameField option to docs * Log warning when mapping invalid crowd field
This commit is contained in:
		| @@ -36,4 +36,9 @@ connectors: | |||||||
|     - my-group |     - my-group | ||||||
|     # Prompt for username field. |     # Prompt for username field. | ||||||
|     usernamePrompt: Login |     usernamePrompt: Login | ||||||
|  |     # Optionally set preferred_username claim. | ||||||
|  |     # If `preferredUsernameField` is omitted or contains an invalid option, the `preferred_username` claim will be empty. | ||||||
|  |     # If `preferredUsernameField` is set, the `preferred_username` claim will be set to the chosen Crowd user attribute value. | ||||||
|  |     # Possible choices are: "key", "name", "email" | ||||||
|  |     preferredUsernameField: name | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -76,6 +76,7 @@ Dex implements the following connectors: | |||||||
| | [AuthProxy](Documentation/connectors/authproxy.md) | no | no | no | alpha | Authentication proxies such as Apache2 mod_auth, etc. | | | [AuthProxy](Documentation/connectors/authproxy.md) | no | no | no | alpha | Authentication proxies such as Apache2 mod_auth, etc. | | ||||||
| | [Bitbucket Cloud](Documentation/connectors/bitbucketcloud.md) | yes | yes | no | alpha | | | | [Bitbucket Cloud](Documentation/connectors/bitbucketcloud.md) | yes | yes | no | alpha | | | ||||||
| | [OpenShift](Documentation/connectors/openshift.md) | no | yes | no | stable | | | | [OpenShift](Documentation/connectors/openshift.md) | no | yes | no | stable | | | ||||||
|  | | [Atlassian Crowd](Documentation/connectors/atlassiancrowd.md) | yes | yes | yes *) | beta | preferred_username claim must be configured through config | | ||||||
|  |  | ||||||
| Stable, beta, and alpha are defined as: | Stable, beta, and alpha are defined as: | ||||||
|  |  | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ import ( | |||||||
| //       - admin | //       - admin | ||||||
| //       # Prompt for username field | //       # Prompt for username field | ||||||
| //       usernamePrompt: Login | //       usernamePrompt: Login | ||||||
|  | //		 preferredUsernameField: name | ||||||
| // | // | ||||||
| type Config struct { | type Config struct { | ||||||
| 	BaseURL      string   `json:"baseURL"` | 	BaseURL      string   `json:"baseURL"` | ||||||
| @@ -42,6 +43,11 @@ type Config struct { | |||||||
| 	ClientSecret string   `json:"clientSecret"` | 	ClientSecret string   `json:"clientSecret"` | ||||||
| 	Groups       []string `json:"groups"` | 	Groups       []string `json:"groups"` | ||||||
|  |  | ||||||
|  | 	// PreferredUsernameField allows users to set the field to any of the | ||||||
|  | 	// following values: "key", "name" or "email". | ||||||
|  | 	// If unset, the preferred_username field will remain empty. | ||||||
|  | 	PreferredUsernameField string `json:"preferredUsernameField"` | ||||||
|  |  | ||||||
| 	// UsernamePrompt allows users to override the username attribute (displayed | 	// UsernamePrompt allows users to override the username attribute (displayed | ||||||
| 	// in the username/password prompt). If unset, the handler will use. | 	// in the username/password prompt). If unset, the handler will use. | ||||||
| 	// "Username". | 	// "Username". | ||||||
| @@ -368,6 +374,19 @@ func (c *crowdConnector) identityFromCrowdUser(user crowdUser) (connector.Identi | |||||||
| 		EmailVerified: true, | 		EmailVerified: true, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	switch c.PreferredUsernameField { | ||||||
|  | 	case "key": | ||||||
|  | 		identity.PreferredUsername = user.Key | ||||||
|  | 	case "name": | ||||||
|  | 		identity.PreferredUsername = user.Name | ||||||
|  | 	case "email": | ||||||
|  | 		identity.PreferredUsername = user.Email | ||||||
|  | 	default: | ||||||
|  | 		if c.PreferredUsernameField != "" { | ||||||
|  | 			c.logger.Warnf("preferred_username left empty. Invalid crowd field mapped to preferred_username: %s", c.PreferredUsernameField) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return identity, nil | 	return identity, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -104,6 +104,53 @@ func TestUserPassword(t *testing.T) { | |||||||
| 	expectNil(t, err) | 	expectNil(t, err) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestIdentityFromCrowdUser(t *testing.T) { | ||||||
|  | 	user := crowdUser{ | ||||||
|  | 		Key:    "12345", | ||||||
|  | 		Name:   "testuser", | ||||||
|  | 		Active: true, | ||||||
|  | 		Email:  "testuser@example.com", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c := newTestCrowdConnector("/") | ||||||
|  |  | ||||||
|  | 	// Sanity checks | ||||||
|  | 	expectEquals(t, user.Name, "testuser") | ||||||
|  | 	expectEquals(t, user.Email, "testuser@example.com") | ||||||
|  |  | ||||||
|  | 	// Test unconfigured behaviour | ||||||
|  | 	i, err := c.identityFromCrowdUser(user) | ||||||
|  | 	expectNil(t, err) | ||||||
|  | 	expectEquals(t, i.UserID, "12345") | ||||||
|  | 	expectEquals(t, i.Username, "testuser") | ||||||
|  | 	expectEquals(t, i.Email, "testuser@example.com") | ||||||
|  | 	expectEquals(t, i.EmailVerified, true) | ||||||
|  |  | ||||||
|  | 	// Test for various PreferredUsernameField settings | ||||||
|  | 	// unset | ||||||
|  | 	expectEquals(t, i.PreferredUsername, "") | ||||||
|  |  | ||||||
|  | 	c.Config.PreferredUsernameField = "key" | ||||||
|  | 	i, err = c.identityFromCrowdUser(user) | ||||||
|  | 	expectNil(t, err) | ||||||
|  | 	expectEquals(t, i.PreferredUsername, "12345") | ||||||
|  |  | ||||||
|  | 	c.Config.PreferredUsernameField = "name" | ||||||
|  | 	i, err = c.identityFromCrowdUser(user) | ||||||
|  | 	expectNil(t, err) | ||||||
|  | 	expectEquals(t, i.PreferredUsername, "testuser") | ||||||
|  |  | ||||||
|  | 	c.Config.PreferredUsernameField = "email" | ||||||
|  | 	i, err = c.identityFromCrowdUser(user) | ||||||
|  | 	expectNil(t, err) | ||||||
|  | 	expectEquals(t, i.PreferredUsername, "testuser@example.com") | ||||||
|  |  | ||||||
|  | 	c.Config.PreferredUsernameField = "invalidstring" | ||||||
|  | 	i, err = c.identityFromCrowdUser(user) | ||||||
|  | 	expectNil(t, err) | ||||||
|  | 	expectEquals(t, i.PreferredUsername, "") | ||||||
|  | } | ||||||
|  |  | ||||||
| type TestServerResponse struct { | type TestServerResponse struct { | ||||||
| 	Body interface{} | 	Body interface{} | ||||||
| 	Code int | 	Code int | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user