use of com.sun.identity.saml2.profile.IDPSession in project OpenAM by OpenRock.
the class IDPSingleLogout method processLogoutRequest.
/**
* Gets and processes the Single <code>LogoutRequest</code> from SP
* and return <code>LogoutResponse</code>.
*
* @param logoutReq <code>LogoutRequest</code> from SP
* @param request the HttpServletRequest.
* @param response the HttpServletResponse.
* @param binding name of binding will be used for request processing.
* @param relayState the relay state.
* @param idpEntityID name of host entity ID.
* @param realm name of host entity.
* @param isVerified true if the request is verified already.
* @return LogoutResponse the target URL on successful
* <code>LogoutRequest</code>.
* @throws SAML2Exception if error processing
* <code>LogoutRequest</code>.
*/
public static LogoutResponse processLogoutRequest(LogoutRequest logoutReq, HttpServletRequest request, HttpServletResponse response, String binding, String relayState, String idpEntityID, String realm, boolean isVerified) throws SAML2Exception {
Status status = null;
String spEntity = logoutReq.getIssuer().getValue();
Object session = null;
String tmpStr = request.getParameter("isLBReq");
boolean isLBReq = (tmpStr == null || !tmpStr.equals("false"));
try {
do {
String requestId = logoutReq.getID();
SAML2Utils.verifyRequestIssuer(realm, idpEntityID, logoutReq.getIssuer(), requestId);
List siList = logoutReq.getSessionIndex();
if (siList == null) {
debug.error("IDPSingleLogout.processLogoutRequest: " + "session index are null in logout request");
status = SAML2Utils.generateStatus(SAML2Constants.REQUESTER, "");
break;
}
int numSI = siList.size();
// TODO : handle list of session index
Iterator siIter = siList.iterator();
String sessionIndex = null;
if (siIter.hasNext()) {
sessionIndex = (String) siIter.next();
}
if (debug.messageEnabled()) {
debug.message("IDPLogoutUtil.processLogoutRequest: " + "idpEntityID=" + idpEntityID + ", sessionIndex=" + sessionIndex);
}
if (sessionIndex == null) {
// this case won't happen
// according to the spec: SP has to send at least
// one sessionIndex, could be multiple (TODO: need
// to handle that above; but when IDP sends out
// logout request, it could omit sessionIndex list,
// which means all sessions on SP side, so SP side
// needs to care about this case
debug.error("IDPLogoutUtil.processLogoutRequest: " + "No session index in logout request");
status = SAML2Utils.generateStatus(SAML2Constants.REQUESTER, "");
break;
}
String remoteServiceURL = null;
if (isLBReq) {
// server id is the last two digit of the session index
String serverId = sessionIndex.substring(sessionIndex.length() - 2);
if (debug.messageEnabled()) {
debug.message("IDPSingleLogout.processLogoutRequest: " + "sessionIndex=" + sessionIndex + ", id=" + serverId);
}
// find out remote serice URL based on server id
remoteServiceURL = SAML2Utils.getRemoteServiceURL(serverId);
}
IDPSession idpSession = IDPCache.idpSessionsByIndices.get(sessionIndex);
if (idpSession == null && SAML2FailoverUtils.isSAML2FailoverEnabled()) {
// Read from SAML2 Token Repository
IDPSessionCopy idpSessionCopy = null;
try {
idpSessionCopy = (IDPSessionCopy) SAML2FailoverUtils.retrieveSAML2Token(sessionIndex);
} catch (SAML2TokenRepositoryException se) {
debug.error("IDPSingleLogout.processLogoutRequest: Error while deleting token from " + "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!!!");
}
}
if (idpSession == null) {
// peer then we have to route the request.
if (remoteServiceURL != null) {
boolean peerError = false;
String remoteLogoutURL = remoteServiceURL + SAML2Utils.removeDeployUri(request.getRequestURI());
String queryString = request.getQueryString();
if (queryString == null) {
remoteLogoutURL = remoteLogoutURL + "?isLBReq=false";
} else {
remoteLogoutURL = remoteLogoutURL + "?" + queryString + "&isLBReq=false";
}
LogoutResponse logoutRes = LogoutUtil.forwardToRemoteServer(logoutReq, remoteLogoutURL);
if ((logoutRes != null) && !isNameNotFound(logoutRes)) {
if ((isSuccess(logoutRes)) && (numSI > 0)) {
siList = LogoutUtil.getSessionIndex(logoutRes);
if (siList == null || siList.isEmpty()) {
peerError = false;
break;
}
}
} else {
peerError = true;
}
if (peerError || (siList != null && siList.size() > 0)) {
status = PARTIAL_LOGOUT_STATUS;
break;
} else {
status = SUCCESS_STATUS;
break;
}
} else {
debug.error("IDPLogoutUtil.processLogoutRequest: " + "IDP no longer has this session index " + sessionIndex);
status = SAML2Utils.generateStatus(SAML2Constants.RESPONDER, SAML2Utils.bundle.getString("invalidSessionIndex"));
break;
}
} else {
// signature.
if (!isVerified && !LogoutUtil.verifySLORequest(logoutReq, realm, logoutReq.getIssuer().getValue(), idpEntityID, SAML2Constants.IDP_ROLE)) {
throw new SAML2Exception(SAML2Utils.bundle.getString("invalidSignInRequest"));
}
}
session = idpSession.getSession();
// handle external application logout if configured
BaseConfigType idpConfig = SAML2Utils.getSAML2MetaManager().getIDPSSOConfig(realm, idpEntityID);
List appLogoutURL = (List) SAML2MetaUtils.getAttributes(idpConfig).get(SAML2Constants.APP_LOGOUT_URL);
if (debug.messageEnabled()) {
debug.message("IDPLogoutUtil.processLogoutRequest: " + "external app logout URL= " + appLogoutURL);
}
if ((appLogoutURL != null) && (appLogoutURL.size() != 0)) {
SAML2Utils.postToAppLogout(request, (String) appLogoutURL.get(0), session);
}
List<NameIDandSPpair> list = idpSession.getNameIDandSPpairs();
int n = list.size();
if (debug.messageEnabled()) {
debug.message("IDPLogoutUtil.processLogoutRequest: " + "NameIDandSPpair for " + sessionIndex + " is " + list + ", size=" + n);
}
NameIDandSPpair pair = null;
// remove sending SP from the list
String spIssuer = logoutReq.getIssuer().getValue();
for (int i = 0; i < n; i++) {
pair = list.get(i);
if (pair.getSPEntityID().equals(spIssuer)) {
list.remove(i);
removeTransientNameIDFromCache(pair.getNameID());
break;
}
}
List partners = idpSession.getSessionPartners();
boolean cleanUp = true;
if (partners != null && !partners.isEmpty()) {
cleanUp = false;
}
n = list.size();
if (n == 0) {
// this is the case where there is no other
// session participant
status = destroyTokenAndGenerateStatus(sessionIndex, idpSession.getSession(), request, response, cleanUp);
if (cleanUp) {
IDPCache.idpSessionsByIndices.remove(sessionIndex);
if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
}
if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
try {
SAML2FailoverUtils.deleteSAML2Token(sessionIndex);
} catch (SAML2TokenRepositoryException se) {
debug.error("IDPSingleLogout.processLogoutRequest: Error while deleting token from " + "SAML2 Token Repository for sessionIndex:" + sessionIndex, se);
}
}
IDPCache.authnContextCache.remove(sessionIndex);
}
break;
}
//We should save the originally used request binding to make sure the response is sent back using the
//correct binding.
idpSession.setOriginatingLogoutRequestBinding(binding);
// there are other SPs to be logged out
if (binding.equals(SAML2Constants.HTTP_REDIRECT) || binding.equals(SAML2Constants.HTTP_POST)) {
idpSession.setOriginatingLogoutRequestID(logoutReq.getID());
idpSession.setOriginatingLogoutSPEntityID(logoutReq.getIssuer().getValue());
}
int soapFailCount = 0;
for (int i = 0; i < n; i++) {
pair = list.remove(0);
removeTransientNameIDFromCache(pair.getNameID());
String spEntityID = pair.getSPEntityID();
if (debug.messageEnabled()) {
debug.message("IDPSingleLogout.processLogoutRequest: SP for " + sessionIndex + " is " + spEntityID);
}
List<SingleLogoutServiceElement> slosList = getSPSLOServiceEndpoints(realm, spEntityID);
// get IDP entity config in case of SOAP,for basic auth info
SPSSOConfigElement spConfig = null;
spConfig = SAML2Utils.getSAML2MetaManager().getSPSSOConfig(realm, spEntityID);
String uri = request.getRequestURI();
String metaAlias = SAML2MetaUtils.getMetaAliasByUri(uri);
HashMap paramsMap = new HashMap();
paramsMap.put(SAML2Constants.ROLE, SAML2Constants.IDP_ROLE);
StringBuffer requestID = null;
SingleLogoutServiceElement logoutEndpoint = LogoutUtil.getMostAppropriateSLOServiceLocation(slosList, idpSession.getOriginatingLogoutRequestBinding());
if (logoutEndpoint == null) {
continue;
}
try {
requestID = LogoutUtil.doLogout(metaAlias, spEntityID, null, logoutEndpoint, relayState, sessionIndex, pair.getNameID(), request, response, paramsMap, spConfig);
} catch (SAML2Exception ex) {
if (logoutEndpoint.getBinding().equals(SAML2Constants.SOAP)) {
debug.error("IDPSingleLogout.initiateLogoutRequest:", ex);
soapFailCount++;
continue;
} else {
throw ex;
}
}
String bindingUsed = logoutEndpoint.getBinding();
if (bindingUsed.equals(SAML2Constants.HTTP_REDIRECT) || bindingUsed.equals(SAML2Constants.HTTP_POST)) {
String requestIDStr = requestID.toString();
if (requestIDStr != null && requestIDStr.length() != 0) {
idpSession.setPendingLogoutRequestID(requestIDStr);
}
return null;
}
}
if (soapFailCount == n) {
throw new SAML2Exception(SAML2Utils.bundle.getString("sloFailed"));
} else if (soapFailCount > 0) {
throw new SAML2Exception(SAML2Utils.bundle.getString("partialLogout"));
}
spEntity = idpSession.getOriginatingLogoutSPEntityID();
if (binding.equals(SAML2Constants.HTTP_REDIRECT) || binding.equals(SAML2Constants.HTTP_POST)) {
sendLastResponse(idpSession, null, request, response, sessionIndex, session, realm, idpEntityID, relayState);
return null;
} else {
// binding is SOAP, generate logout response
// and send to initiating SP
status = destroyTokenAndGenerateStatus(sessionIndex, idpSession.getSession(), request, response, true);
if (cleanUp) {
IDPCache.idpSessionsByIndices.remove(sessionIndex);
if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
}
if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
try {
SAML2FailoverUtils.deleteSAML2Token(sessionIndex);
} catch (SAML2TokenRepositoryException se) {
debug.error("IDPSingleLogout.processLogoutRequest: Error while deleting token from " + "SAML2 Token Repository for sessionIndex:" + sessionIndex, se);
}
}
IDPCache.authnContextCache.remove(sessionIndex);
}
}
} while (false);
} catch (SessionException ssoe) {
debug.error("IDPSingleLogout.processLogoutRequest: unable to get meta for ", ssoe);
status = SAML2Utils.generateStatus(idpEntityID, ssoe.toString());
} catch (SAML2Exception e) {
// show throw exception
e.printStackTrace();
SAML2Utils.debug.error("DB ERROR!!!");
}
// process multi-federation protocol
boolean isMultiProtocol = false;
try {
SessionProvider provider = SessionManager.getProvider();
if ((session != null) && (provider.isValid(session)) && MultiProtocolUtils.isMultipleProtocolSession(session, SingleLogoutManager.SAML2)) {
isMultiProtocol = true;
}
} catch (SessionException ex) {
//ignore
}
//here we are providing null for remote entity, because it's an unused variable in the method...
LogoutResponse logRes = LogoutUtil.generateResponse(status, logoutReq.getID(), SAML2Utils.createIssuer(idpEntityID), realm, SAML2Constants.IDP_ROLE, null);
if (!isMultiProtocol) {
return logRes;
} else {
try {
Set set = new HashSet();
set.add(session);
String sessUser = SessionManager.getProvider().getPrincipalName(session);
boolean isSOAPInitiated = binding.equals(SAML2Constants.SOAP);
SingleLogoutServiceElement endpoint = getLogoutResponseEndpoint(realm, spEntity, binding);
String location = getResponseLocation(endpoint);
logRes.setDestination(XMLUtils.escapeSpecialCharacters(location));
debug.message("IDPSingleLogout.processLogReq : call MP");
int retStat = SingleLogoutManager.getInstance().doIDPSingleLogout(set, sessUser, request, response, isSOAPInitiated, false, SingleLogoutManager.SAML2, realm, idpEntityID, spEntity, relayState, logoutReq.toXMLString(true, true), logRes.toXMLString(true, true), SingleLogoutManager.LOGOUT_SUCCEEDED_STATUS);
if (retStat != SingleLogoutManager.LOGOUT_REDIRECTED_STATUS) {
logRes = updateLogoutResponse(logRes, retStat);
return logRes;
} else {
return null;
}
} catch (SessionException ex) {
debug.error("IDPSingleLogout.ProcessLogoutRequest: SP " + "initiated SOAP logout", ex);
throw new SAML2Exception(ex.getMessage());
} catch (Exception ex) {
debug.error("IDPSingleLogout.ProcessLogoutRequest: SP " + "initiated SOAP logout (MP)", ex);
throw new SAML2Exception(ex.getMessage());
}
}
}
use of com.sun.identity.saml2.profile.IDPSession in project OpenAM by OpenRock.
the class IDPSingleLogout method initiateLogoutRequest.
/**
* Parses the request parameters and initiates the Logout
* Request to be sent to the SP.
*
* @param request the HttpServletRequest.
* @param response the HttpServletResponse.
* @param out the print writer for writing out presentation
* @param binding binding used for this request.
* @param paramsMap Map of all other parameters.
* Following parameters names with their respective
* String values are allowed in this paramsMap.
* "RelayState" - the target URL on successful Single Logout
* "Destination" - A URI Reference indicating the address to
* which the request has been sent.
* "Consent" - Specifies a URI a SAML defined identifier
* known as Consent Identifiers.
* "Extension" - Specifies a list of Extensions as list of
* String objects.
* @throws SAML2Exception if error initiating request to SP.
*/
public static void initiateLogoutRequest(HttpServletRequest request, HttpServletResponse response, PrintWriter out, String binding, Map paramsMap) throws SAML2Exception {
if (debug.messageEnabled()) {
debug.message("in initiateLogoutRequest");
debug.message("binding : " + binding);
debug.message("logoutAll : " + (String) paramsMap.get(SAML2Constants.LOGOUT_ALL));
debug.message("paramsMap : " + paramsMap);
}
boolean logoutall = false;
String logoutAllValue = (String) paramsMap.get(SAML2Constants.LOGOUT_ALL);
if ((logoutAllValue != null) && logoutAllValue.equalsIgnoreCase("true")) {
logoutall = true;
}
String metaAlias = (String) paramsMap.get(SAML2Constants.IDP_META_ALIAS);
try {
Object session = sessionProvider.getSession(request);
String sessUser = sessionProvider.getPrincipalName(session);
if (session == null) {
throw new SAML2Exception(SAML2Utils.bundle.getString("nullSSOToken"));
}
if (metaAlias == null) {
String[] values = sessionProvider.getProperty(session, SAML2Constants.IDP_META_ALIAS);
if (values != null && values.length != 0) {
metaAlias = values[0];
}
}
if (metaAlias == null) {
throw new SAML2Exception(SAML2Utils.bundle.getString("nullIDPMetaAlias"));
}
paramsMap.put(SAML2Constants.METAALIAS, metaAlias);
String realm = SAML2Utils.getRealm(SAML2MetaUtils.getRealmByMetaAlias(metaAlias));
String idpEntityID = sm.getEntityByMetaAlias(metaAlias);
if (idpEntityID == null) {
debug.error("Identity Provider ID is missing");
String[] data = { idpEntityID };
LogUtil.error(Level.INFO, LogUtil.INVALID_IDP, data, null);
throw new SAML2Exception(SAML2Utils.bundle.getString("nullIDPEntityID"));
}
// clean up session index
String idpSessionIndex = IDPSSOUtil.getSessionIndex(session);
if (idpSessionIndex == null) {
if (debug.messageEnabled()) {
debug.message("No SP session participant(s)");
}
MultiProtocolUtils.invalidateSession(session, request, response, SingleLogoutManager.SAML2);
return;
}
// then send the request to the original server
if (!SAML2FailoverUtils.isSAML2FailoverEnabled() && isMisroutedRequest(request, response, out, session)) {
return;
} else {
if (debug.messageEnabled()) {
debug.message("IDPSingleLogout.initiateLogoutRequest: " + "SAML2 Failover will be attempted. Be sure SFO is " + "properly configured or the attempt will fail");
}
}
IDPSession idpSession = IDPCache.idpSessionsByIndices.get(idpSessionIndex);
if (idpSession == null) {
if (debug.messageEnabled()) {
debug.message("IDPSLO.initiateLogoutRequest: " + "IDP Session with session index " + idpSessionIndex + " already removed.");
}
try {
if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
SAML2FailoverUtils.deleteSAML2Token(idpSessionIndex);
}
} catch (SAML2TokenRepositoryException se) {
debug.error("IDPSingleLogout.initiateLogoutReq: Error while deleting token from " + "SAML2 Token Repository for idpSessionIndex:" + idpSessionIndex, se);
}
IDPCache.authnContextCache.remove(idpSessionIndex);
MultiProtocolUtils.invalidateSession(session, request, response, SingleLogoutManager.SAML2);
return;
}
if (debug.messageEnabled()) {
debug.message("idpSessionIndex=" + idpSessionIndex);
}
List<NameIDandSPpair> list = idpSession.getNameIDandSPpairs();
int n = list.size();
if (debug.messageEnabled()) {
debug.message("IDPSingleLogout.initiateLogoutReq:" + " NameIDandSPpairs=" + list + ", size=" + n);
}
if (n == 0) {
if (debug.messageEnabled()) {
debug.message("No SP session participant(s)");
}
IDPCache.idpSessionsByIndices.remove(idpSessionIndex);
if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
}
try {
if (SAML2FailoverUtils.isSAML2FailoverEnabled()) {
SAML2FailoverUtils.deleteSAML2Token(idpSessionIndex);
}
} catch (SAML2TokenRepositoryException se) {
debug.error("IDPSingleLogout.initiateLogoutReq: Error while deleting token from " + "SAML2 Token Repository for idpSessionIndex:" + idpSessionIndex, se);
}
IDPCache.authnContextCache.remove(idpSessionIndex);
MultiProtocolUtils.invalidateSession(session, request, response, SingleLogoutManager.SAML2);
return;
}
String relayState = (String) paramsMap.get(SAML2Constants.RELAY_STATE);
// Validate the RelayState URL.
SAML2Utils.validateRelayStateURL(realm, idpEntityID, relayState, SAML2Constants.IDP_ROLE);
int soapFailCount = 0;
idpSession.setOriginatingLogoutRequestBinding(binding);
for (int i = 0; i < n; i++) {
NameIDandSPpair pair = list.remove(0);
removeTransientNameIDFromCache(pair.getNameID());
String spEntityID = pair.getSPEntityID();
if (debug.messageEnabled()) {
debug.message("IDPSingleLogout.initLogoutReq: processing spEntityID " + spEntityID);
}
List extensionsList = LogoutUtil.getExtensionsList(paramsMap);
List<SingleLogoutServiceElement> slosList = getSPSLOServiceEndpoints(realm, spEntityID);
// get IDP entity config in case of SOAP, for basic auth info
SPSSOConfigElement spConfig = sm.getSPSSOConfig(realm, spEntityID);
if (logoutall == true) {
idpSessionIndex = null;
}
SingleLogoutServiceElement logoutEndpoint = LogoutUtil.getMostAppropriateSLOServiceLocation(slosList, idpSession.getOriginatingLogoutRequestBinding());
if (logoutEndpoint == null) {
continue;
}
StringBuffer requestID = null;
try {
requestID = LogoutUtil.doLogout(metaAlias, spEntityID, extensionsList, logoutEndpoint, relayState, idpSessionIndex, pair.getNameID(), request, response, paramsMap, spConfig);
} catch (SAML2Exception ex) {
if (logoutEndpoint.getBinding().equals(SAML2Constants.SOAP)) {
debug.error("IDPSingleLogout.initiateLogoutRequest:", ex);
soapFailCount++;
continue;
} else {
throw ex;
}
}
String requestIDStr = requestID.toString();
String bindingUsed = logoutEndpoint.getBinding();
if (debug.messageEnabled()) {
debug.message("\nIDPSLO.requestIDStr = " + requestIDStr + "\nbinding = " + bindingUsed);
}
if (!requestIDStr.isEmpty() && (bindingUsed.equals(SAML2Constants.HTTP_REDIRECT) || bindingUsed.equals(SAML2Constants.HTTP_POST))) {
idpSession.setPendingLogoutRequestID(requestIDStr);
idpSession.setLogoutAll(logoutall);
Map logoutMap = (Map) paramsMap.get("LogoutMap");
if (logoutMap != null && !logoutMap.isEmpty()) {
IDPCache.logoutResponseCache.put(requestIDStr, (Map) paramsMap.get("LogoutMap"));
}
return;
}
}
//requested binding, or SOAP was used for the logout (or the mixture of this two).
if (logoutall == true) {
String userID = sessionProvider.getPrincipalName(idpSession.getSession());
destroyAllTokenForUser(userID, request, response);
} else {
MultiProtocolUtils.invalidateSession(idpSession.getSession(), request, response, SingleLogoutManager.SAML2);
IDPCache.idpSessionsByIndices.remove(idpSessionIndex);
if (agent != null && agent.isRunning() && saml2Svc != null) {
saml2Svc.setIdpSessionCount((long) IDPCache.idpSessionsByIndices.size());
}
IDPCache.authnContextCache.remove(idpSessionIndex);
}
//handling the case when the auth was initiated with HTTP-Redirect, but only SOAP or no SLO endpoint was
//available, and also the case when the whole logout process was using SOAP binding from the beginning
int logoutStatus = SingleLogoutManager.LOGOUT_SUCCEEDED_STATUS;
boolean isMultiProtocol = MultiProtocolUtils.isMultipleProtocolSession(request, SingleLogoutManager.SAML2);
//TODO: would be nice to actually return the correct message in idpSingleLogoutInit.jsp
if (soapFailCount == n) {
if (isMultiProtocol) {
logoutStatus = SingleLogoutManager.LOGOUT_FAILED_STATUS;
}
} else if (soapFailCount > 0) {
if (isMultiProtocol) {
logoutStatus = SingleLogoutManager.LOGOUT_PARTIAL_STATUS;
}
}
// processing multi-federation protocol session
if (isMultiProtocol) {
Set set = new HashSet();
set.add(session);
boolean isSOAPInitiated = binding.equals(SAML2Constants.SOAP) ? true : false;
int retStat = SingleLogoutManager.LOGOUT_SUCCEEDED_STATUS;
try {
debug.message("IDPSingleLogout.initLogReq: MP");
retStat = SingleLogoutManager.getInstance().doIDPSingleLogout(set, sessUser, request, response, isSOAPInitiated, true, SingleLogoutManager.SAML2, realm, idpEntityID, null, relayState, null, null, logoutStatus);
} catch (Exception ex) {
debug.warning("IDPSingleLogout.initiateLoogutReq: MP", ex);
throw new SAML2Exception(ex.getMessage());
}
if (debug.messageEnabled()) {
debug.message("IDPSingleLogout.initLogoutRequest: " + "SLOManager return status = " + retStat);
}
switch(retStat) {
case SingleLogoutManager.LOGOUT_FAILED_STATUS:
throw new SAML2Exception(SAML2Utils.bundle.getString("sloFailed"));
case SingleLogoutManager.LOGOUT_PARTIAL_STATUS:
throw new SAML2Exception(SAML2Utils.bundle.getString("partialLogout"));
default:
break;
}
}
} catch (SAML2MetaException sme) {
debug.error("Error retreiving metadata", sme);
throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
} catch (SessionException ssoe) {
debug.error("SessionException: ", ssoe);
throw new SAML2Exception(SAML2Utils.bundle.getString("metaDataError"));
}
}
use of com.sun.identity.saml2.profile.IDPSession 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;
}
use of com.sun.identity.saml2.profile.IDPSession in project OpenAM by OpenRock.
the class DoManageNameID method processManageNameIDRequest.
private static Status processManageNameIDRequest(ManageNameIDRequest mniRequest, String realm, String hostEntityID, String remoteEntityID, String hostRole, String userID) throws Exception {
String method = "processManageNameIDRequest: ";
if (debug.messageEnabled()) {
debug.message(method + "Host EntityID is : " + hostEntityID);
debug.message(method + "Host role is : " + hostRole);
debug.message(method + "Realm is : " + realm);
}
NameID nameID = getNameIDFromMNIRequest(mniRequest, realm, hostEntityID, hostRole);
NameIDInfo oldNameIDInfo = getNameIDInfo(userID, hostEntityID, remoteEntityID, hostRole, realm, nameID.getSPNameQualifier(), true);
NameID oldNameID = null;
if (oldNameIDInfo != null) {
oldNameID = oldNameIDInfo.getNameID();
}
if (oldNameID == null) {
// log manage name id failure
logError("unknownPrinciapl", LogUtil.UNKNOWN_PRINCIPAL, mniRequest.toXMLString(true, true));
return SAML2Utils.generateStatus(SAML2Constants.REQUESTER, SAML2Constants.UNKNOWN_PRINCIPAL, null);
}
List spFedSessions = null;
IDPSession idpSession = null;
// Terminate
if (hostRole.equalsIgnoreCase(SAML2Constants.IDP_ROLE)) {
idpSession = removeIDPFedSession(remoteEntityID, oldNameID.getValue());
} else {
spFedSessions = (List) SPCache.fedSessionListsByNameIDInfoKey.remove(oldNameIDInfo.getNameIDInfoKey().toValueString());
if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
saml2Svc.setFedSessionCount((long) SPCache.fedSessionListsByNameIDInfoKey.size());
}
}
if (!AccountUtils.removeAccountFederation(oldNameIDInfo, userID)) {
// log termination failure
logError("unableToTerminate", LogUtil.UNABLE_TO_TERMINATE, userID);
return SAML2Utils.generateStatus(SAML2Constants.RESPONDER, SAML2Utils.bundle.getString("unableToTerminate"));
}
if (mniRequest.getTerminate()) {
// log termination success
logAccess("requestSuccess", LogUtil.SUCCESS_FED_TERMINATION, userID);
return SAML2Utils.generateStatus(SAML2Constants.SUCCESS, SAML2Utils.bundle.getString("requestSuccess"));
}
// newID case
NewID newID = getNewIDFromMNIRequest(mniRequest, realm, hostEntityID, hostRole);
boolean isAffiliation = oldNameIDInfo.isAffiliation();
String spNameQualifier = oldNameID.getSPNameQualifier();
if (hostRole.equalsIgnoreCase(SAML2Constants.IDP_ROLE)) {
NameID newNameID = AssertionFactory.getInstance().createNameID();
newNameID.setValue(oldNameID.getValue());
newNameID.setNameQualifier(oldNameID.getNameQualifier());
newNameID.setSPNameQualifier(spNameQualifier);
newNameID.setFormat(oldNameID.getFormat());
newNameID.setSPProvidedID(newID.getValue());
NameIDInfo newNameIDinfo = new NameIDInfo(hostEntityID, (isAffiliation ? spNameQualifier : remoteEntityID), newNameID, SAML2Constants.IDP_ROLE, isAffiliation);
AccountUtils.setAccountFederation(newNameIDinfo, userID);
if (idpSession != null) {
// there are active session using this Name id
NameIDandSPpair pair = new NameIDandSPpair(newNameID, remoteEntityID);
synchronized (IDPCache.idpSessionsByIndices) {
List list = (List) idpSession.getNameIDandSPpairs();
list.add(pair);
}
}
// log new name id success
logAccess("requestSuccess", LogUtil.SUCCESS_NEW_NAMEID, userID);
return SAML2Utils.generateStatus(SAML2Constants.SUCCESS, SAML2Utils.bundle.getString("requestSuccess"));
}
// SP ROLE
NameID newNameID = AssertionFactory.getInstance().createNameID();
newNameID.setValue(newID.getValue());
newNameID.setNameQualifier(oldNameID.getNameQualifier());
newNameID.setSPProvidedID(oldNameID.getSPProvidedID());
newNameID.setSPNameQualifier(spNameQualifier);
newNameID.setFormat(oldNameID.getFormat());
NameIDInfo newNameIDInfo = new NameIDInfo((isAffiliation ? spNameQualifier : hostEntityID), remoteEntityID, newNameID, hostRole, isAffiliation);
AccountUtils.setAccountFederation(newNameIDInfo, userID);
if (spFedSessions != null) {
String newInfoKeyStr = newNameIDInfo.getNameIDInfoKey().toValueString();
String infoKeyAttribute = AccountUtils.getNameIDInfoKeyAttribute();
synchronized (spFedSessions) {
for (Iterator iter = spFedSessions.iterator(); iter.hasNext(); ) {
SPFedSession spFedSession = (SPFedSession) iter.next();
spFedSession.info = newNameIDInfo;
String tokenID = spFedSession.spTokenID;
try {
Object session = sessionProvider.getSession(tokenID);
String[] fromToken = sessionProvider.getProperty(session, infoKeyAttribute);
if ((fromToken == null) || (fromToken.length == 0) || (fromToken[0] == null) || (fromToken[0].length() == 0)) {
String[] values = { newInfoKeyStr };
sessionProvider.setProperty(session, infoKeyAttribute, values);
} else {
if (fromToken[0].indexOf(newInfoKeyStr) == -1) {
String[] values = { fromToken[0] + SAML2Constants.SECOND_DELIM + newInfoKeyStr };
sessionProvider.setProperty(session, infoKeyAttribute, values);
}
}
} catch (SessionException ex) {
debug.error("DoManageNameID." + "processManageNameIDRequest:", ex);
}
}
}
SPCache.fedSessionListsByNameIDInfoKey.put(newInfoKeyStr, spFedSessions);
if ((agent != null) && agent.isRunning() && (saml2Svc != null)) {
saml2Svc.setFedSessionCount((long) SPCache.fedSessionListsByNameIDInfoKey.size());
}
}
// log new name id success
logAccess("requestSuccess", LogUtil.SUCCESS_NEW_NAMEID, userID);
return SAML2Utils.generateStatus(SAML2Constants.SUCCESS, SAML2Utils.bundle.getString("requestSuccess"));
}
use of com.sun.identity.saml2.profile.IDPSession in project OpenAM by OpenRock.
the class IDPSSOUtil method sendResponseToACS.
/**
* 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, Object session, AuthnRequest authnReq, String spEntityID, String idpEntityID, String idpMetaAlias, String realm, String nameIDFormat, String relayState, AuthnContext matchingAuthnContext) throws SAML2Exception {
StringBuffer returnedBinding = new StringBuffer();
String acsURL = IDPSSOUtil.getACSurl(spEntityID, realm, authnReq, request, returnedBinding);
String acsBinding = returnedBinding.toString();
if ((acsURL == null) || (acsURL.trim().length() == 0)) {
SAML2Utils.debug.error("IDPSSOUtil.sendResponseToACS:" + " no ACS URL found.");
String[] data = { idpMetaAlias };
LogUtil.error(Level.INFO, LogUtil.NO_ACS_URL, data, session);
throw new SAML2Exception(SAML2Utils.bundle.getString("UnableTofindACSURL"));
}
if ((acsBinding == null) || (acsBinding.trim().length() == 0)) {
SAML2Utils.debug.error("IDPSSOUtil.sendResponseToACS:" + " no return binding found.");
String[] data = { idpMetaAlias };
LogUtil.error(Level.INFO, LogUtil.NO_RETURN_BINDING, data, session);
throw new SAML2Exception(SAML2Utils.bundle.getString("UnableTofindBinding"));
}
String affiliationID = request.getParameter(SAML2Constants.AFFILIATION_ID);
//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.
String remoteServiceURL = SAML2Utils.getRemoteServiceURL(getSessionIndex(session));
if (remoteServiceURL != null) {
remoteServiceURL += SAML2Utils.removeDeployUri(request.getRequestURI()) + "?" + request.getQueryString();
if (SAML2Utils.debug.messageEnabled()) {
SAML2Utils.debug.message("SessionIndex for this SSOToken is not local, forwarding the request to: " + remoteServiceURL);
}
String redirectUrl = null;
String outputData = null;
String responseCode = null;
HashMap<String, String> remoteRequestData = SAML2Utils.sendRequestToOrigServer(request, response, remoteServiceURL);
if (remoteRequestData != null && !remoteRequestData.isEmpty()) {
redirectUrl = remoteRequestData.get(SAML2Constants.AM_REDIRECT_URL);
outputData = remoteRequestData.get(SAML2Constants.OUTPUT_DATA);
responseCode = remoteRequestData.get(SAML2Constants.RESPONSE_CODE);
}
try {
if (redirectUrl != null && !redirectUrl.isEmpty()) {
response.sendRedirect(redirectUrl);
} else {
if (responseCode != null) {
response.setStatus(Integer.valueOf(responseCode));
}
// no redirect, perhaps an error page, return the content
if (outputData != null && !outputData.isEmpty()) {
SAML2Utils.debug.message("Printing the forwarded response");
response.setContentType("text/html; charset=UTF-8");
out.println(outputData);
return;
}
}
} catch (IOException ioe) {
if (SAML2Utils.debug.messageEnabled()) {
SAML2Utils.debug.message("IDPSSOUtil.sendResponseToACS() error in Request Routing", ioe);
}
}
return;
}
//end of request proxy
// generate a response for the authn request
Response res = getResponse(request, session, authnReq, spEntityID, idpEntityID, idpMetaAlias, realm, nameIDFormat, acsURL, affiliationID, matchingAuthnContext);
if (res == null) {
SAML2Utils.debug.error("IDPSSOUtil.sendResponseToACS:" + " response is null");
String errorMsg = SAML2Utils.bundle.getString("UnableToCreateAssertion");
if (authnReq == null) {
//idp initiated case, will not send error response to sp
throw new SAML2Exception(errorMsg);
}
res = SAML2Utils.getErrorResponse(authnReq, SAML2Constants.RESPONDER, null, errorMsg, idpEntityID);
} else {
try {
String[] values = { idpMetaAlias };
sessionProvider.setProperty(session, SAML2Constants.IDP_META_ALIAS, values);
} catch (SessionException e) {
SAML2Utils.debug.error("IDPSSOUtil.sendResponseToACS:" + " error setting idpMetaAlias into the session: ", e);
}
}
if (res != null) {
// call multi-federation protocol to set the protocol
MultiProtocolUtils.addFederationProtocol(session, SingleLogoutManager.SAML2);
// check if the COT cookie needs to be set
if (setCOTCookie(request, response, acsBinding, spEntityID, idpEntityID, idpMetaAlias, realm, relayState, acsURL, res, session)) {
if (SAML2Utils.debug.messageEnabled()) {
SAML2Utils.debug.message("IDPSSOUtil.sendResponseToACS:" + " Redirected to set COT cookie.");
}
return;
}
if (SAML2Utils.debug.messageEnabled()) {
SAML2Utils.debug.message("IDPSSOUtil.sendResponseToACS:" + " Doesn't set COT cookie.");
SAML2Utils.debug.message("IDPSSOUtil.sendResponseToACS:" + " Response is: " + res.toXMLString());
}
try {
SAML2Utils.debug.message("IDPSSOUtil.sendResponseToACS: Invoking the IDP Adapter");
SAML2IdentityProviderAdapter idpAdapter = IDPSSOUtil.getIDPAdapterClass(realm, idpEntityID);
if (idpAdapter != null) {
idpAdapter.preSignResponse(authnReq, res, idpEntityID, realm, request, session, relayState);
}
} catch (SAML2Exception se) {
SAML2Utils.debug.error("IDPSSOUtil.sendResponseToACS: There was a problem when invoking the " + "preSendResponse of the IDP Adapter: ", se);
}
sendResponse(request, response, out, acsBinding, spEntityID, idpEntityID, idpMetaAlias, realm, relayState, acsURL, res, session);
} else {
SAML2Utils.debug.error("IDPSSOUtil.sendResponseToACS:" + " error response is null");
throw new SAML2Exception(SAML2Utils.bundle.getString("UnableToCreateErrorResponse"));
}
}
Aggregations