package org.picketlink.identity.federation.bindings.jboss.auth.mapping; import java.security.Principal; import java.util.Map; import org.jboss.security.SimplePrincipal; import org.jboss.security.mapping.MappingResult; import org.jboss.security.mapping.providers.principal.AbstractPrincipalMappingProvider; import org.picketlink.identity.federation.PicketLinkLogger; import org.picketlink.identity.federation.PicketLinkLoggerFactory; import org.picketlink.identity.federation.core.wstrust.auth.AbstractSTSLoginModule; import org.picketlink.identity.federation.core.wstrust.plugins.saml.SAMLUtil; import org.picketlink.identity.federation.saml.v2.assertion.AssertionType; import org.picketlink.identity.federation.saml.v2.assertion.BaseIDAbstractType; import org.picketlink.identity.federation.saml.v2.assertion.NameIDType; import org.picketlink.identity.federation.saml.v2.assertion.SubjectType; import org.w3c.dom.Element; /** * <p> * This mapping provider looks at the NameID in the Assertion and returns a corresponding JBoss Principal for insertion into the * Subject. * </p> * * <h3>Configuration</h3> * * <pre> * {@code * <application-policy name="saml-issue-token"> * <authentication> * <login-module code="org.picketlink.identity.federation.core.wstrust.auth.STSIssuingLoginModule" flag="required"> * <module-option name="configFile">/sts-client.properties</module-option> * <module-option name="password-stacking">useFirstPass</module-option> * </login-module> * </authentication> * <mapping> * <mapping-module code="org.picketlink.identity.federation.bindings.jboss.auth.mapping.STSPrincipalMappingProvider" type="principal"/> * <mapping-module code="org.picketlink.identity.federation.bindings.jboss.auth.mapping.STSGroupMappingProvider" type="role"/> * </mapping> * </application-policy> * } * </pre> * * @author <a href="mailto:Babak@redhat.com">Babak Mozaffari</a> */ public class STSPrincipalMappingProvider extends AbstractPrincipalMappingProvider { private static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger(); private MappingResult<Principal> result; public void init(Map<String, Object> contextMap) { // No initialization needed } public void performMapping(Map<String, Object> contextMap, Principal principal) { if (contextMap == null) { logger.mappingContextNull(); } Object tokenObject = contextMap.get(AbstractSTSLoginModule.SHARED_TOKEN); if (!(tokenObject instanceof Element)) { // With Tomcat SSO Valves, mapping providers DO get called automatically, so there may be no tokens and errors // should be expected and handled logger.debug("Did not find a token " + Element.class.getName() + " under " + AbstractSTSLoginModule.SHARED_TOKEN + " in the map"); } try { Element tokenElement = (Element) tokenObject; AssertionType assertion = SAMLUtil.fromElement(tokenElement); SubjectType subject = assertion.getSubject(); if (subject != null) { BaseIDAbstractType baseID = subject.getSubType().getBaseID(); if (baseID != null && baseID instanceof NameIDType) { NameIDType nameID = (NameIDType) baseID; Principal mappedPrincipal = new SimplePrincipal(nameID.getValue()); result.setMappedObject(mappedPrincipal); logger.trace("Mapped principal = " + mappedPrincipal); return; } } } catch (Exception e) { logger.samlAssertionPasingFailed(e); } } public void setMappingResult(MappingResult<Principal> mappingResult) { this.result = mappingResult; } }