/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: IDPSSOUtil.java,v 1.56 2009/11/24 21:53:28 madan_ranganath Exp $
*
* Portions Copyrighted 2010-2016 ForgeRock AS.
* Portions Copyrighted 2013 Nomura Research Institute, Ltd
*/
/**
* The utility class is used by the identity provider to process
* the authentication request from a service provider and send back
* a proper response.
* The identity provider can also send unsolicited response to a service
*/
public class IDPSSOUtil {
// key name for name id format on SSOToken
static {
try {
metaManager = new SAML2MetaManager();
cotManager = new CircleOfTrustManager();
} catch (COTException ce) {
} catch (SAML2MetaException sme) {
}
try {
} catch (SessionException se) {
"IDPSSOUtil static block: Error getting SessionProvider.",
se);
}
}
private IDPSSOUtil() {
}
/**
* Does SSO with existing federation or new federation
*
* @param request the <code>HttpServletRequest</code> object
* @param response the <code>HttpServletResponse</code> object
* @param out the print writer for writing out presentation
* @param authnReq the <code>AuthnRequest</code> object
* @param spEntityID the entity id of the service provider
* @param idpMetaAlias the meta alias of the identity provider
* @param nameIDFormat the <code>NameIDFormat</code>
* @param relayState the relay state
* @param auditor the auditor for logging SAML2 Events - may be null
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
}
/**
* Does SSO with existing federation or new federation
*
* @param request the <code>HttpServletRequest</code> object
* @param response the <code>HttpServletResponse</code> object
* @param out the print writer for writing out presentation
* @param authnReq the <code>AuthnRequest</code> object
* @param spEntityID the entity id of the service provider
* @param idpMetaAlias the meta alias of the identity provider
* @param nameIDFormat the <code>NameIDFormat</code>
* @param relayState the relay state
* @param newSession Session used in IDP Proxy Case
* @param auditor the auditor for logging SAML2 Events
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
if (newSession != null) {
} else {
try {
}
} catch (SessionException se) {
classMethod + "No session yet.");
}
}
}
// log the authnRequest
}
// retrieve IDP entity id from meta alias
try {
if (metaManager == null) {
"Unable to get meta manager.");
throw new SAML2Exception(
}
if ((idpEntityID == null)
"Unable to get IDP Entity ID from meta.");
throw new SAML2Exception(
}
} catch (SAML2MetaException sme) {
"Unable to get IDP Entity ID from meta.");
throw new SAML2Exception(
}
// check if the remote provider is valid
"The remote provider is not valid.");
}
throw new SAML2Exception(
}
}
// Validate the RelayState URL.
// idp initiated and not logged in yet, need to authenticate
try {
} else {
try {
} catch (SessionException se) {
}
}
} else {
}
} catch (IOException ioe) {
"Unable to redirect to authentication.", ioe);
"UnableToRedirectToAuth",
}
return;
}
// Invoke the IDP Adapter
try {
+ "IDP Adapter");
if (idpAdapter != null) {
// If the preSendResponse returns true we end here
return;
} // else we continue with the logic. Beware of loops
}
} catch (SAML2Exception se2) {
+ "the preSendResponse of the IDP Adapter: ", se2);
}
// End of invocation
}
/**
* Sends <code>Response</code> containing an <code>Assertion</code>
* back to the requesting service provider
*
* @param request the <code>HttpServletRequest</code> object
* @param response the <code>HttpServletResponse</code> object
* @param out the print writer for writing out presentation
* @param session user session
* @param authnReq the <code>AuthnRequest</code> object
* @param spEntityID the entity id of the service provider
* @param idpEntityID the entity id of the identity provider
* @param idpMetaAlias the meta alias of the identity provider
* @param realm the realm
* @param nameIDFormat the <code>NameIDFormat</code>
* @param relayState the relay state
* @param matchingAuthnContext the <code>AuthnContext</code> used to find
* authentication type and scheme.
*/
public static void sendResponseToACS(HttpServletRequest request, HttpServletResponse response, PrintWriter out,
throws SAML2Exception {
" no ACS URL found.");
throw new SAML2Exception(
}
" no return binding found.");
throw new SAML2Exception(
}
//check first if there is already an existing sessionindex associated with this SSOToken, if there is, then
//we need to redirect the request internally to the holder of the idpsession.
//The remoteServiceURL will be null if there is no sessionindex for this SSOToken, or there is, but it's
//local. If the remoteServiceURL is not null, we can start to send the request to the original server.
if (remoteServiceURL != null) {
remoteServiceURL += SAML2Utils.removeDeployUri(request.getRequestURI()) + "?" + request.getQueryString();
+ remoteServiceURL);
}
try {
} else {
if (responseCode != null) {
}
// no redirect, perhaps an error page, return the content
return;
}
}
} catch (IOException ioe) {
}
}
return;
}
}
//end of request proxy
// generate a response for the authn request
" response is null");
//idp initiated case, will not send error response to sp
throw new SAML2Exception(errorMsg);
}
} else {
try {
} catch (SessionException e) {
" error setting idpMetaAlias into the session: ", e);
}
}
// call multi-federation protocol to set the protocol
// check if the COT cookie needs to be set
session)) {
" Redirected to set COT cookie.");
}
return;
}
" Doesn't set COT cookie.");
}
try {
if (idpAdapter != null) {
}
} catch (SAML2Exception se) {
+ "preSendResponse of the IDP Adapter: ", se);
}
} else {
" error response is null");
throw new SAML2Exception(
}
}
private static boolean setCOTCookie(
// could not find the writer URL, do not set the COT cookie
return false;
}
// save the needed info into cache so they can be used later
// when it is redirected back
// construct redirect URL
.append("?")
.append("=")
} else {
}
.append("=")
.append("&")
.append("=")
"Writer redirect URL: " + redirectURL);
}
try {
return true;
} catch (IOException ioe) {
"Unable to send redirect: ", ioe);
}
return false;
}
/**
* A convenience method to construct response with First-level and Second-level status code for
* SAML authentication requests.
*
* @param request The servlet request.
* @param response The servlet response.
* @param out The print writer for writing out presentation.
* @param idpMetaAlias The IdP's metaAlias.
* @param idpEntityID The IdP's entity ID.
* @param realm The realm where the IdP belongs to.
* @param authnReq The SAML AuthnRequest sent by the SP.
* @param relayState The RelayState value.
* @param spEntityID The SP's entity ID.
* @param firstlevelStatusCodeValue First-level status code value passed.
* @param secondlevelStatusCodeValue Second-level status code value passed.
* @throws SAML2Exception If there was an error while creating or sending the response back to the SP.
*/
Response res = SAML2Utils.getErrorResponse(authnReq, firstlevelStatusCodeValue, secondlevelStatusCodeValue,
null, idpEntityID);
sendResponse(request, response, out, acsBinding, spEntityID, idpEntityID, idpMetaAlias, realm, relayState,
}
/**
* Sends a response to service provider
*
* @param request The servlet request.
* @param response The servlet response.
* @param out The print writer for writing out presentation.
* @param cachedResID the key used to retrieve response information
* from the response information cache
* @throws SAML2Exception if the operation is not successful
*/
public static void sendResponse(
throws SAML2Exception {
} else {
"unable to get response information from cache.");
throw new SAML2Exception(
"UnableToGetResponseInfoFromCache"));
}
}
/**
* Sends a response to service provider
*
* @param response the <code>HttpServletResponse</code> object
* @param acsBinding the assertion consumer service binding
* @param spEntityID the entity id of the service provider
* @param idpEntityID the entity id of the identity provider
* @param idpMetaAlias the meta alias of the identity provider
* @param realm the realm name
* @param relayState the relay state
* @param acsURL the assertion consumer service <code>url</code>
* @param res the <code>SAML Response</code> object
* @throws SAML2Exception if the operation is not successful
*/
public static void sendResponse(
throws SAML2Exception {
// send the response back through HTTP POST or Artifact
// 4.1.4.5 POST-Specific Processing Rules (sstc-saml-profiles-errata-2.0-wd-06-diff.pdf)
//If response is not signed and POST binding is used, the assertion(s) MUST be signed.
// encryption is optional based on SP config settings.
boolean signAssertion = true;
// check if response needs to be signed.
boolean signResponse = SAML2Utils.wantPOSTResponseSigned(realm, spEntityID, SAML2Constants.SP_ROLE);
// if signing response then signing assertion is optional
// so will base on wantAssertionsSigned flag
if (signResponse) {
}
if (signResponse) {
}
"SAML Response content :\n" + resMsg);
}
try {
} catch (SAML2Exception saml2E) {
throw saml2E;
}
// signing assertion is a must for ECP profile.
// encryption is optional based on SP config settings.
} else {
"unsupported return binding.");
throw new SAML2Exception(
}
}
/**
* Returns a <code>SAML Response</code> object.
*
* @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 Response</code> object.
* @throws SAML2Exception if the operation is not successful.
*/
throws SAML2Exception {
return null;
}
if (statusCode == null) {
return null;
}
try {
classMethod + "Unable to get Assertion.");
return null;
}
} catch (SAML2InvalidNameIDPolicyException se) {
}
// sp initiated case, need to set InResponseTo attribute
}
// set the idp entity id as the response issuer
return res;
}
/**
* 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.
*/
throws SAML2Exception {
synchronized (sessionID) {
authnStatement = getAuthnStatement(request, session, isNewSessionIndex, authnReq, idpEntityID, realm,
if (authnStatement == null) {
return null;
}
if (isNewSessionIndex.getValue()) {
"This is a new IDP session with sessionIndex=" +
sessionIndex + ", and sessionID=" +
}
if (idpSession == null) {
}
// Set the metaAlias in the IDP session object
}
} else {
}
}
if (isNewSessionIndex.getValue()) {
"a new IDP session has been saved in cache, " +
"with sessionIndex=" + sessionIndex);
}
try {
} catch (SessionException e) {
"Unable to add session listener.");
}
} else {
// Read from SAML2 Token Repository
try {
} catch (SAML2TokenRepositoryException se) {
"Unable to obtain IDPSessionCopy from the SAML2 Token Repository for sessionIndex:"
+ sessionIndex, se);
}
// Copy back to IDPSession
if (idpSessionCopy != null) {
} else {
throw new SAML2Exception(
}
} else if ((idpSession == null) &&
"is disabled");
throw new SAML2Exception(
} else {
"This is an existing IDP session with sessionIndex="
+ sessionIndex + ", and sessionID=" +
}
}
}
if (attrStatement != null) {
}
// get the assertion effective time (in seconds)
// get the NotBefore skew (in seconds)
// get the subject element
// register (spEntityID, nameID) with the sso token
// for later logout use
} else {
}
synchronized (IDPCache.idpSessionsByIndices) {
} else {
id = spEntityID;
}
boolean found = false;
found = true;
break;
}
}
if (!found) {
}
}
if ((discoBootstrapEnabled != null) &&
if (attrStatementList == null) {
attrStatementList = new ArrayList();
}
spEntityID, realm);
}
try {
} catch (SessionException se) {
"Unable to get principal name from the session.", se);
throw new SAML2Exception(
}
if (assertions == null) {
synchronized (IDPCache.assertionCache) {
if (assertions == null) {
assertions = new ArrayList();
}
}
}
synchronized (assertions) {
}
if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
try {
assertion.toXMLString(true, true),
"Saving Assertion to SAML2 Token Repository. ID = " + assertionID);
}
} catch (SAML2TokenRepositoryException se) {
}
}
}
// Save to SAML2 Token Repository
try {
if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
}
}
} catch (SessionException se) {
} catch (SAML2TokenRepositoryException se) {
SAML2Utils.debug.error(classMethod + "Unable to save IDPSession to the SAML2 Token Repository", se);
}
return assertion;
}
/**
* Returns a <code>SAML AuthnStatement</code> object.
*
* @param request The HTTP request.
* @param session The user's session.
* @param isNewSessionIndex A returned flag from which the caller knows if the session index in the returned
* <code>AuthnStatement</code> is a new session index.
* @param authnReq The <code>AuthnRequest</code> object.
* @param idpEntityID The entity ID of the identity provider.
* @param realm The realm name.
* @param matchingAuthnContext The <code>AuthnContext</code> used to find authentication type and scheme.
* @param metaAlias The meta alias.
* @return The <code>SAML AuthnStatement</code> object.
* @throws SAML2Exception If the operation is not successful.
*/
throws SAML2Exception {
// will be used when we add SubjectLocality to the statement
try {
}
} catch (Exception e) {
"exception retrieving info from the session: ", e);
throw new SAML2Exception(
}
if (authInstant == null) {
authInstant = newDate();
}
if (authnContext == null) {
try {
}
} catch (Exception e) {
"exception retrieving auth level info from the session: ",
e);
throw new SAML2Exception(
}
}
final Response idpResponse = (Response) request.getAttribute(SAML2Constants.SAML_PROXY_IDP_RESPONSE_KEY);
if (idpResponse != null) {
// IdP proxy case: we already received an assertion from the remote IdP and now the IdP proxy is generating
// a new SAML response for the SP.
}
// According to SAML profile 4.1.4.2 each assertion within the SAML Response MUST have the same issuer, so
// this should suffice. We should have at least one assertion or encrypted assertion available since the
// IdP proxy's SP already accepted it.
} else {
// Check for Encrypted Assertions
boolean firstAssertion = true;
Set<PrivateKey> decryptionKeys = KeyUtil.getDecryptionKeys(metaManager.getSPSSOConfig(realm, hostEntityId));
if (firstAssertion) {
firstAssertion = false;
}
}
}
}
}
try {
values);
} catch (SessionException e) {
"error setting session index into the session: ", e);
throw new SAML2Exception(
}
isNewSessionIndex.setValue(true);
} else {
isNewSessionIndex.setValue(false);
}
"SessionIndex (in AuthnStatement) =" + sessionIndex);
}
if (sessionIndex != null) {
authContextSet = new HashSet();
}
// cache the AuthContext to use in the case of session upgrade.
}
return authnStatement;
}
/**
* Returns a <code>SAML AttributeStatement</code> object
*
* @param session the user's session
* @param idpEntityID the entity id of the identity provider
* @param recipientEntityID the entity id of the response recipient
* @param realm the realm name
* @return the <code>SAML AttributeStatement</code> object
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
return null;
}
return attrStatement;
}
/**
* Returns an <code>IDPAttributeMapper</code>
*
* @param realm the realm name
* @param idpEntityID the entity id of the identity provider
* @return the <code>IDPAttributeMapper</code>
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
try {
if (idpAttributeMapperName == null) {
}
}
if (idpAttributeMapper == null) {
} else {
"got the IDPAttributeMapper from cache");
}
}
"Unable to get IDP Attribute Mapper.", ex);
throw new SAML2Exception(ex);
}
return idpAttributeMapper;
}
/**
* Returns an <code>IDPAuthnContextMapper</code>
*
* @param realm the realm name
* @param idpEntityID the entity id of the identity provider
* @return the <code>IDPAuthnContextMapper</code>
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
try {
if (idpAuthnContextMapperName == null) {
}
}
if (idpAuthnContextMapper == null) {
} else {
"got the IDPAuthnContextMapper from cache");
}
}
"Unable to get IDP AuthnContext Mapper.", ex);
throw new SAML2Exception(ex);
}
return idpAuthnContextMapper;
}
/**
* Returns an <code>IDPECPSessionMapper</code>
*
* @param realm the realm name
* @param idpEntityID the entity id of the identity provider
* @return the <code>IDPECPSessionMapper</code>
* @throws SAML2Exception if the operation is not successful
*/
try {
if (idpECPSessionMapperName == null) {
"IDPSSOUtil.getIDPECPSessionMapper: use " +
}
}
if (idpECPSessionMapper == null) {
} else {
"IDPSSOUtil.getIDPECPSessionMapper: " +
"got the IDPECPSessionMapper from cache");
}
}
"Unable to get IDPECPSessionMapper.", ex);
throw new SAML2Exception(ex);
}
return idpECPSessionMapper;
}
/**
* Returns a <code>SAML Subject</code> object
*
* @param session the user's session
* @param authnReq the <code>AuthnRequest</code> object
* @param acsURL the <code>ACS</code> service <code>url</code>
* @param nameIDFormat the <code>NameIDFormat</code>
* @param realm The realm name
* @param idpEntityID the entity id of the identity provider
* @param recipientEntityID the entity id of the response recipient
* @param effectiveTime the effective time of the assertion
* @param affiliationID affiliationID for IDP initiated SSO
* @return the <code>SAML Subject</code> object
* @throws SAML2Exception if the operation is not successful
*/
int effectiveTime,
throws SAML2Exception {
boolean ignoreProfile = false;
try {
} catch (SessionException se) {
"There was a problem with the session.", se);
throw new SAML2Exception(
}
boolean allowCreate = true; // allow create is the default
boolean isAffiliation = false;
if (hasNameIDPolicy) {
// this will take care of affiliation
isAffiliation = true;
} else {
}
}
} else {
}
}
} else {
// IDP initialted SSO
if (affiliationID != null) {
"affiliationNotFound"));
}
isAffiliation = true;
} else {
"spNotAffiliationMember"));
}
} else {
}
}
"metaDataError"));
}
"metaDataError"));
}
//Use-cases for NameID persistence:
//* transient NameID -> The NameID MUST NOT be stored
//* ignored user profile mode -> The NameID CANNOT be stored
//* for any other cases -> The NameID MAY be stored based on customizable logic
if (!isTransient) {
try {
} catch (SessionException se) {
}
if (shouldPersistNameID) {
if (nameIDInfo != null) {
}
}
}
}
if (!allowCreate && shouldPersistNameID) {
}
if (shouldPersistNameID && allowCreate) {
// write federation info into the persistent datastore
} else {
}
}
}
if (isTransient) {
userName);
}
}
"Unable to get subject confirmation");
throw new SAML2Exception(
}
return subject;
}
/**
* Returns a <code>SAML SubjectConfirmation</code> object
*
* @param inResponseTo the request id of the <code>AuthnRequest</code>
* @param acsURL the <code>ACS</code> service <code>url</code>
* @param effectiveTime the effective time of the assertion
* @return the <code>SAML SubjectConfirmation</code> object
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
if (inResponseTo != null) {
}
return sc;
}
/**
* Returns a <code>SAML Conditions</code> object
*
* @param audienceEntityID the entity id of the audience
* @param effectiveTime the effective time of the assertion
* @return the <code>SAML Conditions</code> object
* @throws SAML2Exception if the operation is not successful
*/
"Unable to get Audience Restriction");
throw new SAML2Exception(
}
return conditions;
}
/**
* Returns a <code>SAML AudienceRestriction</code> object
*
* @param audienceEntityID the entity id of the audience
* @return the <code>SAML AudienceRestriction</code> object
* @throws SAML2Exception if the operation is not successful
*/
if (audienceEntityID != null) {
}
return ar;
}
/**
* Returns the assertion consumer service <code>URL</code>
*
* @param spEntityID the entity id of the service provider
* @param realm the realm name of the identity provider
* @param authnReq the <code>AuthnRequest</code> object
* @param request the <code>HttpServletRequest</code> object
* @param rBinding the binding used to send back <code>Response</code>
* @return the assertion consumer service <code>URL</code>
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
} else {
}
}
/**
* Returns the assertion consumer service <code>URL</code>.
*
* @param spEntityID The entity id of the service provider.
* @param realm The realm name of the identity provider.
* @param acsURL AssertionConsumerServiceURL in AuthnRequest.
* @param binding ProtocolBinding in AuthnRequest.
* @param index AssertionConsumerServiceIndex in AuthnRequest.
* @param request The <code>HttpServletRequest</code> object.
* @param rBinding The binding used to send back <code>Response</code>.
* @return The assertion consumer service <code>URL</code>.
* @throws SAML2Exception if the operation is not successful.
*/
public static String getACSurl(String spEntityID, String realm, String acsURL, String binding, Integer index,
// convert short format binding to long format
}
} else {
int acsIndex;
} else {
acsIndex = 0;
}
}
}
} else {
}
} else {
}
}
return acsURL;
}
/**
* Returns the default assertion consumer service url and binding
* from the metadata.
*
* @param spEntityID the entity id of the service provider
* @param realm the realm name of the identity provider
* @return the assertion consumer service url with returned binding.
* @throws SAML2Exception if the operation is not successful
*/
if (acs.isIsDefault()) {
}
if (i == 0) {
}
}
}
}
return acsURL;
}
/**
* Returns the assertion consumer service url binding from
* the metadata.
*
* @param spEntityID the entity id of the service provider
* @param realm the realm name of the identity provider
* @return the assertion consumer service url binding
* @throws SAML2Exception if the operation is not successful
*/
return acs.getBinding();
}
}
return null;
}
/**
* Returns the assertion consumer service <code>URL</code> from
* meta data by binding
*
* @param spEntityID the entity id of the service provider
* @param realm the realm name of the identity provider
* @param desiredBinding the desired binding
* @param returnedBinding the binding used to send back
* <code>Response</code>
* @return the assertion consumer service <code>URL</code>
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
break;
}
if (acs.isIsDefault()) {
}
if (i == 0) {
}
}
"Unable to get valid Assertion " +
"Consumer Service URL");
return null;
}
} else {
}
} else {
}
return acsURL;
}
/**
* Returns the assertion consumer service <code>URL</code> from
* meta data by binding
*
* @param spEntityID the entity id of the service provider
* @param realm the realm name of the identity provider
* @param acsIndex the <code>ACS</code> index
* @param returnedBinding the binding used to send back
* <code>Response</code>
* @return the assertion consumer service <code>URL</code>
* @throws SAML2Exception if the operation is not successful
*/
int acsIndex,
throws SAML2Exception {
int index;
break;
}
if (acs.isIsDefault()) {
}
if (i == 0) {
}
}
"Unable to get valid Assertion " +
"Consumer Service URL");
return null;
}
} else {
}
} else {
}
return acsURL;
}
/**
* This method opens a URL connection to the target specified and
* sends artifact response to it using the
* <code>HttpServletResponse</code> object.
*
* @param response the <code>HttpServletResponse</code> object
* @param idpEntityID the entity id of the identity provider
* @param realm the realm name of the identity provider
* @param acsURL the assertion consumer service <code>URL</code>
* @param relayState the value of the <code>RelayState</code>
* @param res the <code>SAML Response</code> object
* @param session user session
* @param props property map including nameIDString for logging
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
try {
realm, idpEntityID);
if (idpSSODescriptorElement == null) {
+ "Unable to get IDP SSO Descriptor from meta.");
throw new SAML2Exception(
}
} catch (SAML2MetaException sme) {
+ "Unable to get IDP SSO Descriptor from meta.");
throw new SAML2Exception(
}
"Unable to get ArtifactResolutionServiceElement from meta.");
throw new SAML2Exception(
}
try {
null,
);
} catch (SAML2Exception se) {
"Unable to create artifact: ", se);
return;
}
try {
if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
try {
+ artStr);
}
} catch (SAML2TokenRepositoryException se) {
}
}
"messageEncoding = " + messageEncoding);
"artStr = " + artStr);
}
if ((messageEncoding != null) &&
} else {
redirectURL += "&RelayState=" +
}
"Redirect URL = " + redirectURL);
}
}
} catch (IOException ioe) {
"Unable to send redirect: ", ioe);
}
}
/**
* This method sends SAML Response back to ECP.
*
* @param request The servlet request.
* @param response The servlet response.
* @param out The print writer for writing out presentation.
* @param idpEntityID the entity id of the identity provider
* @param realm the realm name of the identity provider
* @param acsURL the assertion consumer service <code>URL</code>
* @param res the <code>SAML Response</code> object
* @throws SAML2Exception if the operation is not successful
*/
try {
false);
}
null);
// Need to call saveChanges because we're
// going to use the MimeHeaders to set HTTP
// response information. These MimeHeaders
// are generated as part of the save.
if (reply.saveRequired()) {
reply.saveChanges();
}
// Write out the message on the response stream
null);
return;
}
}
/**
* Returns the session index of an <code>IDPSession</code>
*
* @param session the session corresponding to the <code>IDPSession</code>
* @return the session index string
*/
return null;
}
try {
} catch (SessionException e) {
"error retrieving session index from the session: ", e);
}
return null;
}
return null;
}
}
return index;
}
/**
* Returns the authentication service <code>URL</code> of the
* identity provider
*
* @param realm the realm name of the identity provider
* @param hostEntityId the entity id of the identity provider
* @param request the <code>HttpServletRequest</code> object
* @return the authentication service <code>URL</code> of the
* identity provider
*/
// need to get it from the request
if (secondSlashIndex != -1) {
}
}
}
return authUrl;
}
try {
}
} catch (SAML2MetaException sme) {
"get IDPSSOConfig failed:", sme);
}
}
return result;
}
/**
* Redirects to authenticate service
*
* @param request the <code>HttpServletRequest</code> object
* @param response the <code>HttpServletResponse</code> object
* @param authnReq the <code>AuthnRequest</code> object
* @param reqID the <code>AuthnRequest ID</code>
* @param realm the realm name of the identity provider
* @param idpEntityID the entity id of the identity provider
* @param spEntityID the entity id of the service provider
*/
static void redirectAuthentication(
throws SAML2Exception, IOException {
// get the authentication service url
// Pass spEntityID to IdP Auth Module
if (spEntityID != null) {
} else {
}
}
// find out the authentication method, e.g. module=LDAP, from
// authn context mapping
if ((authnTypeAndValues != null)
&& (!authnTypeAndValues.isEmpty())) {
}
} else {
}
}
}
} else {
}
//We are appending redirected=true to the goto URL so that we can tell if the user was already redirected
//to the login interface for authentication.
} else {
}
}
"gotoURL=" + gotoURL);
}
}
// TODO: here we should check if the new URL is one
// the same web container, if yes, forward,
// if not, redirect
return;
}
/**
* Signs an <code>Assertion</code>
*
* @param realm the realm name of the identity provider
* @param idpEntityID the entity id of the identity provider
* @param assertion The <code>Assertion</code> to be signed
*/
throws SAML2Exception {
"Unable to get a key provider instance.");
throw new SAML2Exception(
}
if (idpSignCertAlias == null) {
"Unable to get the hosted IDP signing certificate alias.");
throw new SAML2Exception(
}
} else {
}
}
/**
* 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
*/
boolean signAssertion)
throws SAML2Exception {
boolean toEncryptAssertion = false;
boolean toEncryptNameID = false;
boolean toEncryptAttribute = false;
return;
}
return;
}
// get the encryption related flags from the SP Entity Config
if (!toEncryptAssertion) {
}
if ((!toEncryptAssertion) && (!toEncryptNameID)
&& (!toEncryptAttribute)) {
// all encryption flags are off, no encryption needed
if (signAssertion) {
}
return;
}
// get the encryption information
"failed to get service provider encryption key info.");
throw new SAML2Exception(
}
if (toEncryptAssertion) {
// sign assertion first, then encrypt the assertion
if (signAssertion) {
}
// we only encrypt the Assertion
if (encryptedAssertion == null) {
"failed to encrypt the assertion.");
throw new SAML2Exception(
}
}
} else {
// assertion if applicable
if (toEncryptNameID) {
// we need to encrypt the NameID
return;
}
return;
}
if (encryptedNameID == null) {
"failed to encrypt the NameID.");
throw new SAML2Exception(
"FailedToEncryptNameID"));
}
}
}
if (toEncryptAttribute) {
// we need to encrypt the Attribute
if ((attributeStatements != null)
// to hold all the AttributeStatements
for (int i = 0; i < asSize; i++) {
continue;
}
// holds all the encrypted Attributes in this statement
for (int j = 0; j < aSize; j++) {
if (encryptedAttribute == null) {
"failed to encrypt the Attribute.");
throw new SAML2Exception(
"FailedToEncryptAttribute"));
}
}
}
"Attribute encrypted.");
}
}
}
if (signAssertion) {
}
}
}
String spEntityID) {
try {
// get cot list of the idp
if (idpEntityCfg != null) {
}
return null;
}
return null;
}
// get cot list of the sp
if (spEntityCfg != null) {
}
return null;
}
return null;
}
// retain in the idpCOTList the intersection of two lists
break;
}
}
} catch (COTException ce) {
+ "circle of trust", ce);
}
} catch (SAML2Exception se) {
"Not able to getting writer URL : ", se);
}
} catch (Exception e) {
"Not able to getting writer URL : ", e);
}
}
return writerURL;
}
/**
* Returns the effective time from the IDP
* extended metadata . If the attreibute is not
* defined in the metadata then defaults to
* a value of 600 seconds (5 minutes).
*
* @return the effective time value in seconds.
*/
if (effectiveTimeStr != null) {
try {
"got effective time from config:" + effectiveTime);
}
} catch (NumberFormatException nfe) {
"Failed to get assertion effective time from " +
"IDP SSO config: ", nfe);
}
}
return effectiveTime;
}
/**
* Returns the NotBefore skew time from the IDP
* extended metadata . If the attreibute is not
* defined in the metadata then defaults to
* a value of 600 seconds (5 minutes).
*
* @return the NotBefore skew value in seconds.
*/
int notBeforeSkewTime =
// get the assertion effective time (in seconds)
if (skewTimeStr != null) {
try {
"got NotBefore skew time from config:"
}
} catch (NumberFormatException nfe) {
}
}
}
return notBeforeSkewTime;
}
}
}
return bytes;
}
public static long getValidTimeofResponse(
throws SAML2Exception {
// in seconds
if (timeskew < 0) {
}
}
}
// failed case
return (currentTimeMillis()
+ timeskew * 1000);
}
throw new SAML2Exception("nullConditions");
}
if (notOnOrAfter == null ||
(ret < currentTimeMillis())) {
+ " is invalid.");
}
throw new SAML2Exception(
}
return ret;
}
/**
* Signs SAMLv2 Response.
*
* @param realm the realm name.
* @param idpEntityID the identity provider entity identifier
* @param response the SAMLv2 <code>Response</code>
* @throws <code>SAML2Exception</code> if there is an
* error signing the response.
*/
+ "Unable to get a key provider instance.");
throw new SAML2Exception(
}
if (idpSignCertAlias == null) {
"Unable to get the hosted IDP signing certificate alias.");
throw new SAML2Exception(
}
} else {
}
}
/**
* Returns a <code>SAML2IdentityProviderAdapter</code>
*
* @param realm the realm name
* @param idpEntityID the entity id of the identity provider
* @return the <code>SAML2IdenityProviderAdapter</code>
* @throws SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
}
/**
* Validates if the Assertion Consumer Service URL acsURL exists in the
* metadata of the Service Provider spEntityID
*
* @param acsURL the assertion consumer service <code>URL</code>
* @param spEntityID the entity id of the service provider
* @param realm the realm name of the identity provider
* @return true if the assertion consumer service URL was found
* false otherwise
*/
throws SAML2Exception {
boolean isValidACSurl = false;
isValidACSurl = true;
"Found in the metadata");
break;
}
}
return isValidACSurl;
}
/**
* Returns the the value of the wantAssertionsSigned property
* @param spEntityID ID of the SP entity to be retrieved.
* @param realm The realm under which the entity resides.
* @return boolean value of the wantAssertionsSigned property.
* @throws SAML2MetaException if unable to retrieve the service
* provider's SSO descriptor.
*/
private static boolean wantAssertionsSigned(String realm, String spEntityID) throws SAML2Exception {
}
return spSSODescriptor.isWantAssertionsSigned();
}
/**
* Returns the service provider's SSO descriptor in an entity under the realm.
* @param realm The realm under which the entity resides.
* @param spEntityID ID of the SP entity to be retrieved.
* @param classMethod the calling class method
* @return <code>SPSSODescriptorElement</code> for the entity
* @throws SAML2Exception if entity is not found
*/
throws SAML2Exception {
if (metaManager == null) {
}
try {
if (spSSODescriptor == null) {
+ "Unable to get SP SSO Descriptor from metadata, descriptor is null.");
}
} catch (SAML2MetaException sme) {
SAML2Utils.debug.error(classMethod + "Unable to get SP SSO Descriptor from metadata, descriptor is null.");
}
return spSSODescriptor;
}
/**
* Check that the authenticated session belongs to the same realm where the IDP is defined.
*
* @param realm The realm where the IdP is defined.
* @param session The Session object of the authenticated user.
* @return true If the session was initiated in the same realm as the session's realm.
*/
boolean isValidSessionInRealm = false;
try {
// A user can only be authenticated in one realm
String sessionRealm = SAML2Utils.getSingleValuedSessionProperty(session, SAML2Constants.ORGANIZATION);
isValidSessionInRealm = true;
} else {
+ ", while the realm of the IdP is:" + realm);
}
}
}
} catch (SessionException ex) {
}
return isValidSessionInRealm;
}
if (authnStatements != null) {
if (authorities != null) {
}
}
}
return authenticatingAuthorities;
}
}