Package org.picketlink.identity.federation.core.wstrust.auth

Source Code of org.picketlink.identity.federation.core.wstrust.auth.AbstractSTSLoginModule

/*
* JBoss, Home of Professional Open Source Copyright 2009, Red Hat Middleware
* LLC, and individual contributors by the @authors tag. See the copyright.txt
* in the distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.picketlink.identity.federation.core.wstrust.auth;

import java.io.IOException;
import java.security.Principal;
import java.security.acl.Group;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.xml.datatype.XMLGregorianCalendar;

import org.jboss.security.SecurityConstants;
import org.jboss.security.SecurityContext;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.identity.Role;
import org.jboss.security.identity.RoleGroup;
import org.jboss.security.mapping.MappingContext;
import org.jboss.security.mapping.MappingManager;
import org.jboss.security.mapping.MappingType;
import org.picketlink.identity.federation.PicketLinkLogger;
import org.picketlink.identity.federation.PicketLinkLoggerFactory;
import org.picketlink.identity.federation.core.constants.AttributeConstants;
import org.picketlink.identity.federation.core.constants.PicketLinkFederationConstants;
import org.picketlink.identity.federation.core.exceptions.ParsingException;
import org.picketlink.identity.federation.core.factories.JBossAuthCacheInvalidationFactory;
import org.picketlink.identity.federation.core.factories.JBossAuthCacheInvalidationFactory.TimeCacheExpiry;
import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
import org.picketlink.identity.federation.core.util.StringUtil;
import org.picketlink.identity.federation.core.wstrust.STSClient;
import org.picketlink.identity.federation.core.wstrust.STSClientConfig;
import org.picketlink.identity.federation.core.wstrust.STSClientConfig.Builder;
import org.picketlink.identity.federation.core.wstrust.STSClientFactory;
import org.picketlink.identity.federation.core.wstrust.SamlCredential;
import org.picketlink.identity.federation.core.wstrust.WSTrustException;
import org.picketlink.identity.federation.core.wstrust.plugins.saml.SAMLUtil;
import org.picketlink.identity.federation.saml.v2.assertion.AssertionType;
import org.w3c.dom.Element;

/**
* Abstract JAAS LoginModule for JBoss STS (Security Token Service). </p>
*
* Subclasses are required to implement {@link #invokeSTS(STSClient)()} to perform their specific actions.
*
* <h3>Configuration</h3> Concrete implementations specify from where the username and credentials should be read from. <lu> <li>
* Callback handler, {@link NameCallback} and {@link PasswordCallback}.</li> <li>From the login modules options configuration.</li>
* <li>From the login modules earlier in the login modules stack.</li> </lu>
*
* <h3>Configuration example</h3> 1. Callbackhandler configuration:
*
* <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>
*     </login-module>
*   </authentication>
* </application-policy>
* }
* </pre>
*
* 2. Login module options configuration:
*
* <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="useOptionsCredentials">true</module-option>
*     </login-module>
*   </authentication>
* </application-policy>
* }
* </pre>
*
* 3. Password stacking configuration:
*
* <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>
* </application-policy>
* }
* </pre>
*
* <h3>Password stacking</h3> Password stacking can be configured which means that a Login module configured with
* 'password-stacking' set to 'true' will set the username and password in the shared state map. Login modules that come after
* can set 'password-stacking' to 'useFirstPass' which means that that login module will use the username and password from the
* shared map.
* <p/>
* </pre> 4. Mapping Provider configuration:
*
* <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>
*     <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>
*   </authentication>
* </application-policy>
* }
* </pre>
*
* <h3>Mapping Providers</h3>
* Principal and Role mapping providers may be configured on subclasses of this login module and be leveraged to populate the
* JAAS Subject with appropriate user id and roles. The token is made available to the mapping providers so that identity
* information may be extracted.
* <p/>
*
* Subclasses can define more configuration options by overriding initialize. Also note that subclasses are not forced to put
* configuration options in a file. They can all be set as options just like the 'configFile' is specified above.
*
* <h3>Additional Configuration</h3>
* <p>
* roleKey: By default, the saml attributes with key "Role" are assumed to represent user roles. You can configure a comma
* separated list of string values to represent the attribute names for user roles.
* </p>
*
* <p>
* cache.invalidation: set it to true if you require invalidation of JBoss Auth Cache at SAML Principal expiration.
* </p>
* <p>
* jboss.security.security_domain: name of the security domain where this login module is configured. This is only required if
* the cache.invalidation option is configured.
* </p>
*
* <p>
* inject.callerprincipal: set it to true if you want to add a group principal called "CallerPrincipal" with the roles from the
* assertion, into the subject
* </p>
*
* @author <a href="mailto:dbevenius@jboss.com">Daniel Bevenius</a>
* @author Anil.Saldhana@redhat.com
*/
public abstract class AbstractSTSLoginModule implements LoginModule {
   
