commit
fbf62b2a63
8 changed files with 278 additions and 1 deletions
|
@ -17,6 +17,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.broker.provider;
|
package org.keycloak.broker.provider;
|
||||||
|
|
||||||
|
import org.keycloak.models.ClientSessionModel;
|
||||||
import org.keycloak.models.IdentityProviderModel;
|
import org.keycloak.models.IdentityProviderModel;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -43,6 +44,7 @@ public class BrokeredIdentityContext {
|
||||||
private IdentityProviderModel idpConfig;
|
private IdentityProviderModel idpConfig;
|
||||||
private IdentityProvider idp;
|
private IdentityProvider idp;
|
||||||
private Map<String, Object> contextData = new HashMap<>();
|
private Map<String, Object> contextData = new HashMap<>();
|
||||||
|
private ClientSessionModel clientSession;
|
||||||
|
|
||||||
public BrokeredIdentityContext(String id) {
|
public BrokeredIdentityContext(String id) {
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
|
@ -166,6 +168,14 @@ public class BrokeredIdentityContext {
|
||||||
this.lastName = lastName;
|
this.lastName = lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ClientSessionModel getClientSession() {
|
||||||
|
return clientSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientSession(ClientSessionModel clientSession) {
|
||||||
|
this.clientSession = clientSession;
|
||||||
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
int i = name.lastIndexOf(' ');
|
int i = name.lastIndexOf(' ');
|
||||||
|
|
|
@ -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.";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,3 @@
|
||||||
org.keycloak.broker.provider.HardcodedRoleMapper
|
org.keycloak.broker.provider.HardcodedRoleMapper
|
||||||
|
org.keycloak.broker.provider.HardcodedAttributeMapper
|
||||||
|
org.keycloak.broker.provider.HardcodedUserSessionAttributeMapper
|
|
@ -1264,6 +1264,24 @@ keycloak.createLoginUrl({
|
||||||
JSON structure in Keycloak log file.
|
JSON structure in Keycloak log file.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</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>
|
<section>
|
||||||
<title>Examples</title>
|
<title>Examples</title>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,5 +4,6 @@ org.keycloak.protocol.saml.mappers.HardcodedRole
|
||||||
org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper
|
org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper
|
||||||
org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper
|
org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper
|
||||||
org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper
|
org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper
|
||||||
|
org.keycloak.protocol.saml.mappers.UserSessionNoteStatementMapper
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,7 @@ public class IdentityBrokerService implements IdentityProvider.AuthenticationCal
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientSessionModel clientSession = clientCode.getClientSession();
|
ClientSessionModel clientSession = clientCode.getClientSession();
|
||||||
|
context.setClientSession(clientSession);
|
||||||
|
|
||||||
session.getContext().setClient(clientSession.getClient());
|
session.getContext().setClient(clientSession.getClient());
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue