Search in sources :

Example 6 with Subject

use of com.sun.identity.saml2.assertion.Subject in project OpenAM by OpenRock.

the class IDPSSOUtil method getAssertion.

/**
     * Returns a <code>SAML Assertion</code> object
     *
     * @throws SAML2Exception if the operation is not successful
     * @param request The HTTP request.
     * @param session The user's session object.
     * @param authnReq The <code>AuthnRequest</code> object.
     * @param recipientEntityID The entity ID of the response recipient.
     * @param idpEntityID The entity ID of the identity provider.
     * @param realm The realm name.
     * @param nameIDFormat The <code>NameIDFormat</code>.
     * @param acsURL The <code>ACS</code> service <code>url</code>.
     * @param affiliationID AffiliationID for IDP initiated SSO.
     * @param matchingAuthnContext the <code>AuthnContext</code> used to find authentication type and scheme.
     * @return the <code>SAML Assertion</code> object.
     * @throws SAML2Exception if the operation is not successful.
     */
private static Assertion getAssertion(HttpServletRequest request, Object session, AuthnRequest authnReq, String recipientEntityID, String idpEntityID, String idpMetaAlias, String realm, String nameIDFormat, String acsURL, String affiliationID, AuthnContext matchingAuthnContext) throws SAML2Exception {
    String classMethod = "IDPSSOUtil.getAssertion: ";
    Assertion assertion = AssertionFactory.getInstance().createAssertion();
    String assertionID = SAML2Utils.generateID();
    assertion.setID(assertionID);
    assertion.setVersion(SAML2Constants.VERSION_2_0);
    assertion.setIssueInstant(new Date());
    Issuer issuer = AssertionFactory.getInstance().createIssuer();
    issuer.setValue(idpEntityID);
    assertion.setIssuer(issuer);
    List statementList = new ArrayList();
    NewBoolean isNewSessionIndex = new NewBoolean();
    AuthnStatement authnStatement = null;
    IDPSession idpSession = null;
    String sessionIndex = null;
    String sessionID = sessionProvider.getSessionID(session);
    synchronized (sessionID) {
        authnStatement = getAuthnStatement(request, session, isNewSessionIndex, authnReq, idpEntityID, realm, matchingAuthnContext);
        if (authnStatement == null) {
            return null;
        }
        sessionIndex = authnStatement.getSessionIndex();
        if (isNewSessionIndex.getValue()) {
            if (SAML2Utils.debug.messageEnabled()) {
                SAML2Utils.debug.message(classMethod + "This is a new IDP session with sessionIndex=" + sessionIndex + ", and sessionID=" + sessionID);
            }
            idpSession = (IDPSession) IDPCache.idpSessionsBySessionID.get(sessionProvider.getSessionID(session));
            if (idpSession == null) {
                idpSession = new IDPSession(session);
            }
            // Set the metaAlias in the IDP session object
            idpSession.setMetaAlias(idpMetaAlias);
            IDPCache.idpSessionsByIndices.put(sessionIndex, idpSession);
            if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
                saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
            }
        } else {
            idpSession = (IDPSession) IDPCache.idpSessionsByIndices.get(sessionIndex);
        }
    }
    if (isNewSessionIndex.getValue()) {
        if (SAML2Utils.debug.messageEnabled()) {
            SAML2Utils.debug.message(classMethod + "a new IDP session has been saved in cache, " + "with sessionIndex=" + sessionIndex);
        }
        try {
            sessionProvider.addListener(session, sessionListener);
        } catch (SessionException e) {
            SAML2Utils.debug.error(classMethod + "Unable to add session listener.");
        }
    } else {
        if (idpSession == null && SAML2FailoverUtils.isSAML2FailoverEnabled()) {
            // Read from SAML2 Token Repository
            IDPSessionCopy idpSessionCopy = null;
            try {
                idpSessionCopy = (IDPSessionCopy) SAML2FailoverUtils.retrieveSAML2Token(sessionIndex);
            } catch (SAML2TokenRepositoryException se) {
                SAML2Utils.debug.error(classMethod + "Unable to obtain IDPSessionCopy from the SAML2 Token Repository for sessionIndex:" + sessionIndex, se);
            }
            // Copy back to IDPSession
            if (idpSessionCopy != null) {
                idpSession = new IDPSession(idpSessionCopy);
            } else {
                SAML2Utils.debug.error("IDPSessionCopy is null");
                throw new SAML2Exception(SAML2Utils.bundle.getString("IDPSessionIsNULL"));
            }
        } else if ((idpSession == null) && (!SAML2FailoverUtils.isSAML2FailoverEnabled())) {
            SAML2Utils.debug.error("IDPSession is null; SAML2 failover" + "is disabled");
            throw new SAML2Exception(SAML2Utils.bundle.getString("IDPSessionIsNULL"));
        } else {
            if (SAML2Utils.debug.messageEnabled()) {
                SAML2Utils.debug.message(classMethod + "This is an existing IDP session with sessionIndex=" + sessionIndex + ", and sessionID=" + sessionProvider.getSessionID(idpSession.getSession()));
            }
        }
    }
    statementList.add(authnStatement);
    AttributeStatement attrStatement = getAttributeStatement(session, idpEntityID, recipientEntityID, realm);
    if (attrStatement != null) {
        List attrStatementList = new ArrayList();
        attrStatementList.add(attrStatement);
        assertion.setAttributeStatements(attrStatementList);
    }
    // get the assertion effective time (in seconds)
    int effectiveTime = getEffectiveTime(realm, idpEntityID);
    // get the NotBefore skew (in seconds)
    int notBeforeSkewTime = getNotBeforeSkewTime(realm, idpEntityID);
    // get the subject element
    Subject subject = getSubject(session, authnReq, acsURL, nameIDFormat, realm, idpEntityID, recipientEntityID, effectiveTime, affiliationID);
    // register (spEntityID, nameID) with the sso token
    // for later logout use 
    String spEntityID = null;
    if (authnReq != null) {
        spEntityID = authnReq.getIssuer().getValue();
    } else {
        spEntityID = recipientEntityID;
    }
    NameIDandSPpair pair = new NameIDandSPpair(subject.getNameID(), spEntityID);
    synchronized (IDPCache.idpSessionsByIndices) {
        List<NameIDandSPpair> list = idpSession.getNameIDandSPpairs();
        String id;
        if (authnReq != null) {
            id = authnReq.getIssuer().getValue();
        } else {
            id = spEntityID;
        }
        boolean found = false;
        for (NameIDandSPpair nameIDandSPpair : list) {
            if (nameIDandSPpair.getSPEntityID().equals(id)) {
                found = true;
                break;
            }
        }
        if (!found) {
            list.add(pair);
        }
    }
    assertion.setAuthnStatements(statementList);
    assertion.setSubject(subject);
    Conditions conditions = getConditions(recipientEntityID, notBeforeSkewTime, effectiveTime);
    assertion.setConditions(conditions);
    String discoBootstrapEnabled = getAttributeValueFromIDPSSOConfig(realm, idpEntityID, SAML2Constants.DISCO_BOOTSTRAPPING_ENABLED);
    if ((discoBootstrapEnabled != null) && discoBootstrapEnabled.equalsIgnoreCase("true")) {
        List attrStatementList = assertion.getAttributeStatements();
        if (attrStatementList == null) {
            attrStatementList = new ArrayList();
            assertion.setAttributeStatements(attrStatementList);
        }
        DiscoveryBootstrap bootstrap = new DiscoveryBootstrap(session, subject, authnStatement.getAuthnContext().getAuthnContextClassRef(), spEntityID, realm);
        attrStatementList.add(bootstrap.getBootstrapStatement());
        assertion.setAdvice(bootstrap.getCredentials());
    }
    if (assertionCacheEnabled(realm, idpEntityID)) {
        String userName = null;
        try {
            userName = sessionProvider.getPrincipalName(session);
        } catch (SessionException se) {
            SAML2Utils.debug.error(classMethod + "Unable to get principal name from the session.", se);
            throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSSOToken"));
        }
        String cacheKey = userName.toLowerCase();
        List assertions = (List) IDPCache.assertionCache.get(cacheKey);
        if (assertions == null) {
            synchronized (IDPCache.assertionCache) {
                assertions = (List) IDPCache.assertionCache.get(cacheKey);
                if (assertions == null) {
                    assertions = new ArrayList();
                    IDPCache.assertionCache.put(cacheKey, assertions);
                }
            }
        }
        synchronized (assertions) {
            assertions.add(assertion);
        }
        IDPCache.assertionByIDCache.put(assertionID, assertion);
        if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
            try {
                SAML2FailoverUtils.saveSAML2Token(assertionID, cacheKey, assertion.toXMLString(true, true), conditions.getNotOnOrAfter().getTime() / 1000);
                if (SAML2Utils.debug.messageEnabled()) {
                    SAML2Utils.debug.message(classMethod + "Saving Assertion to SAML2 Token Repository. ID = " + assertionID);
                }
            } catch (SAML2TokenRepositoryException se) {
                SAML2Utils.debug.error(classMethod + "Unable to save Assertion to the SAML2 Token Repository", se);
            }
        }
    }
    //  Save to SAML2 Token Repository
    try {
        if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
            long sessionExpireTime = System.currentTimeMillis() / 1000 + (sessionProvider.getTimeLeft(session));
            SAML2FailoverUtils.saveSAML2TokenWithoutSecondaryKey(sessionIndex, new IDPSessionCopy(idpSession), sessionExpireTime);
        }
        if (SAML2Utils.debug.messageEnabled()) {
            SAML2Utils.debug.message(classMethod + "SAVE IDPSession!");
        }
    } catch (SessionException se) {
        SAML2Utils.debug.error(classMethod + "Unable to get left-time from the session.", se);
        throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSSOToken"));
    } catch (SAML2TokenRepositoryException se) {
        SAML2Utils.debug.error(classMethod + "Unable to save IDPSession to the SAML2 Token Repository", se);
    }
    return assertion;
}
Also used : Issuer(com.sun.identity.saml2.assertion.Issuer) EncryptedAssertion(com.sun.identity.saml2.assertion.EncryptedAssertion) Assertion(com.sun.identity.saml2.assertion.Assertion) ArrayList(java.util.ArrayList) NewBoolean(com.sun.identity.saml2.common.NewBoolean) SessionException(com.sun.identity.plugin.session.SessionException) Date(java.util.Date) Subject(com.sun.identity.saml2.assertion.Subject) Conditions(com.sun.identity.saml2.assertion.Conditions) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) AttributeStatement(com.sun.identity.saml2.assertion.AttributeStatement) AuthnStatement(com.sun.identity.saml2.assertion.AuthnStatement) List(java.util.List) ArrayList(java.util.ArrayList) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException)

Example 7 with Subject

use of com.sun.identity.saml2.assertion.Subject in project OpenAM by OpenRock.

the class IDPSSOUtil method signAndEncryptResponseComponents.

/**
     * Signs and encrypts the components of a <code>SAML Response</code>
     * based on the service provider meta data. If the flag of
     * encrypting <code>Assertion</code> is on, then the embedded
     * <code>Assertion</code> object will be encrypted; if the flag
     * of encrypting <code>Assertion</code> is off and the flag of
     * encrypting <code>NameID</code> is on, then the <code>NameID</code>
     * embedded in the <code>Assertion</code> will be encrypted; if the
     * flag of encrypting <code>Assertion</code> is off and the flag of
     * encrypting <code>Attribute</code> is on, then the
     * <code>Attribute</code> embedded in the <code>Assertion</code>
     * will be encrypted. If the flag signAssertion is on, then the
     * <code>Assertion</code> will be signed. It will be signed before
     * it is encrypted and after its embedded <code>NameID</code> or
     * <code>Attribute</code> is encrypted.
     *
     * @param realm         the realm name of the identity provider
     * @param spEntityID    the entity id of the service provider
     * @param idpEntityID   the entity id of the identity provider
     * @param res           The <code>Response</code> whose components may be
     *                      encrypted based on the service provider meta data setting
     * @param signAssertion A flag to indicate if <code>Assertion</code>
     *                      signing is required
     */
static void signAndEncryptResponseComponents(String realm, String spEntityID, String idpEntityID, Response res, boolean signAssertion) throws SAML2Exception {
    String classMethod = "IDPSSOUtil.signAndEncryptResponseComponents: ";
    boolean toEncryptAssertion = false;
    boolean toEncryptNameID = false;
    boolean toEncryptAttribute = false;
    if (res == null) {
        return;
    }
    List assertions = res.getAssertion();
    if ((assertions == null) || (assertions.size() == 0)) {
        return;
    }
    Assertion assertion = (Assertion) assertions.get(0);
    // get the encryption related flags from the SP Entity Config
    String wantAssertionEncrypted = SAML2Utils.getAttributeValueFromSSOConfig(realm, spEntityID, SAML2Constants.SP_ROLE, SAML2Constants.WANT_ASSERTION_ENCRYPTED);
    toEncryptAssertion = (wantAssertionEncrypted != null) && (wantAssertionEncrypted.equals(SAML2Constants.TRUE));
    if (!toEncryptAssertion) {
        String wantNameIDEncrypted = SAML2Utils.getAttributeValueFromSSOConfig(realm, spEntityID, SAML2Constants.SP_ROLE, SAML2Constants.WANT_NAMEID_ENCRYPTED);
        toEncryptNameID = (wantNameIDEncrypted != null) && (wantNameIDEncrypted.equals(SAML2Constants.TRUE));
        String wantAttributeEncrypted = SAML2Utils.getAttributeValueFromSSOConfig(realm, spEntityID, SAML2Constants.SP_ROLE, SAML2Constants.WANT_ATTRIBUTE_ENCRYPTED);
        toEncryptAttribute = (wantAttributeEncrypted != null) && (wantAttributeEncrypted.equals(SAML2Constants.TRUE));
    }
    if ((!toEncryptAssertion) && (!toEncryptNameID) && (!toEncryptAttribute)) {
        // all encryption flags are off, no encryption needed
        if (signAssertion) {
            signAssertion(realm, idpEntityID, assertion);
            List assertionList = new ArrayList();
            assertionList.add(assertion);
            res.setAssertion(assertionList);
        }
        return;
    }
    SPSSODescriptorElement spSSODescriptorElement = getSPSSODescriptor(realm, spEntityID, classMethod);
    // get the encryption information
    EncInfo encInfo = KeyUtil.getEncInfo(spSSODescriptorElement, spEntityID, SAML2Constants.SP_ROLE);
    if (encInfo == null) {
        SAML2Utils.debug.error(classMethod + "failed to get service provider encryption key info.");
        throw new SAML2Exception(SAML2Utils.bundle.getString("UnableToFindEncryptKeyInfo"));
    }
    if (toEncryptAssertion) {
        // sign assertion first, then encrypt the assertion
        if (signAssertion) {
            signAssertion(realm, idpEntityID, assertion);
        }
        // we only encrypt the Assertion
        EncryptedAssertion encryptedAssertion = assertion.encrypt(encInfo.getWrappingKey(), encInfo.getDataEncAlgorithm(), encInfo.getDataEncStrength(), spEntityID);
        if (encryptedAssertion == null) {
            SAML2Utils.debug.error(classMethod + "failed to encrypt the assertion.");
            throw new SAML2Exception(SAML2Utils.bundle.getString("FailedToEncryptAssertion"));
        }
        List assertionList = new ArrayList();
        assertionList.add(encryptedAssertion);
        res.setEncryptedAssertion(assertionList);
        // reset assertion list
        res.setAssertion(new ArrayList());
        if (SAML2Utils.debug.messageEnabled()) {
            SAML2Utils.debug.message(classMethod + "Assertion encrypted.");
        }
    } else {
        // assertion if applicable
        if (toEncryptNameID) {
            // we need to encrypt the NameID            
            Subject subject = assertion.getSubject();
            if (subject == null) {
                return;
            }
            NameID nameID = subject.getNameID();
            if (nameID == null) {
                return;
            }
            EncryptedID encryptedNameID = nameID.encrypt(encInfo.getWrappingKey(), encInfo.getDataEncAlgorithm(), encInfo.getDataEncStrength(), spEntityID);
            if (encryptedNameID == null) {
                SAML2Utils.debug.error(classMethod + "failed to encrypt the NameID.");
                throw new SAML2Exception(SAML2Utils.bundle.getString("FailedToEncryptNameID"));
            }
            subject.setEncryptedID(encryptedNameID);
            // reset NameID
            subject.setNameID(null);
            assertion.setSubject(subject);
            if (SAML2Utils.debug.messageEnabled()) {
                SAML2Utils.debug.message(classMethod + "NameID encrypted.");
            }
        }
        if (toEncryptAttribute) {
            // we need to encrypt the Attribute
            List attributeStatements = assertion.getAttributeStatements();
            if ((attributeStatements != null) && (attributeStatements.size() > 0)) {
                int asSize = attributeStatements.size();
                // to hold all the AttributeStatements
                List stmts = new ArrayList();
                for (int i = 0; i < asSize; i++) {
                    AttributeStatement attributeStatement = (AttributeStatement) attributeStatements.get(i);
                    List attributes = attributeStatement.getAttribute();
                    if ((attributes == null) || (attributes.size() == 0)) {
                        continue;
                    }
                    int aSize = attributes.size();
                    // holds all the encrypted Attributes in this statement
                    List eaList = new ArrayList();
                    for (int j = 0; j < aSize; j++) {
                        Attribute attribute = (Attribute) attributes.get(j);
                        EncryptedAttribute encryptedAttribute = attribute.encrypt(encInfo.getWrappingKey(), encInfo.getDataEncAlgorithm(), encInfo.getDataEncStrength(), spEntityID);
                        if (encryptedAttribute == null) {
                            SAML2Utils.debug.error(classMethod + "failed to encrypt the Attribute.");
                            throw new SAML2Exception(SAML2Utils.bundle.getString("FailedToEncryptAttribute"));
                        }
                        eaList.add(encryptedAttribute);
                    }
                    attributeStatement.setEncryptedAttribute(eaList);
                    attributeStatement.setAttribute(new ArrayList());
                    stmts.add(attributeStatement);
                }
                assertion.setAttributeStatements(stmts);
                if (SAML2Utils.debug.messageEnabled()) {
                    SAML2Utils.debug.message(classMethod + "Attribute encrypted.");
                }
            }
        }
        if (signAssertion) {
            signAssertion(realm, idpEntityID, assertion);
        }
        List assertionList = new ArrayList();
        assertionList.add(assertion);
        res.setAssertion(assertionList);
    }
}
Also used : EncryptedAttribute(com.sun.identity.saml2.assertion.EncryptedAttribute) NameID(com.sun.identity.saml2.assertion.NameID) Attribute(com.sun.identity.saml2.assertion.Attribute) EncryptedAttribute(com.sun.identity.saml2.assertion.EncryptedAttribute) SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) EncryptedAssertion(com.sun.identity.saml2.assertion.EncryptedAssertion) Assertion(com.sun.identity.saml2.assertion.Assertion) ArrayList(java.util.ArrayList) EncryptedID(com.sun.identity.saml2.assertion.EncryptedID) Subject(com.sun.identity.saml2.assertion.Subject) EncInfo(com.sun.identity.saml2.key.EncInfo) SAML2Exception(com.sun.identity.saml2.common.SAML2Exception) EncryptedAssertion(com.sun.identity.saml2.assertion.EncryptedAssertion) AttributeStatement(com.sun.identity.saml2.assertion.AttributeStatement) List(java.util.List) ArrayList(java.util.ArrayList)

Example 8 with Subject

use of com.sun.identity.saml2.assertion.Subject in project OpenAM by OpenRock.

the class IDPProxyUtil method getNameIDFormat.

private static String getNameIDFormat(Response res) {
    if (res == null) {
        return null;
    }
    List assertions = res.getAssertion();
    if ((assertions == null) || (assertions.size() == 0)) {
        return null;
    }
    Assertion assertion = (Assertion) assertions.get(0);
    Subject subject = assertion.getSubject();
    if (subject == null) {
        return null;
    }
    NameID nameID = subject.getNameID();
    if (nameID == null) {
        return null;
    }
    String format = nameID.getFormat();
    return format;
}
Also used : NameID(com.sun.identity.saml2.assertion.NameID) Assertion(com.sun.identity.saml2.assertion.Assertion) List(java.util.List) IDPList(com.sun.identity.saml2.protocol.IDPList) ArrayList(java.util.ArrayList) Subject(com.sun.identity.saml2.assertion.Subject)

Example 9 with Subject

use of com.sun.identity.saml2.assertion.Subject in project OpenAM by OpenRock.

the class SAML2Utils method verifyResponse.

/**
     * Verifies single sign on <code>Response</code> and returns information
     * to SAML2 auth module for further processing. This method is used by
     * SAML2 auth module only.
     *
     * @param httpRequest    HttpServletRequest
     * @param httpResponse   HttpServletResponse
     * @param response       Single Sign On <code>Response</code>.
     * @param orgName        name of the realm or organization the provider is in.
     * @param hostEntityId   Entity ID of the hosted provider.
     * @param profileBinding Profile binding used.
     * @return A Map of information extracted from the Response. The keys of
     * map are:
     * <code>SAML2Constants.SUBJECT</code>,
     * <code>SAML2Constants.POST_ASSERTION</code>,
     * <code>SAML2Constants.ASSERTIONS</code>,
     * <code>SAML2Constants.SESSION_INDEX</code>,
     * <code>SAML2Constants.AUTH_LEVEL</code>,
     * <code>SAML2Constants.MAX_SESSION_TIME</code>.
     * @throws SAML2Exception if the Response is not valid according to the
     *                        processing rules.
     */
public static Map verifyResponse(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final Response response, final String orgName, final String hostEntityId, final String profileBinding) throws SAML2Exception {
    final String method = "SAML2Utils.verifyResponse:";
    if (response == null || orgName == null || orgName.length() == 0) {
        if (debug.messageEnabled()) {
            debug.message(method + "response or orgName is null.");
        }
        throw new SAML2Exception(bundle.getString("nullInput"));
    }
    String respID = response.getID();
    AuthnRequestInfo reqInfo = null;
    String inRespToResp = response.getInResponseTo();
    if (inRespToResp != null && inRespToResp.length() != 0) {
        reqInfo = (AuthnRequestInfo) SPCache.requestHash.get(inRespToResp);
        if (reqInfo == null) {
            if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                // Attempt to read AuthnRequestInfoCopy from SAML2 repository
                AuthnRequestInfoCopy reqInfoCopy = null;
                try {
                    reqInfoCopy = (AuthnRequestInfoCopy) SAML2FailoverUtils.retrieveSAML2Token(inRespToResp);
                } catch (SAML2TokenRepositoryException se) {
                    debug.error(method + "AuthnRequestInfoCopy" + " unable to retrieve from SAML2 repository for inResponseTo: " + inRespToResp);
                }
                if (reqInfoCopy != null) {
                    // Get back the AuthnRequestInfo
                    reqInfo = reqInfoCopy.getAuthnRequestInfo(httpRequest, httpResponse);
                    if (debug.messageEnabled()) {
                        debug.message(method + "AuthnRequestInfoCopy" + " retrieved from SAML2 repository for inResponseTo: " + inRespToResp);
                    }
                } else {
                    debug.error(method + "InResponseTo attribute in Response" + " is invalid: " + inRespToResp + ", SAML2 failover is enabled");
                    String[] data = { respID };
                    LogUtil.error(Level.INFO, LogUtil.INVALID_INRESPONSETO_RESPONSE, data, null);
                    throw new SAML2Exception(bundle.getString("invalidInResponseToInResponse"));
                }
            } else {
                AuthnRequestInfoCopy reqInfoCopy = (AuthnRequestInfoCopy) SAML2Store.getTokenFromStore(inRespToResp);
                if (reqInfoCopy != null) {
                    // Get back the AuthnRequestInfo
                    reqInfo = reqInfoCopy.getAuthnRequestInfo(httpRequest, httpResponse);
                    if (debug.messageEnabled()) {
                        debug.message(method + "AuthnRequestInfoCopy" + " retrieved from SAML2 repository for inResponseTo: " + inRespToResp);
                    }
                } else {
                    debug.error(method + "InResponseTo attribute in Response" + " is invalid: " + inRespToResp + ", SAML2 failover is enabled");
                    String[] data = { respID };
                    LogUtil.error(Level.INFO, LogUtil.INVALID_INRESPONSETO_RESPONSE, data, null);
                    throw new SAML2Exception(bundle.getString("invalidInResponseToInResponse"));
                }
            }
        }
    }
    // reqInfo can remain null and will do for IDP initiated SSO requests
    // invoke SP Adapter
    SAML2ServiceProviderAdapter spAdapter = SAML2Utils.getSPAdapterClass(hostEntityId, orgName);
    if (spAdapter != null) {
        AuthnRequest authnRequest = null;
        if (reqInfo != null) {
            authnRequest = reqInfo.getAuthnRequest();
        }
        spAdapter.preSingleSignOnProcess(hostEntityId, orgName, httpRequest, httpResponse, authnRequest, response, profileBinding);
    }
    String idpEntityId = null;
    Issuer respIssuer = response.getIssuer();
    if (respIssuer != null) {
        // optional
        if (!isSourceSiteValid(respIssuer, orgName, hostEntityId)) {
            if (debug.messageEnabled()) {
                debug.message(method + "Issuer in Response is not valid.");
            }
            String[] data = { hostEntityId, orgName, respID };
            LogUtil.error(Level.INFO, LogUtil.INVALID_ISSUER_RESPONSE, data, null);
            throw new SAML2Exception(bundle.getString("invalidIssuerInResponse"));
        } else {
            idpEntityId = respIssuer.getValue();
        }
    }
    Status status = response.getStatus();
    if (status == null || !status.getStatusCode().getValue().equals(SAML2Constants.SUCCESS)) {
        String statusCode = (status == null) ? "" : status.getStatusCode().getValue();
        if (debug.messageEnabled()) {
            debug.message(method + "Response's status code is not success: " + statusCode);
        }
        String[] data = { respID, "" };
        if (LogUtil.isErrorLoggable(Level.FINE)) {
            data[1] = statusCode;
        }
        LogUtil.error(Level.INFO, LogUtil.WRONG_STATUS_CODE, data, null);
        if (SAML2Constants.RESPONDER.equals(statusCode)) {
            //In case of passive authentication the NoPassive response will be sent using two StatusCode nodes:
            //the outer StatusCode will be Responder and the inner StatusCode will contain the NoPassive URN
            StatusCode secondLevelStatusCode = status.getStatusCode().getStatusCode();
            if (secondLevelStatusCode != null && SAML2Constants.NOPASSIVE.equals(secondLevelStatusCode.getValue())) {
                throw new SAML2Exception(SAML2Utils.BUNDLE_NAME, "noPassiveResponse", null);
            }
        } else if (SAML2Constants.REQUESTER.equals(statusCode)) {
            // when is AllowCreate=false mode the auth module gets here with a
            // statusCode of urn:oasis:names:tc:SAML:2.0:status:Requester
            StatusCode secondLevelStatusCode = status.getStatusCode().getStatusCode();
            if (secondLevelStatusCode != null && SAML2Constants.INVALID_NAME_ID_POLICY.equals(secondLevelStatusCode.getValue())) {
                throw new SAML2Exception(SAML2Utils.BUNDLE_NAME, "nameIDMReqInvalidNameIDPolicy", null);
            }
        }
        throw new SAML2Exception(bundle.getString("invalidStatusCodeInResponse"));
    }
    if (saml2MetaManager == null) {
        throw new SAML2Exception(bundle.getString("nullMetaManager"));
    }
    SPSSOConfigElement spConfig = null;
    SPSSODescriptorElement spDesc = null;
    spConfig = saml2MetaManager.getSPSSOConfig(orgName, hostEntityId);
    spDesc = saml2MetaManager.getSPSSODescriptor(orgName, hostEntityId);
    if (debug.messageEnabled()) {
        debug.message(method + "binding is :" + profileBinding);
    }
    // SAML spec processing
    //  4.1.4.3   Verify any signatures present on the assertion(s) or the response
    boolean responseIsSigned = false;
    if (response.isSigned()) {
        IDPSSODescriptorElement idpSSODescriptor = null;
        try {
            idpSSODescriptor = saml2MetaManager.getIDPSSODescriptor(orgName, idpEntityId);
        } catch (SAML2MetaException sme) {
            String[] data = { orgName, idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.IDP_METADATA_ERROR, data, null);
            throw new SAML2Exception(sme);
        }
        if (idpSSODescriptor != null) {
            Set<X509Certificate> verificationCerts = KeyUtil.getVerificationCerts(idpSSODescriptor, idpEntityId, SAML2Constants.IDP_ROLE);
            if (CollectionUtils.isEmpty(verificationCerts) || !response.isSignatureValid(verificationCerts)) {
                debug.error(method + "Response is not signed or signature is not valid.");
                String[] data = { orgName, hostEntityId, idpEntityId };
                LogUtil.error(Level.INFO, LogUtil.POST_RESPONSE_INVALID_SIGNATURE, data, null);
                throw new SAML2Exception(bundle.getString("invalidSignInResponse"));
            }
        } else {
            String[] data = { idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.IDP_METADATA_ERROR, data, null);
            throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
        }
        responseIsSigned = true;
    }
    if (debug.messageEnabled()) {
        debug.message(method + "responseIsSigned is :" + responseIsSigned);
    }
    // assertion encryption check
    boolean needAssertionEncrypted = false;
    String assertionEncryptedAttr = getAttributeValueFromSPSSOConfig(spConfig, SAML2Constants.WANT_ASSERTION_ENCRYPTED);
    needAssertionEncrypted = Boolean.parseBoolean(assertionEncryptedAttr);
    if (debug.messageEnabled()) {
        debug.message(method + "NeedAssertionEncrypted is :" + needAssertionEncrypted);
    }
    List<Assertion> assertions = response.getAssertion();
    if (needAssertionEncrypted && !CollectionUtils.isEmpty(assertions)) {
        String[] data = { respID };
        LogUtil.error(Level.INFO, LogUtil.ASSERTION_NOT_ENCRYPTED, data, null);
        throw new SAML2Exception(SAML2Utils.bundle.getString("assertionNotEncrypted"));
    }
    Set<PrivateKey> decryptionKeys;
    List<EncryptedAssertion> encAssertions = response.getEncryptedAssertion();
    if (encAssertions != null) {
        decryptionKeys = KeyUtil.getDecryptionKeys(spConfig);
        for (EncryptedAssertion encAssertion : encAssertions) {
            Assertion assertion = encAssertion.decrypt(decryptionKeys);
            if (assertions == null) {
                assertions = new ArrayList<>();
            }
            assertions.add(assertion);
        }
    }
    if (CollectionUtils.isEmpty(assertions)) {
        if (debug.messageEnabled()) {
            debug.message(method + "no assertion in the Response.");
        }
        String[] data = { respID };
        LogUtil.error(Level.INFO, LogUtil.MISSING_ASSERTION, data, null);
        throw new SAML2Exception(SAML2Utils.bundle.getString("missingAssertion"));
    }
    boolean wantAssertionsSigned = spDesc.isWantAssertionsSigned();
    if (debug.messageEnabled()) {
        debug.message(method + "wantAssertionsSigned is :" + wantAssertionsSigned);
    }
    // validate the assertions
    Map smap = null;
    Map bearerMap = null;
    IDPSSODescriptorElement idp = null;
    Set<X509Certificate> verificationCerts = null;
    boolean allAssertionsSigned = true;
    for (Assertion assertion : assertions) {
        String assertionID = assertion.getID();
        Issuer issuer = assertion.getIssuer();
        if (!isSourceSiteValid(issuer, orgName, hostEntityId)) {
            debug.error("assertion's source site is not valid.");
            String[] data = { assertionID };
            LogUtil.error(Level.INFO, LogUtil.INVALID_ISSUER_ASSERTION, data, null);
            throw new SAML2Exception(bundle.getString("invalidIssuerInAssertion"));
        }
        if (idpEntityId == null) {
            idpEntityId = issuer.getValue();
        } else {
            if (!idpEntityId.equals(issuer.getValue())) {
                if (debug.messageEnabled()) {
                    debug.message(method + "Issuer in Assertion doesn't " + "match the Issuer in Response or other " + "Assertions in the Response.");
                }
                String[] data = { assertionID };
                LogUtil.error(Level.INFO, LogUtil.MISMATCH_ISSUER_ASSERTION, data, null);
                throw new SAML2Exception(SAML2Utils.bundle.getString("mismatchIssuer"));
            }
        }
        if (assertion.isSigned()) {
            if (verificationCerts == null) {
                idp = saml2MetaManager.getIDPSSODescriptor(orgName, idpEntityId);
                verificationCerts = KeyUtil.getVerificationCerts(idp, idpEntityId, SAML2Constants.IDP_ROLE);
            }
            if (CollectionUtils.isEmpty(verificationCerts) || !assertion.isSignatureValid(verificationCerts)) {
                debug.error(method + "Assertion is not signed or signature is not valid.");
                String[] data = { assertionID };
                LogUtil.error(Level.INFO, LogUtil.INVALID_SIGNATURE_ASSERTION, data, null);
                throw new SAML2Exception(bundle.getString("invalidSignatureOnAssertion"));
            }
        } else {
            allAssertionsSigned = false;
        }
        List authnStmts = assertion.getAuthnStatements();
        if (authnStmts != null && !authnStmts.isEmpty()) {
            Subject subject = assertion.getSubject();
            if (subject == null) {
                continue;
            }
            List subjectConfirms = subject.getSubjectConfirmation();
            if (subjectConfirms == null || subjectConfirms.isEmpty()) {
                continue;
            }
            bearerMap = isBearerSubjectConfirmation(subjectConfirms, inRespToResp, spDesc, spConfig, assertionID);
            if (!((Boolean) bearerMap.get(SAML2Constants.IS_BEARER))) {
                continue;
            }
            boolean foundAssertion = false;
            if ((SPCache.assertionByIDCache != null) && (SPCache.assertionByIDCache.containsKey(assertionID))) {
                foundAssertion = true;
            }
            if ((!foundAssertion) && SAML2FailoverUtils.isSAML2FailoverEnabled()) {
                try {
                    if (SAML2FailoverUtils.retrieveSAML2Token(assertionID) != null) {
                        foundAssertion = true;
                    }
                } catch (SAML2TokenRepositoryException e) {
                    if (debug.messageEnabled()) {
                        debug.message("Session not found in AMTokenSAML2Repository.", e);
                    }
                }
            }
            if (foundAssertion) {
                debug.error("Bearer Assertion is one time use only!");
                throw new SAML2Exception(bundle.getString("usedBearAssertion"));
            }
            checkAudience(assertion.getConditions(), hostEntityId, assertionID);
            if (smap == null) {
                smap = fillMap(authnStmts, subject, assertion, assertions, reqInfo, inRespToResp, orgName, hostEntityId, idpEntityId, spConfig, (Date) bearerMap.get(SAML2Constants.NOTONORAFTER));
            }
        }
    // end of having authnStmt
    }
    if (smap == null) {
        debug.error("No Authentication Assertion in Response.");
        throw new SAML2Exception(bundle.getString("missingAuthnAssertion"));
    }
    // the enclosing element
    if (wantAssertionsSigned && !(responseIsSigned || allAssertionsSigned)) {
        debug.error(method + "WantAssertionsSigned is true and response or all assertions are not signed");
        String[] data = { orgName, hostEntityId, idpEntityId };
        LogUtil.error(Level.INFO, LogUtil.INVALID_SIGNATURE_ASSERTION, data, null);
        throw new SAML2Exception(bundle.getString("assertionNotSigned"));
    }
    // signing each individual <Assertion> element or by signing the <Response> element.
    if (profileBinding.equals(SAML2Constants.HTTP_POST)) {
        boolean wantPostResponseSigned = SAML2Utils.wantPOSTResponseSigned(orgName, hostEntityId, SAML2Constants.SP_ROLE);
        if (debug.messageEnabled()) {
            debug.message(method + "wantPostResponseSigned is :" + wantPostResponseSigned);
        }
        if (wantPostResponseSigned && !responseIsSigned) {
            debug.error(method + "wantPostResponseSigned is true but response is not signed");
            String[] data = { orgName, hostEntityId, idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.POST_RESPONSE_INVALID_SIGNATURE, data, null);
            throw new SAML2Exception(bundle.getString("responseNotSigned"));
        }
        if (!responseIsSigned && !allAssertionsSigned) {
            debug.error(method + "WantAssertionsSigned is true but some or all assertions are not signed");
            String[] data = { orgName, hostEntityId, idpEntityId };
            LogUtil.error(Level.INFO, LogUtil.INVALID_SIGNATURE_ASSERTION, data, null);
            throw new SAML2Exception(bundle.getString("assertionNotSigned"));
        }
    }
    return smap;
}
Also used : PrivateKey(java.security.PrivateKey) Issuer(com.sun.identity.saml2.assertion.Issuer) AuthnRequestInfo(com.sun.identity.saml2.profile.AuthnRequestInfo) SPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.SPSSODescriptorElement) StatusCode(com.sun.identity.saml2.protocol.StatusCode) ArrayList(java.util.ArrayList) List(java.util.List) AuthnRequestInfoCopy(com.sun.identity.saml2.profile.AuthnRequestInfoCopy) SAML2ServiceProviderAdapter(com.sun.identity.saml2.plugins.SAML2ServiceProviderAdapter) SAML2MetaException(com.sun.identity.saml2.meta.SAML2MetaException) Status(com.sun.identity.saml2.protocol.Status) SPSSOConfigElement(com.sun.identity.saml2.jaxb.entityconfig.SPSSOConfigElement) EncryptedAssertion(com.sun.identity.saml2.assertion.EncryptedAssertion) Assertion(com.sun.identity.saml2.assertion.Assertion) X509Certificate(java.security.cert.X509Certificate) Subject(com.sun.identity.saml2.assertion.Subject) Date(java.util.Date) AuthnRequest(com.sun.identity.saml2.protocol.AuthnRequest) EncryptedAssertion(com.sun.identity.saml2.assertion.EncryptedAssertion) SAML2TokenRepositoryException(org.forgerock.openam.federation.saml2.SAML2TokenRepositoryException) Map(java.util.Map) HashMap(java.util.HashMap) IDPSSODescriptorElement(com.sun.identity.saml2.jaxb.metadata.IDPSSODescriptorElement)