    protected static final PicketLinkLogger logger = PicketLinkLoggerFactory.getLogger();

    /**
     * Key used in share state map when LMs are stacked.
     */
    public static final String SHARED_TOKEN = "org.picketlink.identity.federation.core.wstrust.lm.stsToken";

    /**
     * Options configuration name;
     */
    public static final String OPTIONS_CREDENTIALS = "useOptionsCredentials";

    /**
     * Options configuration name;
     */
    public static final String OPTIONS_PW_STACKING = "password-stacking";

    /**
     * This is the required option that should identify the configuration file for WSTrustClient.
     */
    public static final String STS_CONFIG_FILE = "configFile";

    /**
     * Attribute names indicating the user roles
     */
    public static final String ROLE_KEY = "roleKey";

    /**
     * Key to specify the end point address
     */
    public static final String ENDPOINT_ADDRESS = "endpointAddress";

    /**
     * Key to specify the port name
     */
    public static final String PORT_NAME = "portName";

    /**
     * Key to specify the service name
     */
    public static final String SERVICE_NAME = "serviceName";

    /**
     * Key to specify the username
     */
    public static final String USERNAME_KEY = "username";

    /**
     * Key to specify the password
     */
    public static final String PASSWORD_KEY = "password";

    /**
     * Key to specify whether this batch issue request
     */
    public static final String IS_BATCH = "isBatch";

    /**
     * Paramater name.
     */
    public static final String MAX_CLIENTS_IN_POOL = "maxClientsInPool";

    /**
     * Paramater name.
     */
    public static final String INITIAL_NUMBER_OF_CLIENTS = "initialNumberOfClients";

    /**
     * The subject to be populated.
     */
    protected Subject subject;

    /**
     * Callback handler used to gather information from the caller.
     */
    protected CallbackHandler callbackHandler;

    /**
     * WS-Trust SAML Assertion element.
     */
    protected Element samlToken;

    /**
     * The outcome of the authentication process.
     */
    protected boolean success;

    /**
     * The options map passed into this login modules initalize method.
     */
    protected Map<String, ?> options;

    /**
     * The shared state map passed into this login modules initalize method.
     */
    @SuppressWarnings("rawtypes")
    protected Map sharedState;

    /**
     * Indicates whether password stacking option was configured.
     */
    protected boolean passwordStacking;

    /**
     * Indicates whether the password-stacking options was specifed as 'useFirstPass'.
     */
    protected boolean useFirstPass;

    /**
     * Indicates whether the 'useOptionsCredentials' was configured.
     */
    protected boolean useOptionsCredentials;

    /**
     * Name of the saml attribute representing roles. Can be csv
     */
    protected String roleKey = AttributeConstants.ROLE_IDENTIFIER_ASSERTION;

    protected boolean enableCacheInvalidation = false;

    /**
     * Should a separate Group Principal called "CallerPrincipal" be injected into subject with the roles from the assertion?
     */
    protected boolean injectCallerPrincipalGroup = false;

    protected String securityDomain = null;

