a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Copyright (c) 2007 Sun Microsystems Inc. All Rights Reserved
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The contents of this file are subject to the terms
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * of the Common Development and Distribution License
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * (the License). You may not use this file except in
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * compliance with the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You can obtain a copy of the License at
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the License for the specific language governing
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * permission and limitations under the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * When distributing Covered Code, include this CDDL
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Header Notice in each file and include the License file
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If applicable, add the following below the CDDL Header,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * with the fields enclosed by brackets [] replaced by
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * your own identifying information:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * $Id: SAML11RequestedSecurityToken.java,v 1.7 2009/12/14 23:42:48 mallas Exp $
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.Assertion;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.AttributeStatement;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.AudienceRestrictionCondition;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.AuthenticationStatement;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.Conditions;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.NameIdentifier;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.Statement;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.assertion.SubjectStatement;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.common.SAMLConstants;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml.common.SAMLException;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.saml2.common.SAML2Constants;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.common.WSFederationConstants;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.common.WSFederationException;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.common.WSFederationUtils;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.jaxb.entityconfig.SPSSOConfigElement;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.jaxb.wsfederation.FederationElement;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.logging.LogUtil;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.meta.WSFederationMetaManager;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterimport com.sun.identity.wsfederation.meta.WSFederationMetaUtils;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * SAML11RequestedSecurityToken represents a concrete RequestedSecurityToken -
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * one containing a SAML 1.1 assertion.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterpublic class SAML11RequestedSecurityToken implements RequestedSecurityToken {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Just get this system property once - it should never change!
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster System.getProperty("line.separator").equals("\r\n");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster private static Debug debug = WSFederationUtils.debug;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Creates a SAML11RequestedSecurityToken given a DOM Node
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param token a DOM Node representing a RequestedSecurityToken
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public SAML11RequestedSecurityToken(Node token)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "SAML11RequestedSecurityToken.SAML11RequestedSecurityToken(Node)";
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ( ! token.getLocalName().equals("RequestedSecurityToken") ){
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster SAMLConstants.assertionSAMLNameSpaceURI + ":" +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WSFederationUtils.bundle.getString("invalidToken"));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster equals(SAMLConstants.assertionSAMLNameSpaceURI)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster && ae.getLocalName().equals(SAMLConstants.TAG_ASSERTION)))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster SAMLConstants.assertionSAMLNameSpaceURI + ":" +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WSFederationUtils.bundle.getString("invalidToken"));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message(classMethod + "found Assertion with issuer:" +
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster List signs = XMLUtils.getElementsByTagNameNS1(ae,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message(classMethod + "found signature");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "included more than one Signature element.");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WSFederationUtils.bundle.getString("moreElement"));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Creates a SAML11RequestedSecurityToken.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param realm the realm of the entities.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param spEntityId service provider entity ID - consumer of the token.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param idpEntityId identity provifer entity ID - issuer of the token.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param notBeforeSkew number of seconds to subtract from current time
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * to form Assertion notBefore time.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param effectiveTime length of time, in seconds, from Assertion's
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * notBefore time to its notOnOrAfter time.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param certAlias alias of the signing certificate. null means do not
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * sign the assertion
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param authMethod mechanism by which the subject authenticated to the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * identity provider
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param authInstant time at which the subject authenticated to the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * identity provider
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param ni SAML 1.1 NameIdentitifer for the subject
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param attributes List of com.sun.identity.saml.assertion.Attribute to
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * include in the Assertion
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @throws com.sun.identity.wsfederation.common.WSFederationException in
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * case of error.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public SAML11RequestedSecurityToken(String realm, String spEntityId,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String idpEntityId, int notBeforeSkew, int effectiveTime,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String certAlias, String authMethod, Date authInstant,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String classMethod = "SAML11RequestedSecurityToken."+
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster "SAML11RequestedSecurityToken(String*)";
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster statements.add(new AuthenticationStatement(authMethod, authInstant,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((attributes != null) && (!attributes.isEmpty())) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster statements.add(new AttributeStatement(sub, attributes));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Date notBefore = new Date(issueInstant.getTime() - skewPeriod);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Date notAfter = new Date(issueInstant.getTime() + period);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster metaManager.getEntityDescriptor(realm, idpEntityId);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster metaManager.getEntityDescriptor(realm, spEntityId);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String issuer = metaManager.getTokenIssuerName(idp);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster List<String> targets = new ArrayList<String>();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster targets.add(metaManager.getTokenIssuerName(sp));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Conditions cond = new Conditions(notBefore, notAfter, null, arc);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster assertion = new Assertion(null /* assertionID */, issuer,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String[] data = { assertion.toString(true, true)};
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @return the unique identifier of the RequestedSecurityToken. Maps to the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * SAML 1.1 Assertion's AssertionID
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @return the issuer of the RequestedSecurityToken.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @return a list of attributes of type
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * <code>com.sun.identity.saml.assertion.Attribute</code>
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Iterator stmtIter = assertion.getStatement().iterator();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Statement statement = (Statement) stmtIter.next();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @return the underlying SAML 1.1 Assertion
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * This method marshalls the token, returning a String comprising the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * textual XML representation.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @return The textual XML representation of the token.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return XMLUtils.print(SAMLUtils.getCanonicalElement(
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Pass (true,true) to assertion.toString so we get namespace
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String assertionString = assertion.toString(true,true);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Xalan uses the line.separator system property when creating
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // output - i.e. on Windows, uses \r\n
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // We ALWAYS want \n, or signatures break in ADFS - issue # 3927
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // NOTE - transformer.setOutputProperty(
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // "{http://xml.apache.org/xalan}line-separator","\n");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // DOESN'T WORK WITH com.sun.org.apache.xalan.internal
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // Doing this here rather than in XMLUtils.print(Node, String)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // minimizes the scope of the change.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster assertionString = assertionString.replaceAll("\r\n", "\n");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Verifies the token's validity, checking the signature, validity period
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param realm the realm of the local entity
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param hostEntityId the local entity ID
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param timeskew permitted skew between service provider and identity
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * provider clocks, in seconds
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @return a Map of relevant data including Subject and the List of
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Assertions.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @throws com.sun.identity.wsfederation.common.WSFederationException in
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * case of any error - invalid token signature, token expired etc.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster public Map<String,Object> verifyToken(String realm, String hostEntityId,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster String classMethod = "SAML11RequestedSecurityToken.verifyToken";
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // check that assertion issuer is trusted by the local entity
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster metaManager.getEntityByTokenIssuerName(realm, issuer);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster {LogUtil.isErrorLoggable(Level.FINER)? this.toString() :
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WSFederationUtils.bundle.getString("untrustedIssuer"));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster metaManager.getSPSSOConfig(realm, hostEntityId);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.error(classMethod + "cannot find configuration for SP "
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster throw new WSFederationException("unableToFindSPConfiguration");
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // By default, we want to sign assertions
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster boolean wantAssertionSigned = (strWantAssertionSigned != null)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (!WSFederationUtils.isSignatureValid(assertion, realm,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // isSignatureValid will log the error
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WSFederationUtils.bundle.getString("invalidSignature"));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // TODO: check AudienceRestrictionCondition
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Iterator stmtIter = assertion.getStatement().iterator();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Statement statement = (Statement) stmtIter.next();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster {LogUtil.isErrorLoggable(Level.FINER)? this.toString() :
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WSFederationUtils.bundle.getString("missingSubject"));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // must be valid (timewise)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (!WSFederationUtils.isTimeValid(assertion, timeskew)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster // isTimeValid will log the error
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster WSFederationUtils.bundle.getString("timeInvalid"));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Map<String,Object> attrMap = new HashMap<String,Object>();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster attrMap.put(SAML2Constants.SUBJECT, assertionSubject);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster attrMap.put(SAML2Constants.POST_ASSERTION, assertion);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster attrMap.put(SAML2Constants.ASSERTIONS, assertions);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster attrMap.put(SAML2Constants.AUTH_LEVEL, new Integer(authLevel));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster Date sessionNotOnOrAfter = assertion.getConditions().getNotOnorAfter();
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster long maxSessionTime = (sessionNotOnOrAfter.getTime() -
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster debug.message(classMethod +" Attribute Map : " + attrMap);