diff --git a/Documentation/connectors/atlassian-crowd.md b/Documentation/connectors/atlassian-crowd.md
index 3a5f071291edd609b80a92bcdc4580c5994df399..8dbaef80d921ca6e8e574eefa5f038842943419e 100644
--- a/Documentation/connectors/atlassian-crowd.md
+++ b/Documentation/connectors/atlassian-crowd.md
@@ -36,4 +36,9 @@ connectors:
     - my-group
     # Prompt for username field.
     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
 ```
diff --git a/README.md b/README.md
index 65384cdad9ff6e865095d6a49798e4bc8e0d4ee1..bbfb4f2954dbbdb13d896baaf6fd16db589a0345 100644
--- a/README.md
+++ b/README.md
@@ -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. |
 | [Bitbucket Cloud](Documentation/connectors/bitbucketcloud.md) | yes | yes | no | alpha | |
 | [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:
 
diff --git a/connector/atlassiancrowd/atlassiancrowd.go b/connector/atlassiancrowd/atlassiancrowd.go
index d835d4cf91155286e0d852530f9f4e8bd44e75fd..928e69a6db9fb433e5376e9bb4b962b2a99ccd66 100644
--- a/connector/atlassiancrowd/atlassiancrowd.go
+++ b/connector/atlassiancrowd/atlassiancrowd.go
@@ -35,6 +35,7 @@ import (
 //       - admin
 //       # Prompt for username field
 //       usernamePrompt: Login
+//		 preferredUsernameField: name
 //
 type Config struct {
 	BaseURL      string   `json:"baseURL"`
@@ -42,6 +43,11 @@ type Config struct {
 	ClientSecret string   `json:"clientSecret"`
 	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
 	// in the username/password prompt). If unset, the handler will use.
 	// "Username".
@@ -368,6 +374,19 @@ func (c *crowdConnector) identityFromCrowdUser(user crowdUser) (connector.Identi
 		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
 }
 
diff --git a/connector/atlassiancrowd/atlassiancrowd_test.go b/connector/atlassiancrowd/atlassiancrowd_test.go
index 966f5b6f5435226a6d78cb3c5f7602007781f8e1..213c1829fd062f3bcf02939c61155d219782c03e 100644
--- a/connector/atlassiancrowd/atlassiancrowd_test.go
+++ b/connector/atlassiancrowd/atlassiancrowd_test.go
@@ -104,6 +104,53 @@ func TestUserPassword(t *testing.T) {
 	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 {
 	Body interface{}
 	Code int