    /**
     * Value to indicate whether the RST is a batch request
     */
    protected boolean isBatch = false;

    /**
     * Maximal number of clients in the STS Client Pool.
     */
    protected int maxClientsInPool = 0;

    /**
     * Number of clients initialized for in case pool is out of free clients.
     */
    protected int initialNumberOfClients = 0;

    /**
     * Initialized this login module. Simple stores the passed in fields and also validates the options.
     *
     * @param subject The subject to authenticate/populate.
     * @param callbackHandler The callbackhandler that will gather information required by this login module.
     * @param sharedState State that is shared with other login modules. Used when modules are chained/stacked.
     * @param options The options that were specified for this login module.
     */
    public void initialize(final Subject subject, final CallbackHandler callbackHandler, final Map<String, ?> sharedState,
            final Map<String, ?> options) {
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.options = options;
        this.sharedState = sharedState;

        final String pwStackingOption = (String) options.get(OPTIONS_PW_STACKING);
        passwordStacking = pwStackingOption != null;
        if (passwordStacking)
            useFirstPass = "useFirstPass".equals(pwStackingOption);

        final Boolean useOptionsCreds = Boolean.valueOf((String) options.get(OPTIONS_CREDENTIALS));
        if (useOptionsCreds != null)
            useOptionsCredentials = useOptionsCreds.booleanValue();

        final String roleKeyStr = (String) options.get(ROLE_KEY);
        if (roleKeyStr != null && roleKeyStr.length() > 0)
            roleKey = roleKeyStr;

        String cacheInvalidation = (String) options.get("cache.invalidation");
        if (cacheInvalidation != null && !cacheInvalidation.isEmpty()) {
            enableCacheInvalidation = Boolean.parseBoolean(cacheInvalidation);
            securityDomain = (String) options.get(SecurityConstants.SECURITY_DOMAIN_OPTION);
            if (securityDomain == null || securityDomain.isEmpty())
                throw logger.optionNotSet(SecurityConstants.SECURITY_DOMAIN_OPTION);
        }

        String callerPrincipalGroup = (String) options.get("inject.callerprincipal");
        if (callerPrincipalGroup != null && !callerPrincipalGroup.isEmpty()) {
            this.injectCallerPrincipalGroup = Boolean.parseBoolean(callerPrincipalGroup);
        }

        String batchIssueString = (String) options.get(IS_BATCH);
        if (StringUtil.isNotNull(batchIssueString)) {
            this.isBatch = Boolean.parseBoolean(batchIssueString);
        }

        String maxClientsString = (String) options.get(MAX_CLIENTS_IN_POOL);
        if (StringUtil.isNotNull(maxClientsString)) {
            try {
                this.maxClientsInPool = Integer.parseInt(maxClientsString);
            } catch (Exception e) {
                logger.cannotParseParameterValue(MAX_CLIENTS_IN_POOL, e);
            }
        }

        String initialNumberOfClientsString = (String) options.get(INITIAL_NUMBER_OF_CLIENTS);
        if (StringUtil.isNotNull(initialNumberOfClientsString)) {
            try {
                this.initialNumberOfClients = Integer.parseInt(initialNumberOfClientsString);
            } catch (Exception e) {
                logger.cannotParseParameterValue(INITIAL_NUMBER_OF_CLIENTS, e);
            }
        }

    }

    /**
     * Subclasses must implement the login to perform their specific tasks.
     *
     * The login module should call {@link #setSamlToken(Element)} with the saml token element that should be added to the
     * public credentials in {@link #commit()}.
     *
     * @return true If the login was successful otherwise false.
     * @throws LoginException If an error occurs while trying to perform the authentication.
     */
    public boolean login() throws LoginException {
        try {
            final Builder builder = createBuilder();
            if (useOptionsCredentials) {
                useCredentialsFromOptions(builder, options);
            } else if (isUseFirstPass()) {
                useCredentialsFromSharedState(builder);
            } else {
                useCredentialsFromCallback(builder);
            }

            if (passwordStacking)
                setPasswordStackingCredentials(builder);

            final STSClient stsClient = createWSTrustClient(builder.build());

            final Element token = invokeSTS(stsClient);

            if (token == null) {
                // Throw an exception as returing false only says that this login module should be ignored.
                throw logger.authCouldNotIssueSAMLToken();
            }
            setSuccess(true);
            setSamlToken(token);
            setSharedToken(token);
            return true;
        } catch (WSTrustException e) {
            throw logger.authLoginError(e);
        }
    }

