keycloak-uncached
Changes
broker/core/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java 87(+87 -0)
broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper 4(+3 -1)
saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java 69(+69 -0)
Details
diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java b/broker/core/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java
index f90f803..6052f57 100755
--- a/broker/core/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java
@@ -17,6 +17,7 @@
*/
package org.keycloak.broker.provider;
+import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.IdentityProviderModel;
import java.util.HashMap;
@@ -43,6 +44,7 @@ public class BrokeredIdentityContext {
private IdentityProviderModel idpConfig;
private IdentityProvider idp;
private Map<String, Object> contextData = new HashMap<>();
+ private ClientSessionModel clientSession;
public BrokeredIdentityContext(String id) {
if (id == null) {
@@ -166,6 +168,14 @@ public class BrokeredIdentityContext {
this.lastName = lastName;
}
+ public ClientSessionModel getClientSession() {
+ return clientSession;
+ }
+
+ public void setClientSession(ClientSessionModel clientSession) {
+ this.clientSession = clientSession;
+ }
+
public void setName(String name) {
if (name != null) {
int i = name.lastIndexOf(' ');
diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedAttributeMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedAttributeMapper.java
new file mode 100755
index 0000000..d182d6f
--- /dev/null
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedAttributeMapper.java
@@ -0,0 +1,89 @@
+package org.keycloak.broker.provider;
+
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.RoleModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HardcodedAttributeMapper extends AbstractIdentityProviderMapper {
+ public static final String ATTRIBUTE = "attribute";
+ public static final String ATTRIBUTE_VALUE = "attribute.value";
+ protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+ static {
+ ProviderConfigProperty property;
+ property = new ProviderConfigProperty();
+ property.setName(ATTRIBUTE);
+ property.setLabel("User Attribute");
+ property.setHelpText("Name of user attribute you want to hardcode");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ property = new ProviderConfigProperty();
+ property.setName(ATTRIBUTE_VALUE);
+ property.setLabel("User Attribute Value");
+ property.setHelpText("Value you want to hardcode");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ }
+
+
+
+ @Override
+ public List<ProviderConfigProperty> getConfigProperties() {
+ return configProperties;
+ }
+
+ @Override
+ public String getDisplayCategory() {
+ return "Attribute Importer";
+ }
+
+ @Override
+ public String getDisplayType() {
+ return "Hardcoded Attribute";
+ }
+
+ public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
+
+
+ public static final String PROVIDER_ID = "hardcoded-attribute-idp-mapper";
+
+ @Override
+ public String getId() {
+ return PROVIDER_ID;
+ }
+
+ @Override
+ public String[] getCompatibleProviders() {
+ return COMPATIBLE_PROVIDERS;
+ }
+
+ @Override
+ public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+ String attribute = mapperModel.getConfig().get(ATTRIBUTE);
+ String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
+ user.setSingleAttribute(attribute, attributeValue);
+ }
+
+ @Override
+ public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+ String attribute = mapperModel.getConfig().get(ATTRIBUTE);
+ String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
+ user.setSingleAttribute(attribute, attributeValue);
+ }
+
+ @Override
+ public String getHelpText() {
+ return "When user is imported from provider, hardcode a value to a specific user attribute.";
+ }
+}
diff --git a/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java
new file mode 100755
index 0000000..676e6b1
--- /dev/null
+++ b/broker/core/src/main/java/org/keycloak/broker/provider/HardcodedUserSessionAttributeMapper.java
@@ -0,0 +1,87 @@
+package org.keycloak.broker.provider;
+
+import org.keycloak.models.IdentityProviderMapperModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.RealmModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class HardcodedUserSessionAttributeMapper extends AbstractIdentityProviderMapper {
+ public static final String ATTRIBUTE = "attribute";
+ public static final String ATTRIBUTE_VALUE = "attribute.value";
+ protected static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+ static {
+ ProviderConfigProperty property;
+ property = new ProviderConfigProperty();
+ property.setName(ATTRIBUTE);
+ property.setLabel("User Session Attribute");
+ property.setHelpText("Name of user session attribute you want to hardcode");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ property = new ProviderConfigProperty();
+ property.setName(ATTRIBUTE_VALUE);
+ property.setLabel("User Session Attribute Value");
+ property.setHelpText("Value you want to hardcode");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ }
+
+
+
+ @Override
+ public List<ProviderConfigProperty> getConfigProperties() {
+ return configProperties;
+ }
+
+ @Override
+ public String getDisplayCategory() {
+ return "Attribute Importer";
+ }
+
+ @Override
+ public String getDisplayType() {
+ return "Hardcoded User Session Attribute";
+ }
+
+ public static final String[] COMPATIBLE_PROVIDERS = {ANY_PROVIDER};
+
+
+ public static final String PROVIDER_ID = "hardcoded-user-session-attribute-idp-mapper";
+
+ @Override
+ public String getId() {
+ return PROVIDER_ID;
+ }
+
+ @Override
+ public String[] getCompatibleProviders() {
+ return COMPATIBLE_PROVIDERS;
+ }
+
+ @Override
+ public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+ String attribute = mapperModel.getConfig().get(ATTRIBUTE);
+ String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
+ context.getClientSession().setUserSessionNote(attribute, attributeValue);
+ }
+
+ @Override
+ public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+ String attribute = mapperModel.getConfig().get(ATTRIBUTE);
+ String attributeValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
+ context.getClientSession().setUserSessionNote(attribute, attributeValue);
+ }
+
+ @Override
+ public String getHelpText() {
+ return "When user is imported from provider, hardcode a value to a specific user session attribute.";
+ }
+}
diff --git a/broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
index a3bf053..ef57994 100755
--- a/broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
+++ b/broker/core/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
@@ -1 +1,3 @@
-org.keycloak.broker.provider.HardcodedRoleMapper
\ No newline at end of file
+org.keycloak.broker.provider.HardcodedRoleMapper
+org.keycloak.broker.provider.HardcodedAttributeMapper
+org.keycloak.broker.provider.HardcodedUserSessionAttributeMapper
\ No newline at end of file
diff --git a/docbook/reference/en/en-US/modules/identity-broker.xml b/docbook/reference/en/en-US/modules/identity-broker.xml
index 2288ed7..a262b85 100755
--- a/docbook/reference/en/en-US/modules/identity-broker.xml
+++ b/docbook/reference/en/en-US/modules/identity-broker.xml
@@ -1264,6 +1264,24 @@ keycloak.createLoginUrl({
JSON structure in Keycloak log file.
</para>
</section>
+ <section>
+ <title>User Session Data</title>
+ <para>
+ After a user logs in from the external IDP, there's some additional user session note data that Keycloak stores that you
+ can access. This data can be propagated to the client requesting a login
+ via the token or SAML assertion being passed back to it by using an appropriate client mapper.
+ <variablelist>
+ <varlistentry>
+ <term>BROKER_PROVIDER_ID</term>
+ <listitem>
+ <para>
+ This is the IDP alias of the broker used to perform the login.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+ </section>
<section>
<title>Examples</title>
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java
new file mode 100755
index 0000000..ccf4c1f
--- /dev/null
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/mappers/UserSessionNoteStatementMapper.java
@@ -0,0 +1,69 @@
+package org.keycloak.protocol.saml.mappers;
+
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.models.ClientSessionModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ProtocolMapperModel;
+import org.keycloak.models.UserModel;
+import org.keycloak.models.UserSessionModel;
+import org.keycloak.protocol.ProtocolMapperUtils;
+import org.keycloak.provider.ProviderConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Maps a user session note to a SAML attribute
+ *
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class UserSessionNoteStatementMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
+ private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+ static {
+ ProviderConfigProperty property;
+ property = new ProviderConfigProperty();
+ property.setName("note");
+ property.setLabel("User Session Note Attribute");
+ property.setHelpText("The user session note you want to grab the value from.");
+ configProperties.add(property);
+ AttributeStatementHelper.setConfigProperties(configProperties);
+
+ }
+
+ public static final String PROVIDER_ID = "saml-user-session-note-mapper";
+
+
+ public List<ProviderConfigProperty> getConfigProperties() {
+ return configProperties;
+ }
+ @Override
+ public String getId() {
+ return PROVIDER_ID;
+ }
+
+ @Override
+ public String getDisplayType() {
+ return "User Session Note";
+ }
+
+ @Override
+ public String getDisplayCategory() {
+ return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
+ }
+
+ @Override
+ public String getHelpText() {
+ return "Map a user session note to a SAML attribute.";
+ }
+
+ @Override
+ public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
+ String note = mappingModel.getConfig().get("note");
+ String value = userSession.getNote(note);
+ if (value == null) return;
+ AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, value);
+
+ }
+}
diff --git a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
index 58e10db..163fed5 100755
--- a/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
+++ b/saml/saml-protocol/src/main/resources/META-INF/services/org.keycloak.protocol.ProtocolMapper
@@ -4,5 +4,6 @@ org.keycloak.protocol.saml.mappers.HardcodedRole
org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper
org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper
org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper
+org.keycloak.protocol.saml.mappers.UserSessionNoteStatementMapper
diff --git a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
index beec664..f95d7d8 100755
--- a/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
+++ b/services/src/main/java/org/keycloak/services/resources/IdentityBrokerService.java
@@ -256,6 +256,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
}
ClientSessionModel clientSession = clientCode.getClientSession();
+ context.setClientSession(clientSession);
session.getContext().setClient(clientSession.getClient());