/* * Copyright (c) 2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.carbon.identity.authenticator.saml2.sso; import org.apache.axis2.context.MessageContext; import org.apache.axis2.transport.http.HTTPConstants; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opensaml.saml2.core.Assertion; import org.opensaml.saml2.core.Attribute; import org.opensaml.saml2.core.AttributeStatement; import org.opensaml.saml2.core.Audience; import org.opensaml.saml2.core.AudienceRestriction; import org.opensaml.saml2.core.Conditions; import org.opensaml.saml2.core.Response; import org.opensaml.xml.XMLObject; import org.opensaml.xml.signature.Signature; import org.opensaml.xml.signature.SignatureValidator; import org.opensaml.xml.validation.ValidationException; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; import org.w3c.dom.Element; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.core.security.AuthenticatorsConfiguration; import org.wso2.carbon.core.services.authentication.CarbonServerAuthenticator; import org.wso2.carbon.core.services.util.CarbonAuthenticationUtil; import org.wso2.carbon.core.util.AnonymousSessionUtil; import org.wso2.carbon.core.util.PermissionUpdateUtil; import org.wso2.carbon.identity.authenticator.saml2.sso.common.SAML2SSOAuthenticatorConstants; import org.wso2.carbon.identity.authenticator.saml2.sso.dto.AuthnReqDTO; import org.wso2.carbon.identity.authenticator.saml2.sso.internal.SAML2SSOAuthBEDataHolder; import org.wso2.carbon.identity.authenticator.saml2.sso.util.Util; import org.wso2.carbon.registry.core.service.RegistryService; import org.wso2.carbon.user.core.UserCoreConstants; import org.wso2.carbon.user.core.UserRealm; import org.wso2.carbon.user.core.UserStoreException; import org.wso2.carbon.user.core.UserStoreManager; import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.AuthenticationObserver; import org.wso2.carbon.utils.ServerConstants; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.math.BigInteger; import java.security.SecureRandom; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; public class SAML2SSOAuthenticator implements CarbonServerAuthenticator { public static final Log log = LogFactory.getLog(SAML2SSOAuthenticator.class); private static final Log AUDIT_LOG = CarbonConstants.AUDIT_LOG; private static final int DEFAULT_PRIORITY_LEVEL = 3; private static final String AUTHENTICATOR_NAME = SAML2SSOAuthenticatorBEConstants.SAML2_SSO_AUTHENTICATOR_NAME; private SecureRandom random = new SecureRandom(); public boolean login(AuthnReqDTO authDto) { String username = null; String tenantDomain = null; String auditResult = SAML2SSOAuthenticatorConstants.AUDIT_RESULT_FAILED; HttpSession httpSession = getHttpSession(); try { XMLObject xmlObject = Util.unmarshall(org.wso2.carbon.identity.authenticator.saml2.sso.common.Util.decode(authDto.getResponse())); username = org.wso2.carbon.identity.authenticator.saml2.sso.common.Util.getUsername(xmlObject); if ((username == null) || "".equals(username.trim())) { log.error("Authentication Request is rejected. " + "SAMLResponse does not contain the username of the subject."); CarbonAuthenticationUtil.onFailedAdminLogin(httpSession, username, -1, "SAML2 SSO Authentication", "SAMLResponse does not contain the username of the subject"); // Unable to call #handleAuthenticationCompleted since there is no way to determine // tenantId without knowing the username. return false; } if (!validateAudienceRestrictionInXML(xmlObject)) { log.error("Authentication Request is rejected. SAMLResponse AudienceRestriction validation failed."); CarbonAuthenticationUtil.onFailedAdminLogin(httpSession, username, -1, "SAML2 SSO Authentication", "AudienceRestriction validation failed"); return false; } RegistryService registryService = SAML2SSOAuthBEDataHolder.getInstance().getRegistryService(); RealmService realmService = SAML2SSOAuthBEDataHolder.getInstance().getRealmService(); tenantDomain = MultitenantUtils.getTenantDomain(username); int tenantId = realmService.getTenantManager().getTenantId(tenantDomain); handleAuthenticationStarted(tenantId); if (isResponseSignatureValidationEnabled()) { boolean isSignatureValid = validateSignature(xmlObject, tenantDomain); if (!isSignatureValid) { log.error("Authentication Request is rejected. Signature validation failed."); CarbonAuthenticationUtil.onFailedAdminLogin(httpSession, username, tenantId, "SAML2 SSO Authentication", "Invalid Signature"); handleAuthenticationCompleted(tenantId, false); return false; } } username = MultitenantUtils.getTenantAwareUsername(username); UserRealm realm = AnonymousSessionUtil.getRealmByTenantDomain(registryService, realmService, tenantDomain); // Authentication is done // Starting user provisioning provisionUser(username, realm, xmlObject); // End user provisioning // Starting Authorization PermissionUpdateUtil.updatePermissionTree(tenantId); boolean isAuthorized = false; if (realm != null) { isAuthorized = realm.getAuthorizationManager().isUserAuthorized(username, "/permission/admin/login", CarbonConstants.UI_PERMISSION_ACTION); } if (isAuthorized) { CarbonAuthenticationUtil.onSuccessAdminLogin(httpSession, username, tenantId, tenantDomain, "SAML2 SSO Authentication"); handleAuthenticationCompleted(tenantId, true); auditResult = SAML2SSOAuthenticatorConstants.AUDIT_RESULT_SUCCESS; return true; } else { log.error("Authentication Request is rejected. Authorization Failure."); CarbonAuthenticationUtil.onFailedAdminLogin(httpSession, username, tenantId, "SAML2 SSO Authentication", "Authorization Failure"); handleAuthenticationCompleted(tenantId, false); return false; } } catch (Exception e) { String msg = "System error while Authenticating/Authorizing User : " + e.getMessage(); log.error(msg, e); return false; } finally { if (username != null && username.trim().length() > 0 && AUDIT_LOG.isInfoEnabled()) { String auditInitiator = username + UserCoreConstants.TENANT_DOMAIN_COMBINER + tenantDomain; String auditData = ""; AUDIT_LOG.info(String.format(SAML2SSOAuthenticatorConstants.AUDIT_MESSAGE, auditInitiator, SAML2SSOAuthenticatorConstants.AUDIT_ACTION_LOGIN, AUTHENTICATOR_NAME, auditData, auditResult)); } } } private void handleAuthenticationStarted(int tenantId) { BundleContext bundleContext = SAML2SSOAuthBEDataHolder.getInstance().getBundleContext(); if (bundleContext != null) { ServiceTracker tracker = new ServiceTracker(bundleContext, AuthenticationObserver.class.getName(), null); tracker.open(); Object[] services = tracker.getServices(); if (services != null) { for (Object service : services) { ((AuthenticationObserver) service).startedAuthentication(tenantId); } } tracker.close(); } } private void handleAuthenticationCompleted(int tenantId, boolean isSuccessful) { BundleContext bundleContext = SAML2SSOAuthBEDataHolder.getInstance().getBundleContext(); if (bundleContext != null) { ServiceTracker tracker = new ServiceTracker(bundleContext, AuthenticationObserver.class.getName(), null); tracker.open(); Object[] services = tracker.getServices(); if (services != null) { for (Object service : services) { ((AuthenticationObserver) service).completedAuthentication( tenantId, isSuccessful); } } tracker.close(); } } public void logout() { String loggedInUser; String delegatedBy; Date currentTime = Calendar.getInstance().getTime(); SimpleDateFormat date = new SimpleDateFormat("'['yyyy-MM-dd HH:mm:ss,SSSS']'"); HttpSession session = getHttpSession(); if (session != null) { loggedInUser = (String) session.getAttribute(ServerConstants.USER_LOGGED_IN); delegatedBy = (String) session.getAttribute("DELEGATED_BY"); if (StringUtils.isNotBlank(loggedInUser)) { String logMessage = "'" + loggedInUser + "' logged out at " + date.format(currentTime); if (delegatedBy != null) { logMessage += " delegated by " + delegatedBy; } log.info(logMessage); } session.invalidate(); if (loggedInUser != null && AUDIT_LOG.isInfoEnabled()) { // username in the session is in tenantAware manner String tenantAwareUsername = loggedInUser; String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain(); String auditInitiator = tenantAwareUsername + UserCoreConstants.TENANT_DOMAIN_COMBINER + tenantDomain; String auditData = delegatedBy != null ? "Delegated By : " + delegatedBy : ""; AUDIT_LOG.info(String.format(SAML2SSOAuthenticatorConstants.AUDIT_MESSAGE, auditInitiator, SAML2SSOAuthenticatorConstants.AUDIT_ACTION_LOGOUT, AUTHENTICATOR_NAME, auditData, SAML2SSOAuthenticatorConstants.AUDIT_RESULT_SUCCESS)); } } } public boolean isHandle(MessageContext messageContext) { return true; } public boolean isAuthenticated(MessageContext messageContext) { HttpServletRequest request = (HttpServletRequest) messageContext .getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST); HttpSession httpSession = request.getSession(); String loginStatus = (String) httpSession.getAttribute(ServerConstants.USER_LOGGED_IN); return (loginStatus != null); } public boolean authenticateWithRememberMe(MessageContext messageContext) { return false; } public int getPriority() { AuthenticatorsConfiguration authenticatorsConfiguration = AuthenticatorsConfiguration.getInstance(); AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig = authenticatorsConfiguration.getAuthenticatorConfig(AUTHENTICATOR_NAME); if (authenticatorConfig != null && authenticatorConfig.getPriority() > 0) { return authenticatorConfig.getPriority(); } return DEFAULT_PRIORITY_LEVEL; } public String getAuthenticatorName() { return AUTHENTICATOR_NAME; } public boolean isDisabled() { AuthenticatorsConfiguration authenticatorsConfiguration = AuthenticatorsConfiguration.getInstance(); AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig = authenticatorsConfiguration.getAuthenticatorConfig(AUTHENTICATOR_NAME); if (authenticatorConfig != null) { return authenticatorConfig.isDisabled(); } return false; } /** * Check whether signature validation is enabled in the authenticators.xml configuration file * * @return false only if SSOAuthenticator configuration has the parameter * <Parameter name="ResponseSignatureValidationEnabled">false</Parameter>, true otherwise */ private boolean isResponseSignatureValidationEnabled() { AuthenticatorsConfiguration authenticatorsConfiguration = AuthenticatorsConfiguration .getInstance(); AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig = authenticatorsConfiguration .getAuthenticatorConfig(AUTHENTICATOR_NAME); if (authenticatorConfig != null) { String responseSignatureValidation = authenticatorConfig .getParameters() .get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.RESPONSE_SIGNATURE_VALIDATION_ENABLED); if (responseSignatureValidation != null && responseSignatureValidation.equalsIgnoreCase("false")) { if (log.isDebugEnabled()) { log.debug("Signature validation is disabled in the configuration"); } return false; } } if (log.isDebugEnabled()) { log.debug("Signature validation is enabled in the configuration"); } return true; } /** * Check whether signature validation is enabled in the authenticators.xml configuration file * * @return false only if SSOAuthenticator configuration has the parameter * <Parameter name="ResponseSignatureValidationEnabled">false</Parameter>, true otherwise */ private boolean isVerifySignWithUserDomain() { AuthenticatorsConfiguration authenticatorsConfiguration = AuthenticatorsConfiguration .getInstance(); AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig = authenticatorsConfiguration .getAuthenticatorConfig(AUTHENTICATOR_NAME); if (authenticatorConfig != null) { String responseSignatureValidation = authenticatorConfig .getParameters() .get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.VALIDATE_SIGNATURE_WITH_USER_DOMAIN); if ("true".equalsIgnoreCase(responseSignatureValidation)) { if (log.isDebugEnabled()) { log.debug("Signature validation is done based on user tenant domain"); } return true; } } if (log.isDebugEnabled()) { log.debug("Signature validation is done with super tenant domain"); } return false; } /** * Validate the signature of a SAML2 XMLObject * * @param xmlObject SAML2 XMLObject * @param domainName domain name of the subject * @return true, if signature is valid. */ private boolean validateSignature(XMLObject xmlObject, String domainName) { if (xmlObject instanceof Response) { return validateSignature((Response) xmlObject, domainName); } else if (xmlObject instanceof Assertion) { return validateSignature((Assertion) xmlObject, domainName); } else { log.error("Only Response and Assertion objects are validated in this authendicator"); return false; } } /** * Validate the signature of a SAML2 Response * * @param response SAML2 Response * @param domainName domain name of the subject * @return true, if signature is valid. */ private boolean validateSignature(Response response, String domainName) { boolean isSignatureValid = false; if (response.getSignature() == null) { log.error("SAML Response is not signed. So authentication process will be terminated."); } else { isSignatureValid = validateSignature(response.getSignature(), domainName); } return isSignatureValid; } /** * Validate the signature of a SAML2 Assertion * * @param assertion SAML2 Assertion * @param domainName domain name of the subject * @return true, if signature is valid. */ private boolean validateSignature(Assertion assertion, String domainName) { boolean isSignatureValid = false; if (assertion.getSignature() == null) { log.error("SAML Assertion is not signed. So authentication process will be terminated."); } else { isSignatureValid = validateSignature(assertion.getSignature(), domainName); } return isSignatureValid; } /** * Validate the signature of a SAML2 Signature * * @param signature SAML2 Signature * @param domainName domain name of the subject * @return true, if signature is valid. */ private boolean validateSignature(Signature signature, String domainName) { boolean isSignatureValid = false; try { SignatureValidator validator = null; if (isVerifySignWithUserDomain()) { validator = new SignatureValidator(Util.getX509CredentialImplForTenant(domainName)); } else { validator = new SignatureValidator(Util.getX509CredentialImplForTenant(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)); } validator.validate(signature); isSignatureValid = true; } catch (SAML2SSOAuthenticatorException e) { String errorMsg = "Error when creating an X509CredentialImpl instance"; log.error(errorMsg, e); } catch (ValidationException e) { log.warn("Signature validation failed for a SAML2 Reposnse from domain : " + domainName, e); } return isSignatureValid; } /** * Get the Assertion from the SAML2 Response * * @param response SAML2 Response * @return assertion */ private Assertion getAssertionFromResponse(Response response) { Assertion assertion = null; if (response != null) { List<Assertion> assertions = response.getAssertions(); if (assertions != null && assertions.size() > 0) { assertion = assertions.get(0); } else { log.error("SAML2 Response doesn't contain Assertions"); } } return assertion; } /** * Validate the AudienceRestriction of SAML2 XMLObject * * @param xmlObject Unmarshalled SAML2 Response * @return validity */ private boolean validateAudienceRestrictionInXML(XMLObject xmlObject) { if (xmlObject instanceof Response) { return validateAudienceRestrictionInResponse((Response) xmlObject); } else if (xmlObject instanceof Assertion) { return validateAudienceRestrictionInAssertion((Assertion) xmlObject); } else { log.error("Only Response and Assertion objects are validated in this authendicator"); return false; } } /** * Validate the AudienceRestriction of SAML2 Response * * @param response SAML2 Response * @return validity */ public boolean validateAudienceRestrictionInResponse(Response response) { Assertion assertion = getAssertionFromResponse(response); return validateAudienceRestrictionInAssertion(assertion); } /** * Validate the AudienceRestriction of SAML2 Assertion * * @param assertion SAML2 Assertion * @return validity */ public boolean validateAudienceRestrictionInAssertion(Assertion assertion) { if (assertion != null) { Conditions conditions = assertion.getConditions(); if (conditions != null) { List<AudienceRestriction> audienceRestrictions = conditions.getAudienceRestrictions(); if (audienceRestrictions != null && !audienceRestrictions.isEmpty()) { for (AudienceRestriction audienceRestriction : audienceRestrictions) { if (audienceRestriction.getAudiences() != null && audienceRestriction.getAudiences().size() > 0) { for (Audience audience : audienceRestriction.getAudiences()) { String spId = org.wso2.carbon.identity.authenticator.saml2.sso.common.Util.getServiceProviderId(); if (spId == null) { org.wso2.carbon.identity.authenticator.saml2.sso.common.Util.initSSOConfigParams(); spId = org.wso2.carbon.identity.authenticator.saml2.sso.common.Util.getServiceProviderId(); } if (spId != null) { if (spId.equals(audience.getAudienceURI())) { return true; } } else { log.warn("No SAML2 service provider ID defined."); } } } else { log.warn("SAML2 Response's AudienceRestriction doesn't contain Audiences"); } } } else { log.error("SAML2 Response doesn't contain AudienceRestrictions"); } } else { log.error("SAML2 Response doesn't contain Conditions"); } } return false; } private HttpSession getHttpSession() { MessageContext msgCtx = MessageContext.getCurrentMessageContext(); HttpSession httpSession = null; if (msgCtx != null) { HttpServletRequest request = (HttpServletRequest) msgCtx.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST); httpSession = request.getSession(); } return httpSession; } /** * Provision/Create user on the server(SP) and update roles accordingly * * @param username * @param realm * @param xmlObject * @throws UserStoreException * @throws SAML2SSOAuthenticatorException */ private void provisionUser(String username, UserRealm realm, XMLObject xmlObject) throws UserStoreException, SAML2SSOAuthenticatorException { AuthenticatorsConfiguration authenticatorsConfiguration = AuthenticatorsConfiguration.getInstance(); AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig = authenticatorsConfiguration.getAuthenticatorConfig(AUTHENTICATOR_NAME); if (authenticatorConfig != null) { Map<String, String> configParameters = authenticatorConfig.getParameters(); boolean isJITProvisioningEnabled = false; if (configParameters.containsKey(SAML2SSOAuthenticatorBEConstants.PropertyConfig.JIT_USER_PROVISIONING_ENABLED)) { isJITProvisioningEnabled = Boolean.parseBoolean(configParameters.get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.JIT_USER_PROVISIONING_ENABLED)); } if (isJITProvisioningEnabled) { String userstoreDomain = null; if (configParameters.containsKey(SAML2SSOAuthenticatorBEConstants.PropertyConfig.PROVISIONING_DEFAULT_USERSTORE)) { userstoreDomain = configParameters.get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.PROVISIONING_DEFAULT_USERSTORE); } UserStoreManager userstore = null; // TODO : Get userstore from asserstion // TODO : remove user store domain name from username if (userstoreDomain != null && !userstoreDomain.isEmpty()) { userstore = realm.getUserStoreManager().getSecondaryUserStoreManager(userstoreDomain); } // If default user store is invalid or not specified use primary user store if (userstore == null) { userstore = realm.getUserStoreManager(); } String[] newRoles = getRoles(xmlObject); // Load default role if asserstion didnt specify roles if (newRoles == null || newRoles.length == 0) { if (configParameters.containsKey(SAML2SSOAuthenticatorBEConstants.PropertyConfig.PROVISIONING_DEFAULT_ROLE)) { newRoles = new String[]{configParameters.get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.PROVISIONING_DEFAULT_ROLE)}; } } if (newRoles == null) { newRoles = new String[]{}; } if (log.isDebugEnabled()) { log.debug("User " + username + " contains roles : " + Arrays.toString(newRoles) + " as per response and (default role) config"); } // addingRoles = newRoles AND allExistingRoles Collection<String> addingRoles = new ArrayList<String>(); Collections.addAll(addingRoles, newRoles); Collection<String> allExistingRoles = Arrays.asList(userstore.getRoleNames()); addingRoles.retainAll(allExistingRoles); if (userstore.isExistingUser(username)) { // Update user Collection<String> currentRolesList = Arrays.asList(userstore.getRoleListOfUser(username)); // addingRoles = (newRoles AND existingRoles) - currentRolesList) addingRoles.removeAll(currentRolesList); Collection<String> deletingRoles = new ArrayList<String>(); deletingRoles.addAll(currentRolesList); // deletingRoles = currentRolesList - newRoles deletingRoles.removeAll(Arrays.asList(newRoles)); // Exclude Internal/everyonerole from deleting role since its cannot be deleted deletingRoles.remove(realm.getRealmConfiguration().getEveryOneRoleName()); // Check for case whether superadmin login if (userstore.getRealmConfiguration().isPrimary() && username.equals(realm.getRealmConfiguration().getAdminUserName())) { boolean isSuperAdminRoleRequired = false; if (configParameters.containsKey(SAML2SSOAuthenticatorBEConstants.PropertyConfig.IS_SUPER_ADMIN_ROLE_REQUIRED)) { isSuperAdminRoleRequired = Boolean.parseBoolean(configParameters.get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.IS_SUPER_ADMIN_ROLE_REQUIRED)); } // Whether superadmin login without superadmin role is permitted if (!isSuperAdminRoleRequired && deletingRoles.contains(realm.getRealmConfiguration().getAdminRoleName())) { // Avoid removing superadmin role from superadmin user. deletingRoles.remove(realm.getRealmConfiguration().getAdminRoleName()); log.warn("Proceeding with allowing super admin to be logged in, eventhough response doesn't include superadmin role assiged for the superadmin user."); } } if (log.isDebugEnabled()) { log.debug("Deleting roles : " + Arrays.toString(deletingRoles.toArray(new String[0])) + " and Adding roles : " + Arrays.toString(addingRoles.toArray(new String[0]))); } userstore.updateRoleListOfUser(username, deletingRoles.toArray(new String[0]), addingRoles.toArray(new String[0])); if (log.isDebugEnabled()) { log.debug("User: " + username + " is updated via SAML authenticator with roles : " + Arrays.toString(newRoles)); } } else { userstore.addUser(username, generatePassword(username), addingRoles.toArray(new String[0]), null, null); if (log.isDebugEnabled()) { log.debug("User: " + username + " is provisioned via SAML authenticator with roles : " + Arrays.toString(addingRoles.toArray(new String[0]))); } } } else { if (log.isDebugEnabled()) { log.debug("User provisioning diabled"); } } } else { if (log.isDebugEnabled()) { log.debug("Cannot find authenticator config for authenticator : " + AUTHENTICATOR_NAME); } throw new SAML2SSOAuthenticatorException("Cannot find authenticator config for authenticator : " + AUTHENTICATOR_NAME); } } /** * Generates (random) password for user to be provisioned * * @param username * @return */ private String generatePassword(String username) { return new BigInteger(130, random).toString(32); } /** * Get roles from the SAML2 XMLObject * * @param xmlObject SAML2 XMLObject * @return String array of roles */ private String[] getRoles(XMLObject xmlObject) { String[] arrRoles = {}; if (xmlObject instanceof Response) { return getRolesFromResponse((Response) xmlObject); } else if (xmlObject instanceof Assertion) { return getRolesFromAssertion((Assertion) xmlObject); } else { return arrRoles; } } /** * Get roles from the SAML2 Response * * @param response SAML2 Response * @return roles array */ private String[] getRolesFromResponse(Response response) { List<Assertion> assertions = response.getAssertions(); Assertion assertion = null; if (assertions != null && assertions.size() > 0) { assertion = assertions.get(0); return getRolesFromAssertion(assertion); } return null; } /** * Get the username from the SAML2 Assertion * * @param assertion SAML2 assertion * @return username */ private String[] getRolesFromAssertion(Assertion assertion) { String[] roles = null; String roleClaim = getRoleClaim(); List<AttributeStatement> attributeStatementList = assertion.getAttributeStatements(); if (attributeStatementList != null) { for (AttributeStatement statement : attributeStatementList) { List<Attribute> attributesList = statement.getAttributes(); for (Attribute attribute : attributesList) { String attributeName = attribute.getName(); if (attributeName != null && roleClaim.equals(attributeName)) { // Assumes role claim appear only once Element value = attribute.getAttributeValues().get(0).getDOM(); String attributeValue = value.getTextContent(); if (log.isDebugEnabled()) { log.debug("AttributeName : " + attributeName + ", AttributeValue : " + attributeValue); } roles = attributeValue.split(getAttributeSeperator()); if (log.isDebugEnabled()) { log.debug("Role list : " + Arrays.toString(roles)); } } } } } return roles; } /** * Role claim attribute value from configuration file or from constants * * @return */ private String getRoleClaim() { AuthenticatorsConfiguration authenticatorsConfiguration = AuthenticatorsConfiguration.getInstance(); AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig = authenticatorsConfiguration.getAuthenticatorConfig(AUTHENTICATOR_NAME); if (authenticatorConfig != null) { Map<String, String> configParameters = authenticatorConfig.getParameters(); if (configParameters.containsKey(SAML2SSOAuthenticatorBEConstants.PropertyConfig.ROLE_CLAIM_ATTRIBUTE)) { return configParameters.get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.ROLE_CLAIM_ATTRIBUTE); } } return SAML2SSOAuthenticatorBEConstants.ROLE_ATTRIBUTE_NAME; } /** * Get attribute separator from configuration or from the constants * * @return */ private String getAttributeSeperator() { AuthenticatorsConfiguration authenticatorsConfiguration = AuthenticatorsConfiguration.getInstance(); AuthenticatorsConfiguration.AuthenticatorConfig authenticatorConfig = authenticatorsConfiguration.getAuthenticatorConfig(AUTHENTICATOR_NAME); if (authenticatorConfig != null) { Map<String, String> configParameters = authenticatorConfig.getParameters(); if (configParameters.containsKey(SAML2SSOAuthenticatorBEConstants.PropertyConfig.ATTRIBUTE_VALUE_SEPARATOR)) { return configParameters.get(SAML2SSOAuthenticatorBEConstants.PropertyConfig.ATTRIBUTE_VALUE_SEPARATOR); } } return SAML2SSOAuthenticatorBEConstants.ATTRIBUTE_VALUE_SEPERATER; } }