    public abstract Element invokeSTS(final STSClient stsclient) throws WSTrustException, LoginException;

    /**
     * Commit will package the samlToken set by the login method in a new {@link SamlCredential}. This new SamlCredential will
     * be put into the Subject public credentials set.
     */
    public boolean commit() throws LoginException {
        if (success) {
            final SamlCredential samlCredential = new SamlCredential(samlToken);
            final boolean added = subject.getPublicCredentials().add(samlCredential);
            populateSubject();
            if (added)
                logger.trace("Added Credential " + samlCredential);

            return true;
        } else {
            return false;
        }
    }

    /**
     * Called if the overall authentication failed (phase 2).
     */
    public boolean abort() throws LoginException {
        success = false;
        clearState();
        return true;
    }

    public boolean logout() throws LoginException {
        clearState();
        return true;
    }

    /**
     * Subclasses can override and create a preconfigured builder
     *
     * @return
     */
    protected Builder createBuilder() {
        if (options.containsKey(STS_CONFIG_FILE)) {
            return new STSClientConfig.Builder(getRequiredOption(getOptions(), STS_CONFIG_FILE));
        } else {
            Builder builder = new Builder();
            builder.endpointAddress((String) options.get(ENDPOINT_ADDRESS));
            builder.portName((String) options.get(PORT_NAME)).serviceName((String) options.get(SERVICE_NAME));
            builder.username((String) options.get(USERNAME_KEY)).password((String) options.get(PASSWORD_KEY));

            builder.setBatch(isBatch);

            String passwordString = (String) options.get(PASSWORD_KEY);
            if (passwordString != null && passwordString.startsWith(PicketLinkFederationConstants.PASS_MASK_PREFIX)) {
                // password is masked
                String salt = (String) options.get(PicketLinkFederationConstants.SALT);
                if (StringUtil.isNullOrEmpty(salt))
                    throw logger.optionNotSet("Salt");

                String iCount = (String) options.get(PicketLinkFederationConstants.ITERATION_COUNT);
                if (StringUtil.isNullOrEmpty(iCount))
                    throw logger.optionNotSet("Iteration Count");

                int iterationCount = Integer.parseInt(iCount);
                try {
                    builder.password(StringUtil.decode(passwordString, salt, iterationCount));
                } catch (Exception e) {
                    throw logger.unableToDecodePasswordError("Unable to decode password:" + passwordString);
                }
            }
            return builder;
        }
    }

