package org.picketlink.identity.federation.bindings.tomcat.sp; import static org.picketlink.identity.federation.core.util.StringUtil.isNotNull; import java.io.IOException; import java.io.InputStream; import java.security.Principal; import java.util.ArrayList; import java.util.List; import org.apache.catalina.LifecycleException; import org.apache.catalina.Session; import org.apache.catalina.authenticator.Constants; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.deploy.LoginConfig; import org.picketlink.identity.federation.bindings.tomcat.sp.holder.ServiceProviderSAMLContext; import org.picketlink.identity.federation.core.ErrorCodes; import org.picketlink.identity.federation.core.parsers.saml.SAMLParser; import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil; import org.picketlink.identity.federation.saml.v1.assertion.SAML11AssertionType; import org.picketlink.identity.federation.saml.v1.assertion.SAML11AuthenticationStatementType; import org.picketlink.identity.federation.saml.v1.assertion.SAML11StatementAbstractType; import org.picketlink.identity.federation.saml.v1.assertion.SAML11SubjectType; import org.picketlink.identity.federation.saml.v1.protocol.SAML11ResponseType; import org.picketlink.identity.federation.web.constants.GeneralConstants; import org.picketlink.identity.federation.web.util.RedirectBindingUtil; import org.picketlink.identity.federation.web.util.ServerDetector; /** * Authenticator for SAML 1.1 processing at the Service Provider * @author anil saldhana * @since Jul 7, 2011 */ public abstract class AbstractSAML11SPRedirectFormAuthenticator extends AbstractSPFormAuthenticator { @Override public boolean authenticate(Request request, Response response, LoginConfig loginConfig) throws IOException { String samlResponse = request.getParameter(GeneralConstants.SAML_RESPONSE_KEY); Principal principal = request.getUserPrincipal(); // If we have already authenticated the user and there is no request from IDP or logout from user if (principal != null) return true; Session session = request.getSessionInternal(true); // See if we got a response from IDP if (isNotNull(samlResponse)) { boolean isValid = false; try { isValid = this.validate(request); } catch (Exception e) { logger.samlSPHandleRequestError(e); throw new IOException(); } if (!isValid) throw new IOException(ErrorCodes.VALIDATION_CHECK_FAILED); try { InputStream base64DecodedResponse = RedirectBindingUtil.base64DeflateDecode(samlResponse); SAMLParser parser = new SAMLParser(); SAML11ResponseType saml11Response = (SAML11ResponseType) parser.parse(base64DecodedResponse); List<SAML11AssertionType> assertions = saml11Response.get(); if (assertions.size() > 1) { logger.trace("More than one assertion from IDP. Considering the first one."); } String username = null; List<String> roles = new ArrayList<String>(); SAML11AssertionType assertion = assertions.get(0); if (assertion != null) { // Get the subject List<SAML11StatementAbstractType> statements = assertion.getStatements(); for (SAML11StatementAbstractType statement : statements) { if (statement instanceof SAML11AuthenticationStatementType) { SAML11AuthenticationStatementType subStat = (SAML11AuthenticationStatementType) statement; SAML11SubjectType subject = subStat.getSubject(); username = subject.getChoice().getNameID().getValue(); } } roles = AssertionUtil.getRoles(assertion, null); } String password = ServiceProviderSAMLContext.EMPTY_PASSWORD; // Map to JBoss specific principal if ((new ServerDetector()).isJboss() || jbossEnv) { // Push a context ServiceProviderSAMLContext.push(username, roles); principal = context.getRealm().authenticate(username, password); ServiceProviderSAMLContext.clear(); } else { // tomcat env SPUtil spUtil = new SPUtil(); principal = spUtil.createGenericPrincipal(request, username, roles); } session.setNote(Constants.SESS_USERNAME_NOTE, username); session.setNote(Constants.SESS_PASSWORD_NOTE, password); request.setUserPrincipal(principal); if (saveRestoreRequest) { this.restoreRequest(request, session); } register(request, response, principal, Constants.FORM_METHOD, username, password); return true; } catch (Exception e) { logger.samlSPHandleRequestError(e); } } logger.trace("Falling back on local Form Authentication if available"); // fallback return super.authenticate(request, response, loginConfig); } protected void startPicketLink() throws LifecycleException{ super.startPicketLink(); this.spConfiguration.setBindingType("REDIRECT"); } }