Example 10 with Subject

use of com.sun.identity.saml2.assertion.Subject in project OpenAM by OpenRock.

the class SAML2Utils method fillMap.

private static Map fillMap(final List authnStmts, final Subject subject, final Assertion assertion, final List assertions, final AuthnRequestInfo reqInfo, final String inRespToResp, final String orgName, final String hostEntityId, final String idpEntityId, final SPSSOConfigElement spConfig, final Date notOnOrAfterTime) throws SAML2Exception {
    // use the first AuthnStmt
    AuthnStatement authnStmt = (AuthnStatement) authnStmts.get(0);
    int authLevel = -1;
    String mapperClass = getAttributeValueFromSPSSOConfig(spConfig, SAML2Constants.SP_AUTHCONTEXT_MAPPER);
    SPAuthnContextMapper mapper = getSPAuthnContextMapper(orgName, hostEntityId, mapperClass);
    RequestedAuthnContext reqContext = null;
    AuthnRequest authnRequest = null;
    if (reqInfo != null) {
        reqContext = (reqInfo.getAuthnRequest()).getRequestedAuthnContext();
        authnRequest = reqInfo.getAuthnRequest();
    }
    authLevel = mapper.getAuthLevel(reqContext, authnStmt.getAuthnContext(), orgName, hostEntityId, idpEntityId);
    String sessionIndex = authnStmt.getSessionIndex();
    Date sessionNotOnOrAfter = authnStmt.getSessionNotOnOrAfter();
    Map smap = new HashMap();
    smap.put(SAML2Constants.SUBJECT, subject);
    smap.put(SAML2Constants.POST_ASSERTION, assertion);
    smap.put(SAML2Constants.ASSERTIONS, assertions);
    if (authnRequest != null) {
        smap.put(SAML2Constants.AUTHN_REQUEST, authnRequest);
    }
    String[] data = { assertion.getID(), "", "" };
    if (LogUtil.isAccessLoggable(Level.FINE)) {
        data[1] = subject.toXMLString();
    }
    if (sessionIndex != null && sessionIndex.length() != 0) {
        data[2] = sessionIndex;
        smap.put(SAML2Constants.SESSION_INDEX, sessionIndex);
    }
    if (authLevel >= 0) {
        smap.put(SAML2Constants.AUTH_LEVEL, new Integer(authLevel));
    }
    // SessionNotOnOrAfter
    if (sessionNotOnOrAfter != null) {
        long maxSessionTime = (sessionNotOnOrAfter.getTime() - System.currentTimeMillis()) / 60000;
        if (maxSessionTime > 0) {
            smap.put(SAML2Constants.MAX_SESSION_TIME, new Long(maxSessionTime));
        }
    }
    if (inRespToResp != null && inRespToResp.length() != 0) {
        smap.put(SAML2Constants.IN_RESPONSE_TO, inRespToResp);
    }
    if (debug.messageEnabled()) {
        debug.message("SAML2Utils.fillMap: Found valid authentication " + "assertion.");
    }
    if (notOnOrAfterTime != null) {
        smap.put(SAML2Constants.NOTONORAFTER, new Long(notOnOrAfterTime.getTime()));
    }
    LogUtil.access(Level.INFO, LogUtil.FOUND_AUTHN_ASSERTION, data, null);
    return smap;
}
Also used : HashMap(java.util.HashMap) Date(java.util.Date) RequestedAuthnContext(com.sun.identity.saml2.protocol.RequestedAuthnContext) AuthnRequest(com.sun.identity.saml2.protocol.AuthnRequest) AuthnStatement(com.sun.identity.saml2.assertion.AuthnStatement) SPAuthnContextMapper(com.sun.identity.saml2.plugins.SPAuthnContextMapper) DefaultSPAuthnContextMapper(com.sun.identity.saml2.plugins.DefaultSPAuthnContextMapper) Map(java.util.Map) HashMap(java.util.HashMap)