    protected void useCredentialsFromCallback(final Builder builder) throws LoginException {
        final NameCallback nameCallback = new NameCallback("user:");
        final PasswordCallback passwordCallback = new PasswordCallback("password:", true);
        try {
            getCallbackHandler().handle(new Callback[] { nameCallback, passwordCallback });
            String userNameStr = nameCallback.getName();
            if (StringUtil.isNotNull(userNameStr)) {
                builder.username(userNameStr);
            } else {
                logger.trace("UserName from callback is null");
            }
            char[] passChars = passwordCallback.getPassword();
            if (passChars != null) {
                builder.password(new String(passChars));
            } else {
                logger.trace("Password from callback is null");
            }
        } catch (final IOException e) {
            throw logger.authLoginError(e);
        } catch (final UnsupportedCallbackException e) {
            throw logger.authLoginError(e);
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private void setPasswordStackingCredentials(final Builder builder) {
        final Map sharedState = this.sharedState;
        sharedState.put("javax.security.auth.login.name", builder.getUsername());
        sharedState.put("javax.security.auth.login.password", builder.getPassword());
    }

    protected void useCredentialsFromSharedState(final Builder builder) {
        builder.username(getSharedUsername()).password(new String(getSharedPassword()));
    }

    /**
     * This method allows subclassed to retreive configuration options map and set on the builder.
     *
     * @param builder
     * @param options
     */
    protected void useCredentialsFromOptions(Builder builder, Map<String, ?> options2) {
        // NoOp.
    }

    /**
     * This method gives users a chance to override how the {@link STSClientConfig} is created. For example some users might
     * perfer to not use a file containing the configuration properties, which is the default, but instead have the
     * configuration options in the login modules configuration directly.
     *
     * @param options The options passed to the initialize method.
     * @return {@link STSClientConfig} The configuration for STSClient.
     */
    protected STSClientConfig getConfiguration(final Map<String, ?> options) {
        final String configFile = getRequiredOption(options, STS_CONFIG_FILE);
        return new STSClientConfig.Builder(configFile).build();
    }

    protected STSClient createWSTrustClient(final STSClientConfig config) {
        try {
            return STSClientFactory.getInstance(maxClientsInPool).create(initialNumberOfClients, config);
        } catch (final Exception e) {
            throw logger.authCouldNotCreateWSTrustClient(e);
        }
    }

    protected String getRequiredOption(final Map<String, ?> options, final String optionName) {
        final String option = (String) options.get(optionName);
        if (option == null)
            throw logger.optionNotSet(optionName);

        return option;
    }

    protected boolean isSuccess() {
        return success;
    }

    protected void setSuccess(boolean success) {
        this.success = success;
    }

    protected Subject getSubject() {
        return subject;
    }

    protected CallbackHandler getCallbackHandler() {
        return callbackHandler;
    }

    protected void setSamlToken(final Element samlToken) {
        this.samlToken = samlToken;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected void setSharedToken(final Object token) {
        if (sharedState == null)
            return;
        /*
         * This is hidious but must be done since the signature of initialize in LoginModule is: public void initialize(final
         * Subject subject, final CallbackHandler callbackHandler, final Map<String, ?> sharedState, final Map<String, ?>
         * options) Notice how sharedState is defined. This means that it will not be possible to put anything into that map
         * without bypassing generics.
         */
        // Cast the shartState to a raw map
        final Map state = sharedState;
        // Put the Token into the shared state map
        state.put(SHARED_TOKEN, token);
    }

    /**
     * Gets Security Token from the share state map if one was made available by a previous LM in the stack.
     *
     * @return Object A security token if one was stored in the shared state map. Or null if one does not exist.
     */
    protected Object getSharedToken() {
        if (sharedState == null)
            return null;

        return sharedState.get(SHARED_TOKEN);
    }

    /**
     * Gets the options provided to this LM in it's {@link #initialize(Subject, CallbackHandler, Map, Map)}.
     *
     * @return Map<String, ?> The options map.
     */
    protected Map<String, ?> getOptions() {
        return options;
    }

    protected String getSharedUsername() {
        if (sharedState == null)
            return null;

        Object sharedName = sharedState.get("javax.security.auth.login.name");
        if (sharedName == null) {
            return null;
        } else if (sharedName instanceof String) {
            return (String)sharedName;
        }
        else if (sharedName instanceof Principal) {
            return ((Principal)sharedName).getName();
        }
       
        // TODO: change to proper message
        throw new RuntimeException("sharedState javax.security.auth.login.name is supposed to contain String or Principal, but contains " + sharedName.getClass().getName());
    }

    protected char[] getSharedPassword() {
        if (sharedState == null)
            return null;

        final Object object = sharedState.get("javax.security.auth.login.password");
        if (object instanceof char[])
            return (char[]) object;
        else if (object instanceof String)
            return ((String) object).toCharArray();

        return null;
    }

    protected boolean isUseFirstPass() {
        return useFirstPass;
    }

    protected boolean isUsePasswordStacking() {
        return passwordStacking;
    }

    protected boolean isUseOptionsConfig() {
        return useOptionsCredentials;
    }

    private void clearState() {
        removeAllSamlCredentials(subject);
        samlToken = null;
    }

    public static void removeAllSamlCredentials(final Subject subject) {
        final Set<SamlCredential> samlCredentials = subject.getPublicCredentials(SamlCredential.class);
        if (!samlCredentials.isEmpty()) {
            subject.getPublicCredentials().removeAll(samlCredentials);
        }
    }

    @SuppressWarnings("deprecation")
    protected void populateSubject() {
        MappingManager mappingManager = getMappingManager();
        if (mappingManager == null) {
            return;
        }

        MappingContext<Principal> principalMappingContext = null;
        MappingContext<RoleGroup> roleMappingContext = null;
        try {
            principalMappingContext = mappingManager.getMappingContext(MappingType.PRINCIPAL.toString());
        } catch (NoSuchMethodError nse) {
            principalMappingContext = mappingManager.getMappingContext(Principal.class);
        }

        try {
            roleMappingContext = mappingManager.getMappingContext(MappingType.ROLE.toString());
        } catch (NoSuchMethodError nse) {
            roleMappingContext = mappingManager.getMappingContext(RoleGroup.class);
        }

        Map<String, Object> contextMap = new HashMap<String, Object>();
        contextMap.put(SHARED_TOKEN, this.samlToken);

        AssertionType assertion = null;
        try {
            assertion = SAMLUtil.fromElement(samlToken);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        if (principalMappingContext != null) {
            principalMappingContext.performMapping(contextMap, null);
            Principal principal = principalMappingContext.getMappingResult().getMappedObject();
            subject.getPrincipals().add(principal);

            // If the user has configured cache invalidation of subject based on saml token expiry
            if (enableCacheInvalidation) {
                TimeCacheExpiry cacheExpiry = JBossAuthCacheInvalidationFactory.getCacheExpiry();

                XMLGregorianCalendar expiry = AssertionUtil.getExpiration(assertion);
                if (expiry != null) {
                    cacheExpiry.register(securityDomain, expiry.toGregorianCalendar().getTime(), principal);
                } else {
                    logger.samlAssertionWithoutExpiration(assertion.getID());
                }
            }
        }

        if (roleMappingContext != null) {
            roleMappingContext.performMapping(contextMap, null);
            RoleGroup group = roleMappingContext.getMappingResult().getMappedObject();

            SimpleGroup rolePrincipal = new SimpleGroup(group.getRoleName());

            for (Role role : group.getRoles()) {
                rolePrincipal.addMember(new SimplePrincipal(role.getRoleName()));
            }
            subject.getPrincipals().add(rolePrincipal);
        } else {
            List<String> roleKeys = new ArrayList<String>();
            roleKeys.addAll(StringUtil.tokenize(roleKey));

            List<String> roles = AssertionUtil.getRoles(assertion, roleKeys);
            if (roles.size() > 0) {
                SimpleGroup group = new SimpleGroup(SecurityConstants.ROLES_IDENTIFIER);
                for (String role : roles) {
                    group.addMember(new SimplePrincipal(role));
                }
                subject.getPrincipals().add(group);
            }
        }

        if (injectCallerPrincipalGroup) {
            Group callerPrincipal = new SimpleGroup("CallerPrincipal");
            List<String> roles = AssertionUtil.getRoles(assertion, null);
            for (String role : roles) {
                callerPrincipal.addMember(new SimplePrincipal(role));
            }
            subject.getPrincipals().add(callerPrincipal);
        }
    }

    protected MappingManager getMappingManager() {
        SecurityContext securityContext = SecurityActions.getSecurityContext();
        if (securityContext == null) {
            return null;
        } else {
            return securityContext.getMappingManager();
        }
    }
}
TOP

Related Classes of org.picketlink.identity.federation.core.wstrust.auth.AbstractSTSLoginModule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.