Package org.jasig.cas.web.view

Source Code of org.jasig.cas.web.view.Saml10SuccessResponseView

/*
* Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license
* distributed with this file and available online at
* http://www.ja-sig.org/products/cas/overview/license/
*/
package org.jasig.cas.web.view;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;

import org.jasig.cas.authentication.Authentication;
import org.jasig.cas.authentication.SamlAuthenticationMetaDataPopulator;
import org.jasig.cas.authentication.principal.SamlService;
import org.jasig.cas.authentication.principal.Service;
import org.jasig.cas.validation.Assertion;
import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLAttribute;
import org.opensaml.SAMLAttributeStatement;
import org.opensaml.SAMLAudienceRestrictionCondition;
import org.opensaml.SAMLAuthenticationStatement;
import org.opensaml.SAMLException;
import org.opensaml.SAMLNameIdentifier;
import org.opensaml.SAMLResponse;
import org.opensaml.SAMLSubject;

/**
* Implementation of a view to return a SAML response and assertion, based on
* the SAML 1.1 specification.
* <p>
* If an AttributePrincipal is supplied, then the assertion will include the
* attributes from it (assuming a String key/Object value pair). The only
* Authentication attribute it will look at is the authMethod (if supplied).
* <p>
* Note that this class will currently not handle proxy authentication.
* <p>
* Note: This class currently expects a bean called "ServiceRegistry" to exist.
*
* @author Scott Battaglia
* @version $Revision: 21756 $ $Date: 2010-09-25 12:42:56 -0400 (Sat, 25 Sep 2010) $
* @since 3.1
*/
public class Saml10SuccessResponseView extends AbstractCasView {

    /** Namespace for custom attributes. */
    private static final String NAMESPACE = "http://www.ja-sig.org/products/cas/";

    private static final String DEFAULT_ENCODING = "UTF-8";

    /** The issuer, generally the hostname. */
    @NotNull
    private String issuer;

    /** The amount of time in milliseconds this is valid for. */
    private long issueLength = 30000;

    @NotNull
    private String encoding = DEFAULT_ENCODING;

    @Override
    protected void renderMergedOutputModel(final Map model,
        final HttpServletRequest request, final HttpServletResponse response) throws Exception {

        try {
            final Assertion assertion = getAssertionFrom(model);
            final Authentication authentication = assertion.getChainedAuthentications().get(0);
            final Date currentDate = new Date();
            final String authenticationMethod = (String) authentication.getAttributes().get(SamlAuthenticationMetaDataPopulator.ATTRIBUTE_AUTHENTICATION_METHOD);
            final Service service = assertion.getService();
            final SAMLResponse samlResponse = new SAMLResponse(null, service.getId(), new ArrayList<Object>(), null);

            samlResponse.setIssueInstant(currentDate);

            // this should be true, but we never enforced it, so we need to check to be safe
            if (service instanceof SamlService) {
                final SamlService samlService = (SamlService) service;

                if (samlService.getRequestID() != null) {
                    samlResponse.setInResponseTo(samlService.getRequestID());
                }
            }

            final SAMLAssertion samlAssertion = new SAMLAssertion();
            samlAssertion.setIssueInstant(currentDate);
            samlAssertion.setIssuer(this.issuer);
            samlAssertion.setNotBefore(currentDate);
            samlAssertion.setNotOnOrAfter(new Date(currentDate.getTime()
                + this.issueLength));

            final SAMLAudienceRestrictionCondition samlAudienceRestrictionCondition = new SAMLAudienceRestrictionCondition();
            samlAudienceRestrictionCondition.addAudience(service.getId());

            final SAMLAuthenticationStatement samlAuthenticationStatement = new SAMLAuthenticationStatement();
            samlAuthenticationStatement.setAuthInstant(authentication
                .getAuthenticatedDate());
            samlAuthenticationStatement
                .setAuthMethod(authenticationMethod != null
                    ? authenticationMethod
                    : SAMLAuthenticationStatement.AuthenticationMethod_Unspecified);

            samlAuthenticationStatement
                .setSubject(getSamlSubject(authentication));

            if (!authentication.getPrincipal().getAttributes().isEmpty()) {
                final SAMLAttributeStatement attributeStatement = new SAMLAttributeStatement();
   
                attributeStatement.setSubject(getSamlSubject(authentication));
                samlAssertion.addStatement(attributeStatement);

                for (final Entry<String, Object> e : authentication.getPrincipal().getAttributes().entrySet()) {
                    final SAMLAttribute attribute = new SAMLAttribute();
                    attribute.setName(e.getKey());
                    attribute.setNamespace(NAMESPACE);

                    if (e.getValue() instanceof Collection<?>) {
                        final Collection<?> c = (Collection<?>) e.getValue();
                        if (c.isEmpty()) {
                            // 100323 bnoordhuis: don't add the attribute, it causes a org.opensaml.MalformedException
                            continue;
                        }
                        attribute.setValues(c);
                    } else {
                        attribute.addValue(e.getValue());
                    }
   
                    attributeStatement.addAttribute(attribute);
                }
            }

            samlAssertion.addStatement(samlAuthenticationStatement);
            samlAssertion.addCondition(samlAudienceRestrictionCondition);
            samlResponse.addAssertion(samlAssertion);

            final String xmlResponse = samlResponse.toString();

            response.setContentType("text/xml; charset=" + this.encoding);
            response.getWriter().print("<?xml version=\"1.0\" encoding=\"" + this.encoding + "\"?>");
            response.getWriter().print("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"><SOAP-ENV:Header/><SOAP-ENV:Body>");
            response.getWriter().print(xmlResponse);
            response.getWriter().print("</SOAP-ENV:Body></SOAP-ENV:Envelope>");
            response.flushBuffer();
        } catch (final Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        }
    }

    protected SAMLSubject getSamlSubject(final Authentication authentication)
        throws SAMLException {
        final SAMLSubject samlSubject = new SAMLSubject();
        samlSubject.addConfirmationMethod(SAMLSubject.CONF_ARTIFACT);
        final SAMLNameIdentifier samlNameIdentifier = new SAMLNameIdentifier();
        samlNameIdentifier.setName(authentication.getPrincipal().getId());

        samlSubject.setNameIdentifier(samlNameIdentifier);

        return samlSubject;
    }

    public void setIssueLength(final long issueLength) {
        this.issueLength = issueLength;
    }

    public void setIssuer(final String issuer) {
        this.issuer = issuer;
    }

    public void setEncoding(final String encoding) {
        this.encoding = encoding;
    }
}
TOP

Related Classes of org.jasig.cas.web.view.Saml10SuccessResponseView

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.