Aggregations

SAML2Exception (com.sun.identity.saml2.common.SAML2Exception)19 Subject (com.sun.identity.saml2.assertion.Subject)15 ArrayList (java.util.ArrayList)15 List (java.util.List)14 Date (java.util.Date)10 NameID (com.sun.identity.saml2.assertion.NameID)9 Assertion (com.sun.identity.saml2.assertion.Assertion)8 AttributeStatement (com.sun.identity.saml2.assertion.AttributeStatement)6 EncryptedAssertion (com.sun.identity.saml2.assertion.EncryptedAssertion)6 EncryptedID (com.sun.identity.saml2.assertion.EncryptedID)6 SubjectConfirmation (com.sun.identity.saml2.assertion.SubjectConfirmation)6 Map (java.util.Map)6 Issuer (com.sun.identity.saml2.assertion.Issuer)5 HashMap (java.util.HashMap)5 Element (org.w3c.dom.Element)5 AssertionFactory (com.sun.identity.saml2.assertion.AssertionFactory)4 AuthnStatement (com.sun.identity.saml2.assertion.AuthnStatement)4 SubjectConfirmationData (com.sun.identity.saml2.assertion.SubjectConfirmationData)4 Node (org.w3c.dom.Node)4 NodeList (org.w3c.dom.NodeList)4