hardcoded saml mappers
This commit is contained in:
parent
7ba0681731
commit
d4468913dd
8 changed files with 225 additions and 10 deletions
|
@ -73,14 +73,14 @@ public class AttributeStatementHelper {
|
|||
|
||||
}
|
||||
public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute, String samlAttributeName, String nameFormat, String friendlyName, boolean consentRequired, String consentText, String mapperId) {
|
||||
ProtocolMapperModel mapper = mapper = new ProtocolMapperModel();
|
||||
ProtocolMapperModel mapper = new ProtocolMapperModel();
|
||||
mapper.setName(name);
|
||||
mapper.setProtocolMapper(mapperId);
|
||||
mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
|
||||
mapper.setConsentRequired(consentRequired);
|
||||
mapper.setConsentText(consentText);
|
||||
Map<String, String> config = new HashMap<String, String>();
|
||||
config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
|
||||
if (userAttribute != null) config.put(ProtocolMapperUtils.USER_ATTRIBUTE, userAttribute);
|
||||
config.put(SAML_ATTRIBUTE_NAME, samlAttributeName);
|
||||
if (friendlyName != null) {
|
||||
config.put(FRIENDLY_NAME, friendlyName);
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package org.keycloak.protocol.saml.mappers;
|
||||
|
||||
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.picketlink.identity.federation.saml.v2.assertion.AttributeStatementType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper implements SAMLAttributeStatementMapper {
|
||||
public static final String PROVIDER_ID = "saml-hardcode-attribute-mapper";
|
||||
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
||||
|
||||
static {
|
||||
ConfigProperty property;
|
||||
property = new ConfigProperty();
|
||||
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
|
||||
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
|
||||
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
|
||||
configProperties.add(property);
|
||||
AttributeStatementHelper.setConfigProperties(configProperties);
|
||||
property = new ConfigProperty();
|
||||
property.setName(ATTRIBUTE_VALUE);
|
||||
property.setLabel("Attribute value");
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
property.setHelpText("Value of the attribute you want to hard code.");
|
||||
configProperties.add(property);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<ConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
}
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "Hardcoded attribute";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCategory() {
|
||||
return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "Hardcode an attribute into the SAML Assertion.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
|
||||
String attributeValue = mappingModel.getConfig().get(ATTRIBUTE_VALUE);
|
||||
AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue);
|
||||
|
||||
}
|
||||
|
||||
public static ProtocolMapperModel create(String name,
|
||||
String samlAttributeName, String nameFormat, String friendlyName, String value,
|
||||
boolean consentRequired, String consentText) {
|
||||
String mapperId = PROVIDER_ID;
|
||||
ProtocolMapperModel model = AttributeStatementHelper.createAttributeMapper(name, null, samlAttributeName, nameFormat, friendlyName,
|
||||
consentRequired, consentText, mapperId);
|
||||
model.getConfig().put(ATTRIBUTE_VALUE, value);
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package org.keycloak.protocol.saml.mappers;
|
||||
|
||||
import org.keycloak.models.ClientSessionModel;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ProtocolMapperModel;
|
||||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.ProtocolMapperUtils;
|
||||
import org.keycloak.protocol.saml.SamlProtocol;
|
||||
import org.picketlink.identity.federation.saml.v2.assertion.AttributeStatementType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Mappings UserModel property (the property name of a getter method) to an AttributeStatement.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class HardcodedRole extends AbstractSAMLProtocolMapper {
|
||||
public static final String PROVIDER_ID = "saml-hardcode-role-mapper";
|
||||
public static final String ATTRIBUTE_VALUE = "attribute.value";
|
||||
private static final List<ConfigProperty> configProperties = new ArrayList<ConfigProperty>();
|
||||
|
||||
static {
|
||||
ConfigProperty property;
|
||||
property = new ConfigProperty();
|
||||
property.setName("role");
|
||||
property.setLabel("Role");
|
||||
property.setHelpText("Role name you want to hardcode.");
|
||||
property.setType(ConfigProperty.STRING_TYPE);
|
||||
configProperties.add(property);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public List<ConfigProperty> getConfigProperties() {
|
||||
return configProperties;
|
||||
}
|
||||
@Override
|
||||
public String getId() {
|
||||
return PROVIDER_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "Hardcoded role";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayCategory() {
|
||||
return AttributeStatementHelper.ATTRIBUTE_STATEMENT_CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHelpText() {
|
||||
return "Hardcode role into SAML Assertion.";
|
||||
}
|
||||
|
||||
public static ProtocolMapperModel create(String name,
|
||||
String role) {
|
||||
String mapperId = PROVIDER_ID;
|
||||
ProtocolMapperModel mapper = new ProtocolMapperModel();
|
||||
mapper.setName(name);
|
||||
mapper.setProtocolMapper(mapperId);
|
||||
mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
|
||||
Map<String, String> config = new HashMap<String, String>();
|
||||
config.put("role", role);
|
||||
mapper.setConfig(config);
|
||||
return mapper;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -14,6 +14,7 @@ import org.picketlink.identity.federation.saml.v2.assertion.AttributeType;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -92,17 +93,33 @@ public class SAMLBasicRoleListMapper extends AbstractSAMLProtocolMapper implemen
|
|||
String single = mappingModel.getConfig().get(SINGLE_ROLE_ATTRIBUTE);
|
||||
boolean singleAttribute = Boolean.parseBoolean(single);
|
||||
|
||||
Map<ProtocolMapperModel, SAMLRoleNameMapper> roleNameMappers = new HashMap<>();
|
||||
List<SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper>> roleNameMappers = new LinkedList<>();
|
||||
KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
|
||||
AttributeType singleAttributeType = null;
|
||||
for (ProtocolMapperModel mapping : clientSession.getClient().getProtocolMappers()) {
|
||||
if (!mapping.getProtocol().equals(SamlProtocol.LOGIN_PROTOCOL)) continue;
|
||||
|
||||
ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
|
||||
if (mapper == null || !(mapper instanceof SAMLRoleNameMapper)) continue;
|
||||
roleNameMappers.put(mapping, (SAMLRoleNameMapper)mapper);
|
||||
if (mapper == null) continue;
|
||||
if (mapper instanceof SAMLRoleNameMapper) {
|
||||
roleNameMappers.add(new SamlProtocol.ProtocolMapperProcessor<>((SAMLRoleNameMapper) mapper,mapping));
|
||||
}
|
||||
if (mapper instanceof HardcodedRole) {
|
||||
AttributeType attributeType = null;
|
||||
if (singleAttribute) {
|
||||
if (singleAttributeType == null) {
|
||||
singleAttributeType = AttributeStatementHelper.createAttributeType(mappingModel);
|
||||
roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(singleAttributeType));
|
||||
}
|
||||
attributeType = singleAttributeType;
|
||||
} else {
|
||||
attributeType = AttributeStatementHelper.createAttributeType(mappingModel);
|
||||
roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
|
||||
}
|
||||
attributeType.addAttributeValue(mapping.getConfig().get("role"));
|
||||
}
|
||||
}
|
||||
|
||||
AttributeType singleAttributeType = null;
|
||||
for (String roleId : clientSession.getRoles()) {
|
||||
// todo need a role mapping
|
||||
RoleModel roleModel = clientSession.getRealm().getRoleById(roleId);
|
||||
|
@ -118,8 +135,8 @@ public class SAMLBasicRoleListMapper extends AbstractSAMLProtocolMapper implemen
|
|||
roleAttributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attributeType));
|
||||
}
|
||||
String roleName = roleModel.getName();
|
||||
for (Map.Entry<ProtocolMapperModel, SAMLRoleNameMapper> entry : roleNameMappers.entrySet()) {
|
||||
String newName = entry.getValue().mapName(entry.getKey(), roleModel);
|
||||
for (SamlProtocol.ProtocolMapperProcessor<SAMLRoleNameMapper> entry : roleNameMappers) {
|
||||
String newName = entry.mapper.mapName(entry.model, roleModel);
|
||||
if (newName != null) {
|
||||
roleName = newName;
|
||||
break;
|
||||
|
|
|
@ -5,9 +5,12 @@ import org.keycloak.models.ProtocolMapperModel;
|
|||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
|
||||
import org.keycloak.protocol.saml.SamlProtocol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Map an assigned role to a different position and name in the token
|
||||
|
@ -88,4 +91,21 @@ public class SAMLBasicRoleNameMapper extends AbstractOIDCProtocolMapper implemen
|
|||
if (roleModel.getName().equals(role)) return newName;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ProtocolMapperModel create(String name,
|
||||
String role,
|
||||
String newName) {
|
||||
String mapperId = PROVIDER_ID;
|
||||
ProtocolMapperModel mapper = new ProtocolMapperModel();
|
||||
mapper.setName(name);
|
||||
mapper.setProtocolMapper(mapperId);
|
||||
mapper.setProtocol(SamlProtocol.LOGIN_PROTOCOL);
|
||||
Map<String, String> config = new HashMap<String, String>();
|
||||
config.put(ROLE_CONFIG, role);
|
||||
config.put(NEW_ROLE_NAME, newName);
|
||||
mapper.setConfig(config);
|
||||
return mapper;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
org.keycloak.protocol.saml.mappers.SAMLBasicRoleListMapper
|
||||
org.keycloak.protocol.saml.mappers.SAMLBasicRoleNameMapper
|
||||
org.keycloak.protocol.saml.mappers.HardcodedRole
|
||||
org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper
|
||||
org.keycloak.protocol.saml.mappers.UserAttributeStatementMapper
|
||||
org.keycloak.protocol.saml.mappers.UserPropertyAttributeStatementMapper
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class OIDCAddClaimMapper extends AbstractOIDCProtocolMapper implements OI
|
|||
|
||||
@Override
|
||||
public String getDisplayType() {
|
||||
return "Hard coded claim";
|
||||
return "Hardcoded claim";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,7 +16,10 @@ import org.keycloak.models.UserModel;
|
|||
import org.keycloak.models.UserSessionModel;
|
||||
import org.keycloak.protocol.oidc.TokenManager;
|
||||
import org.keycloak.protocol.saml.mappers.AttributeStatementHelper;
|
||||
import org.keycloak.protocol.saml.mappers.HardcodedAttributeMapper;
|
||||
import org.keycloak.protocol.saml.mappers.HardcodedRole;
|
||||
import org.keycloak.protocol.saml.mappers.SAMLBasicRoleListMapper;
|
||||
import org.keycloak.protocol.saml.mappers.SAMLBasicRoleNameMapper;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.resources.admin.AdminRoot;
|
||||
|
@ -265,6 +268,9 @@ public class SamlBindingTest {
|
|||
app.addProtocolMapper(mapper);
|
||||
}
|
||||
}
|
||||
app.addProtocolMapper(HardcodedAttributeMapper.create("hardcoded-attribute", "hardcoded-attribute", "Basic", null, "hard", false, null));
|
||||
app.addProtocolMapper(HardcodedRole.create("hardcoded-role", "hardcoded-role"));
|
||||
app.addProtocolMapper(SAMLBasicRoleNameMapper.create("renamed-role","manager", "el-jefe"));
|
||||
}
|
||||
}, "demo");
|
||||
|
||||
|
@ -287,6 +293,8 @@ public class SamlBindingTest {
|
|||
boolean userRole = false;
|
||||
boolean managerRole = false;
|
||||
boolean single = false;
|
||||
boolean hardcodedRole = false;
|
||||
boolean hardcodedAttribute = false;
|
||||
for (AttributeStatementType statement : assertion.getAttributeStatements()) {
|
||||
for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
|
||||
AttributeType attr = choice.getAttribute();
|
||||
|
@ -294,14 +302,21 @@ public class SamlBindingTest {
|
|||
if (single) Assert.fail("too many role attributes");
|
||||
single = true;
|
||||
for (Object value : attr.getAttributeValue()) {
|
||||
if (value.equals("manager")) managerRole = true;
|
||||
if (value.equals("el-jefe")) managerRole = true;
|
||||
if (value.equals("user")) userRole = true;
|
||||
if (value.equals("hardcoded-role")) hardcodedRole = true;
|
||||
}
|
||||
} else if (attr.getName().equals("hardcoded-attribute")) {
|
||||
hardcodedAttribute = true;
|
||||
Assert.assertEquals(attr.getAttributeValue().get(0), "hard");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Assert.assertTrue(single);
|
||||
Assert.assertTrue(hardcodedAttribute);
|
||||
Assert.assertTrue(hardcodedRole);
|
||||
Assert.assertTrue(userRole);
|
||||
Assert.assertTrue(managerRole);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue