diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
index e2fe9fdcf9..c16516136e 100755
--- a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
+++ b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java
@@ -18,7 +18,7 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder;
"allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password",
"client-keystore", "client-keystore-password", "client-key-password",
"auth-server-url-for-backend-requests", "always-refresh-token",
- "register-node-at-startup", "register-node-period", "token-store"
+ "register-node-at-startup", "register-node-period", "token-store", "principal-attribute"
})
public class AdapterConfig extends BaseAdapterConfig {
@@ -48,6 +48,8 @@ public class AdapterConfig extends BaseAdapterConfig {
protected int registerNodePeriod = -1;
@JsonProperty("token-store")
protected String tokenStore;
+ @JsonProperty("principal-attribute")
+ protected String principalAttribute;
public boolean isAllowAnyHostname() {
return allowAnyHostname;
@@ -152,4 +154,12 @@ public class AdapterConfig extends BaseAdapterConfig {
public void setTokenStore(String tokenStore) {
this.tokenStore = tokenStore;
}
+
+ public String getPrincipalAttribute() {
+ return principalAttribute;
+ }
+
+ public void setPrincipalAttribute(String principalAttribute) {
+ this.principalAttribute = principalAttribute;
+ }
}
diff --git a/docbook/reference/en/en-US/modules/adapter-config.xml b/docbook/reference/en/en-US/modules/adapter-config.xml
index 14c8f293a3..216095fdeb 100755
--- a/docbook/reference/en/en-US/modules/adapter-config.xml
+++ b/docbook/reference/en/en-US/modules/adapter-config.xml
@@ -336,6 +336,15 @@
+
+ principal-attribute
+
+
+ OpenID Connection ID Token attribute to populate the UserPrincipal name with. If token attribute is null, defaults to sub
+ Possible values are sub, preferred_username, email, name, nickname, given_name, family_name.
+
+
+
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java
old mode 100644
new mode 100755
index 6e8b97caa1..10d6630339
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterUtils.java
@@ -59,4 +59,27 @@ public class AdapterUtils {
}
return roles;
}
+
+ public static String getPrincipalName(KeycloakDeployment deployment, AccessToken token) {
+ String attr = "sub";
+ if (deployment.getPrincipalAttribute() != null) attr = deployment.getPrincipalAttribute();
+ String name = null;
+ if ("sub".equals(attr)) {
+ name = token.getSubject();
+ } else if ("email".equals(attr)) {
+ name = token.getEmail();
+ } else if ("preferred_username".equals(attr)) {
+ name = token.getPreferredUsername();
+ } else if ("name".equals(attr)) {
+ name = token.getName();
+ } else if ("given_name".equals(attr)) {
+ name = token.getGivenName();
+ } else if ("family_name".equals(attr)) {
+ name = token.getFamilyName();
+ } else if ("nickname".equals(attr)) {
+ name = token.getNickName();
+ }
+ if (name == null) name = token.getSubject();
+ return name;
+ }
}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java
index 2f0956150b..8a35572097 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/CookieTokenStore.java
@@ -68,7 +68,7 @@ public class CookieTokenStore {
log.debug("Token Verification succeeded!");
RefreshableKeycloakSecurityContext secContext = new RefreshableKeycloakSecurityContext(deployment, tokenStore, accessTokenString, accessToken, idTokenString, idToken, refreshTokenString);
- return new KeycloakPrincipal(accessToken.getSubject(), secContext);
+ return new KeycloakPrincipal(AdapterUtils.getPrincipalName(deployment, accessToken), secContext);
} catch (VerificationException ve) {
log.warn("Failed verify token", ve);
return null;
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
index 2380684f9e..fdd295e1d6 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
@@ -34,6 +34,7 @@ public class KeycloakDeployment {
protected String accountUrl;
protected String registerNodeUrl;
protected String unregisterNodeUrl;
+ protected String principalAttribute = "sub";
protected String resourceName;
protected boolean bearerOnly;
@@ -333,4 +334,12 @@ public class KeycloakDeployment {
public void setRegisterNodePeriod(int registerNodePeriod) {
this.registerNodePeriod = registerNodePeriod;
}
+
+ public String getPrincipalAttribute() {
+ return principalAttribute;
+ }
+
+ public void setPrincipalAttribute(String principalAttribute) {
+ this.principalAttribute = principalAttribute;
+ }
}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
index c79d90568d..8d8eed955c 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
@@ -54,6 +54,7 @@ public class KeycloakDeploymentBuilder {
} else {
deployment.setTokenStore(TokenStore.SESSION);
}
+ if (adapterConfig.getPrincipalAttribute() != null) deployment.setPrincipalAttribute(adapterConfig.getPrincipalAttribute());
deployment.setResourceCredentials(adapterConfig.getCredentials());
deployment.setPublicClient(adapterConfig.isPublicClient());
deployment.setUseResourceRoleMappings(adapterConfig.isUseResourceRoleMappings());
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
index a4da6a2842..d5c7119821 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RequestAuthenticator.java
@@ -106,7 +106,7 @@ public abstract class RequestAuthenticator {
protected void completeAuthentication(OAuthRequestAuthenticator oauth) {
RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, tokenStore, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken());
- final KeycloakPrincipal principal = new KeycloakPrincipal(oauth.getToken().getSubject(), session);
+ final KeycloakPrincipal principal = new KeycloakPrincipal(AdapterUtils.getPrincipalName(deployment, oauth.getToken()), session);
completeOAuthAuthentication(principal);
}
@@ -116,7 +116,7 @@ public abstract class RequestAuthenticator {
protected void completeAuthentication(BearerTokenRequestAuthenticator bearer) {
RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, null, bearer.getTokenString(), bearer.getToken(), null, null, null);
- final KeycloakPrincipal principal = new KeycloakPrincipal(bearer.getToken().getSubject(), session);
+ final KeycloakPrincipal principal = new KeycloakPrincipal(AdapterUtils.getPrincipalName(deployment, bearer.getToken()), session);
completeBearerAuthentication(principal);
}
diff --git a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java
index 93e5e86d6b..f19d4d0ee9 100755
--- a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java
+++ b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java
@@ -130,6 +130,42 @@ public class SharedAttributeDefinitons {
.setAllowExpression(true)
.setDefaultValue(new ModelNode(false))
.build();
+ protected static final SimpleAttributeDefinition AUTH_SERVER_URL_FOR_BACKEND_REQUESTS =
+ new SimpleAttributeDefinitionBuilder("auth-server-url-for-backend-requests", ModelType.STRING, true)
+ .setXmlName("auth-server-url-for-backend-requests")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
+ protected static final SimpleAttributeDefinition ALWAYS_REFRESH_TOKEN =
+ new SimpleAttributeDefinitionBuilder("always-refresh-token", ModelType.BOOLEAN, true)
+ .setXmlName("always-refresh-token")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition REGISTER_NODE_AT_STARTUP =
+ new SimpleAttributeDefinitionBuilder("register-node-at-startup", ModelType.BOOLEAN, true)
+ .setXmlName("register-node-at-startup")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition REGISTER_NODE_PERIOD =
+ new SimpleAttributeDefinitionBuilder("register-node-period", ModelType.INT, true)
+ .setXmlName("register-node-period")
+ .setAllowExpression(true)
+ .setValidator(new IntRangeValidator(-1, true))
+ .build();
+ protected static final SimpleAttributeDefinition TOKEN_STORE =
+ new SimpleAttributeDefinitionBuilder("token-store", ModelType.STRING, true)
+ .setXmlName("token-store")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
+ protected static final SimpleAttributeDefinition PRINCIPAL_ATTRIBUTE =
+ new SimpleAttributeDefinitionBuilder("principal-attribute", ModelType.STRING, true)
+ .setXmlName("principal-attribute")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
protected static final List ATTRIBUTES = new ArrayList();
@@ -150,6 +186,12 @@ public class SharedAttributeDefinitons {
ATTRIBUTES.add(CORS_ALLOWED_HEADERS);
ATTRIBUTES.add(CORS_ALLOWED_METHODS);
ATTRIBUTES.add(EXPOSE_TOKEN);
+ ATTRIBUTES.add(AUTH_SERVER_URL_FOR_BACKEND_REQUESTS);
+ ATTRIBUTES.add(ALWAYS_REFRESH_TOKEN);
+ ATTRIBUTES.add(REGISTER_NODE_AT_STARTUP);
+ ATTRIBUTES.add(REGISTER_NODE_PERIOD);
+ ATTRIBUTES.add(TOKEN_STORE);
+ ATTRIBUTES.add(PRINCIPAL_ATTRIBUTE);
}
/**
diff --git a/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties b/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
index 42435c3558..e95b6cd019 100755
--- a/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
+++ b/integration/as7-eap-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
@@ -23,6 +23,12 @@ keycloak.realm.cors-max-age=CORS max-age header
keycloak.realm.cors-allowed-headers=CORS allowed headers
keycloak.realm.cors-allowed-methods=CORS allowed methods
keycloak.realm.expose-token=Enable secure URL that exposes access token
+keycloak.realm.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
+keycloak.realm.always-refresh-token=Refresh token on every single web request
+keycloak.realm.register-node-at-startup=Cluster setting
+keycloak.realm.register-node-period=how often to re-register node
+keycloak.realm.token-store=cookie or session storage for auth session data
+keycloak.realm.principal-attribute=token attribute to use to set Principal name
keycloak.secure-deployment=A deployment secured by Keycloak
keycloak.secure-deployment.add=Add a deployment to be secured by Keycloak
@@ -49,6 +55,12 @@ keycloak.secure-deployment.cors-max-age=CORS max-age header
keycloak.secure-deployment.cors-allowed-headers=CORS allowed headers
keycloak.secure-deployment.cors-allowed-methods=CORS allowed methods
keycloak.secure-deployment.expose-token=Enable secure URL that exposes access token
+keycloak.secure-deployment.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
+keycloak.secure-deployment.always-refresh-token=Refresh token on every single web request
+keycloak.secure-deployment.register-node-at-startup=Cluster setting
+keycloak.secure-deployment.register-node-period=how often to re-register node
+keycloak.secure-deployment.token-store=cookie or session storage for auth session data
+keycloak.secure-deployment.principal-attribute=token attribute to use to set Principal name
keycloak.secure-deployment.credential=Credential value
diff --git a/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd b/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd
index 3e79c4f929..6afc3f1bbb 100755
--- a/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd
+++ b/integration/as7-eap-subsystem/src/main/resources/schema/keycloak_1_0.xsd
@@ -83,6 +83,12 @@
+
+
+
+
+
+
diff --git a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java
index 93e5e86d6b..1b3c48f0d0 100755
--- a/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java
+++ b/integration/wildfly-subsystem/src/main/java/org/keycloak/subsystem/extension/SharedAttributeDefinitons.java
@@ -126,10 +126,47 @@ public class SharedAttributeDefinitons {
.build();
protected static final SimpleAttributeDefinition EXPOSE_TOKEN =
new SimpleAttributeDefinitionBuilder("expose-token", ModelType.BOOLEAN, true)
- .setXmlName("expose-token")
- .setAllowExpression(true)
- .setDefaultValue(new ModelNode(false))
- .build();
+ .setXmlName("expose-token")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition AUTH_SERVER_URL_FOR_BACKEND_REQUESTS =
+ new SimpleAttributeDefinitionBuilder("auth-server-url-for-backend-requests", ModelType.STRING, true)
+ .setXmlName("auth-server-url-for-backend-requests")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
+ protected static final SimpleAttributeDefinition ALWAYS_REFRESH_TOKEN =
+ new SimpleAttributeDefinitionBuilder("always-refresh-token", ModelType.BOOLEAN, true)
+ .setXmlName("always-refresh-token")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition REGISTER_NODE_AT_STARTUP =
+ new SimpleAttributeDefinitionBuilder("register-node-at-startup", ModelType.BOOLEAN, true)
+ .setXmlName("register-node-at-startup")
+ .setAllowExpression(true)
+ .setDefaultValue(new ModelNode(false))
+ .build();
+ protected static final SimpleAttributeDefinition REGISTER_NODE_PERIOD =
+ new SimpleAttributeDefinitionBuilder("register-node-period", ModelType.INT, true)
+ .setXmlName("register-node-period")
+ .setAllowExpression(true)
+ .setValidator(new IntRangeValidator(-1, true))
+ .build();
+ protected static final SimpleAttributeDefinition TOKEN_STORE =
+ new SimpleAttributeDefinitionBuilder("token-store", ModelType.STRING, true)
+ .setXmlName("token-store")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
+ protected static final SimpleAttributeDefinition PRINCIPAL_ATTRIBUTE =
+ new SimpleAttributeDefinitionBuilder("principal-attribute", ModelType.STRING, true)
+ .setXmlName("principal-attribute")
+ .setAllowExpression(true)
+ .setValidator(new StringLengthValidator(1, Integer.MAX_VALUE, true, true))
+ .build();
+
protected static final List ATTRIBUTES = new ArrayList();
@@ -150,6 +187,12 @@ public class SharedAttributeDefinitons {
ATTRIBUTES.add(CORS_ALLOWED_HEADERS);
ATTRIBUTES.add(CORS_ALLOWED_METHODS);
ATTRIBUTES.add(EXPOSE_TOKEN);
+ ATTRIBUTES.add(AUTH_SERVER_URL_FOR_BACKEND_REQUESTS);
+ ATTRIBUTES.add(ALWAYS_REFRESH_TOKEN);
+ ATTRIBUTES.add(REGISTER_NODE_AT_STARTUP);
+ ATTRIBUTES.add(REGISTER_NODE_PERIOD);
+ ATTRIBUTES.add(TOKEN_STORE);
+ ATTRIBUTES.add(PRINCIPAL_ATTRIBUTE);
}
/**
diff --git a/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties b/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
index 30a063ad38..524ae4d60c 100755
--- a/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
+++ b/integration/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/extension/LocalDescriptions.properties
@@ -23,6 +23,13 @@ keycloak.realm.cors-max-age=CORS max-age header
keycloak.realm.cors-allowed-headers=CORS allowed headers
keycloak.realm.cors-allowed-methods=CORS allowed methods
keycloak.realm.expose-token=Enable secure URL that exposes access token
+keycloak.realm.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
+keycloak.realm.always-refresh-token=Refresh token on every single web request
+keycloak.realm.register-node-at-startup=Cluster setting
+keycloak.realm.register-node-period=how often to re-register node
+keycloak.realm.token-store=cookie or session storage for auth session data
+keycloak.realm.principal-attribute=token attribute to use to set Principal name
+
keycloak.secure-deployment=A deployment secured by Keycloak
keycloak.secure-deployment.add=Add a deployment to be secured by Keycloak
@@ -49,6 +56,12 @@ keycloak.secure-deployment.cors-max-age=CORS max-age header
keycloak.secure-deployment.cors-allowed-headers=CORS allowed headers
keycloak.secure-deployment.cors-allowed-methods=CORS allowed methods
keycloak.secure-deployment.expose-token=Enable secure URL that exposes access token
+keycloak.secure-deployment.auth-server-url-for-backend-requests=URL to use to make background calls to auth server
+keycloak.secure-deployment.always-refresh-token=Refresh token on every single web request
+keycloak.secure-deployment.register-node-at-startup=Cluster setting
+keycloak.secure-deployment.register-node-period=how often to re-register node
+keycloak.secure-deployment.token-store=cookie or session storage for auth session data
+keycloak.secure-deployment.principal-attribute=token attribute to use to set Principal name
keycloak.secure-deployment.credential=Credential value
diff --git a/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd b/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd
index 8a9979b661..ff7c16e8d5 100755
--- a/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd
+++ b/integration/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak_1_0.xsd
@@ -42,6 +42,12 @@
+
+
+
+
+
+
@@ -74,6 +80,12 @@
+
+
+
+
+
+