keycloak-memoizeit
Changes
broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper 1(+1 -0)
Details
diff --git a/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/RoleMapper.java b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/RoleMapper.java
new file mode 100755
index 0000000..3c6d655
--- /dev/null
+++ b/broker/saml/src/main/java/org/keycloak/broker/saml/mappers/RoleMapper.java
@@ -0,0 +1,167 @@
+package org.keycloak.broker.saml.mappers;
+
+import org.keycloak.broker.provider.AbstractIdentityProviderMapper;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.broker.saml.SAMLEndpoint;
+import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
+import org.keycloak.dom.saml.v2.assertion.AssertionType;
+import org.keycloak.dom.saml.v2.assertion.AttributeStatementType;
+import org.keycloak.dom.saml.v2.assertion.AttributeType;
+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 org.keycloak.representations.JsonWebToken;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class RoleMapper extends AbstractIdentityProviderMapper {
+
+ public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID};
+
+ private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
+
+ public static final String ROLE = "role";
+ public static final String ATTRIBUTE_NAME = "attribute.name";
+ public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name";
+ public static final String ATTRIBUTE_VALUE = "attribute.value";
+
+ static {
+ ProviderConfigProperty property;
+ property = new ProviderConfigProperty();
+ property.setName(ATTRIBUTE_NAME);
+ property.setLabel("Attribute Name");
+ property.setHelpText("Name of attribute to search for in assertion. You can leave this blank and specify a friendly name instead.");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ property = new ProviderConfigProperty();
+ property.setName(ATTRIBUTE_FRIENDLY_NAME);
+ property.setLabel("Attribute Name");
+ property.setHelpText("Friendly name of attribute to search for in assertion. You can leave this blank and specify a name instead.");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ property = new ProviderConfigProperty();
+ property.setName(ATTRIBUTE_VALUE);
+ property.setLabel("Attribute Value");
+ property.setHelpText("Value the attribute must have. If the attribute is a list, then the value must be contained in the list.");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ property = new ProviderConfigProperty();
+ property.setName(ROLE);
+ property.setLabel("Role");
+ property.setHelpText("Role to grant to user. To reference an application role the syntax is appname.approle, i.e. myapp.myrole");
+ property.setType(ProviderConfigProperty.STRING_TYPE);
+ configProperties.add(property);
+ }
+
+ public static final String PROVIDER_ID = "saml-role-idp-mapper";
+
+ public static String[] parseRole(String role) {
+ int scopeIndex = role.indexOf('.');
+ if (scopeIndex > -1) {
+ String appName = role.substring(0, scopeIndex);
+ role = role.substring(scopeIndex + 1);
+ String[] rtn = {appName, role};
+ return rtn;
+ } else {
+ String[] rtn = {null, role};
+ return rtn;
+
+ }
+ }
+
+ @Override
+ public List<ProviderConfigProperty> getConfigProperties() {
+ return configProperties;
+ }
+
+ @Override
+ public String getId() {
+ return PROVIDER_ID;
+ }
+
+ @Override
+ public String[] getCompatibleProviders() {
+ return COMPATIBLE_PROVIDERS;
+ }
+
+ @Override
+ public String getDisplayCategory() {
+ return "Role Mapper";
+ }
+
+ @Override
+ public String getDisplayType() {
+ return "Role Mapper";
+ }
+
+ @Override
+ public void importNewUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+ String roleName = mapperModel.getConfig().get(ROLE);
+ if (isAttributePresent(mapperModel, context)) {
+ RoleModel role = getRoleFromString(realm, roleName);
+ if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+ user.grantRole(role);
+ }
+ }
+
+ protected RoleModel getRoleFromString(RealmModel realm, String roleName) {
+ String[] parsedRole = parseRole(roleName);
+ RoleModel role = null;
+ if (parsedRole[0] == null) {
+ role = realm.getRole(parsedRole[1]);
+ } else {
+ ClientModel client = realm.getClientByClientId(parsedRole[0]);
+ role = client.getRole(parsedRole[1]);
+ }
+ return role;
+ }
+
+ protected boolean isAttributePresent(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+ String name = mapperModel.getConfig().get(ATTRIBUTE_NAME);
+ if (name != null && name.trim().equals("")) name = null;
+ String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME);
+ if (friendly != null && friendly.trim().equals("")) friendly = null;
+ String desiredValue = mapperModel.getConfig().get(ATTRIBUTE_VALUE);
+ AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION);
+ for (AttributeStatementType statement : assertion.getAttributeStatements()) {
+ for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) {
+ AttributeType attr = choice.getAttribute();
+ if (name != null && !name.equals(attr.getName())) continue;
+ if (friendly != null && !name.equals(attr.getFriendlyName())) continue;
+ for (Object val : attr.getAttributeValue()) {
+ if (val.equals(desiredValue)) return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ @Override
+ public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) {
+ String roleName = mapperModel.getConfig().get(ROLE);
+ if (!isAttributePresent(mapperModel, context)) {
+ RoleModel role = getRoleFromString(realm, roleName);
+ if (role == null) throw new IdentityBrokerException("Unable to find role: " + roleName);
+ user.deleteRoleMapping(role);
+ }
+
+ }
+
+ @Override
+ public String getHelpText() {
+ return "If a claim exists, grant the user the specified realm or application role.";
+ }
+
+}
diff --git a/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
new file mode 100755
index 0000000..af14a9c
--- /dev/null
+++ b/broker/saml/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
@@ -0,0 +1 @@
+org.keycloak.broker.saml.mappers.RoleMapper
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
index 3e151fd..ef62c07 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-saml.html
@@ -163,6 +163,7 @@
</fieldset>
<div class="pull-right form-actions">
+ <a data-ng-show="!newIdentityProvider" class="btn btn-lg btn-primary" href="#/realms/{{realm.realm}}/identity-provider-mappers/{{identityProvider.alias}}/mappers">Mappers</a>
<a class="btn btn-lg btn-primary" href="#/realms/{{realm.realm}}/identity-provider-settings/provider/{{identityProvider.providerId}}/{{identityProvider.alias}}/export" data-ng-show="!importFile && !newIdentityProvider">Export</a>
<button kc-save data-ng-show="changed">Save</button>
<button type="submit" data-ng-click="cancel()" data-ng-show="changed" class="btn btn-lg btn-default">Cancel</button>
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
index 1d99e1f..af202b3 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/account/AccountTest.java
@@ -157,7 +157,7 @@ public class AccountTest {
});
}
- //@Test
+ @Test
public void ideTesting() throws Exception {
Thread.sleep(100000000);
}