public void sendLogoutRequest(SAMLMessageContext context, SAMLCredential credential) throws SAMLException, MetadataProviderException, MessageEncodingException { // If no user is logged in we do not initialize the protocol. if (credential == null) { return; } IDPSSODescriptor idpDescriptor = (IDPSSODescriptor) context.getPeerEntityRoleMetadata(); SPSSODescriptor spDescriptor = (SPSSODescriptor) context.getLocalEntityRoleMetadata(); String binding = SAMLUtil.getLogoutBinding(idpDescriptor, spDescriptor); SingleLogoutService logoutServiceIDP = SAMLUtil.getLogoutServiceForBinding(idpDescriptor, binding); LogoutRequest logoutRequest = getLogoutRequest(context, credential, logoutServiceIDP); context.setCommunicationProfileId(getProfileIdentifier()); context.setOutboundMessage(logoutRequest); context.setOutboundSAMLMessage(logoutRequest); context.setPeerEntityEndpoint(logoutServiceIDP); boolean signMessage = context.getPeerExtendedMetadata().isRequireLogoutRequestSigned(); sendMessage(context, signMessage); SAMLMessageStorage messageStorage = context.getMessageStorage(); if (messageStorage != null) { messageStorage.storeMessage(logoutRequest.getID(), logoutRequest); } }
/** * @param logoutRequest * @param sessionId * @param queryString * @return * @throws IdentityException */ public SAMLSSOReqValidationResponseDTO process( LogoutRequest logoutRequest, String sessionId, String queryString) throws IdentityException { try { SAMLSSOReqValidationResponseDTO reqValidationResponseDTO = new SAMLSSOReqValidationResponseDTO(); reqValidationResponseDTO.setLogOutReq(true); String subject = null; String issuer = null; String defaultSigningAlgoUri = IdentityApplicationManagementUtil.getSigningAlgoURIByConfig(); String defaultDigestAlgoUri = IdentityApplicationManagementUtil.getDigestAlgoURIByConfig(); // Get the sessions from the SessionPersistenceManager and prepare // the logout responses SSOSessionPersistenceManager ssoSessionPersistenceManager = SSOSessionPersistenceManager.getPersistenceManager(); if (StringUtils.isBlank(sessionId)) { String message = "Session was already Expired"; log.error(message); return buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, logoutRequest.getDestination(), defaultSigningAlgoUri, defaultDigestAlgoUri); } String sessionIndex = ssoSessionPersistenceManager.getSessionIndexFromTokenId(sessionId); if (StringUtils.isBlank(sessionId)) { String message = "Session index value not found in the request"; log.error(message); reqValidationResponseDTO = buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, null, defaultSigningAlgoUri, defaultDigestAlgoUri); reqValidationResponseDTO.setLogoutFromAuthFramework(true); return reqValidationResponseDTO; } // Only if the logout request is received. if (logoutRequest != null) { if (logoutRequest.getIssuer() == null) { String message = "Issuer should be mentioned in the Logout Request"; log.error(message); return buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, logoutRequest.getDestination(), defaultSigningAlgoUri, defaultDigestAlgoUri); } // TODO : Check for BaseID and EncryptedID as well. if (logoutRequest.getNameID() != null) { NameID nameID = logoutRequest.getNameID(); subject = nameID.getValue(); } else { String message = "Subject Name should be specified in the Logout Request"; log.error(message); return buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, logoutRequest.getDestination(), defaultSigningAlgoUri, defaultDigestAlgoUri); } if (logoutRequest.getSessionIndexes() == null) { String message = "At least one Session Index should be present in the Logout Request"; log.error(message); return buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, logoutRequest.getDestination(), defaultSigningAlgoUri, defaultDigestAlgoUri); } SessionInfoData sessionInfoData = ssoSessionPersistenceManager.getSessionInfo(sessionIndex); if (sessionInfoData == null) { String message = "No Established Sessions corresponding to Session Indexes provided."; log.error(message); reqValidationResponseDTO = buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, null, defaultSigningAlgoUri, defaultDigestAlgoUri); reqValidationResponseDTO.setLogoutFromAuthFramework(true); return reqValidationResponseDTO; } issuer = logoutRequest.getIssuer().getValue(); if (issuer.contains("@")) { String tenantDomain = issuer.substring(issuer.lastIndexOf('@') + 1); issuer = issuer.substring(0, issuer.lastIndexOf('@')); if (StringUtils.isNotEmpty(tenantDomain) && StringUtils.isNotEmpty(issuer)) { SAMLSSOUtil.setTenantDomainInThreadLocal(tenantDomain); if (log.isDebugEnabled()) { log.debug( "Tenant Domain :" + " " + tenantDomain + " " + "&" + " " + "Issuer name :" + issuer + " " + "has being spilt"); } } else { SAMLSSOServiceProviderDO serviceProvider = sessionInfoData.getServiceProviderList().get(issuer); if (serviceProvider != null) { SAMLSSOUtil.setTenantDomainInThreadLocal( sessionInfoData.getServiceProviderList().get(issuer).getTenantDomain()); } else { throw new IdentityException( "Service provider :" + issuer + " does not exist in session " + "info data."); } } } else { SAMLSSOServiceProviderDO serviceProvider = sessionInfoData.getServiceProviderList().get(issuer); if (serviceProvider != null) { SAMLSSOUtil.setTenantDomainInThreadLocal( sessionInfoData.getServiceProviderList().get(issuer).getTenantDomain()); } else { throw new IdentityException( "Service provider :" + issuer + " does not exist in session info " + "data."); } } subject = sessionInfoData.getSubject(issuer); Map<String, SAMLSSOServiceProviderDO> sessionsList = sessionInfoData.getServiceProviderList(); SAMLSSOServiceProviderDO logoutReqIssuer = sessionsList.get(issuer); if (logoutReqIssuer.isDoSingleLogout()) { // validate session index SessionIndex requestSessionIndex = logoutRequest.getSessionIndexes().size() > 0 ? logoutRequest.getSessionIndexes().get(0) : null; if (requestSessionIndex == null || !sessionIndex.equals(requestSessionIndex.getSessionIndex())) { String message = "Session Index validation for Logout Request failed. " + "Received: [" + (requestSessionIndex == null ? "null" : requestSessionIndex.getSessionIndex()) + "]." + " Expected: [" + sessionIndex + "]"; log.error(message); return buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, logoutRequest.getDestination(), logoutReqIssuer.getSigningAlgorithmUri(), logoutReqIssuer.getDigestAlgorithmUri()); } } if (logoutReqIssuer.isDoValidateSignatureInRequests()) { // Validate 'Destination' List<String> idpUrlSet = SAMLSSOUtil.getDestinationFromTenantDomain( SAMLSSOUtil.getTenantDomainFromThreadLocal()); if (logoutRequest.getDestination() == null || !idpUrlSet.contains(logoutRequest.getDestination())) { String message = "Destination validation for Logout Request failed. " + "Received: [" + logoutRequest.getDestination() + "]." + " Expected: [" + StringUtils.join(idpUrlSet, ',') + "]"; log.error(message); return buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, logoutRequest.getDestination(), logoutReqIssuer.getSigningAlgorithmUri(), logoutReqIssuer.getDigestAlgorithmUri()); } // Validate Signature boolean isSignatureValid = SAMLSSOUtil.validateLogoutRequestSignature( logoutRequest, logoutReqIssuer.getCertAlias(), subject, queryString); if (!isSignatureValid) { String message = "Signature validation for Logout Request failed"; log.error(message); return buildErrorResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, logoutRequest.getDestination(), logoutReqIssuer.getSigningAlgorithmUri(), logoutReqIssuer.getDigestAlgorithmUri()); } } SingleLogoutMessageBuilder logoutMsgBuilder = new SingleLogoutMessageBuilder(); Map<String, String> rpSessionsList = sessionInfoData.getRPSessionsList(); List<SingleLogoutRequestDTO> singleLogoutReqDTOs = new ArrayList<SingleLogoutRequestDTO>(); for (Map.Entry<String, SAMLSSOServiceProviderDO> entry : sessionsList.entrySet()) { String key = entry.getKey(); SAMLSSOServiceProviderDO value = entry.getValue(); if (!key.equals(issuer)) { SingleLogoutRequestDTO logoutReqDTO = new SingleLogoutRequestDTO(); if (StringUtils.isNotBlank(value.getSloRequestURL())) { logoutReqDTO.setAssertionConsumerURL(value.getSloRequestURL()); } else if (StringUtils.isNotBlank(value.getSloResponseURL())) { logoutReqDTO.setAssertionConsumerURL(value.getSloResponseURL()); } else { logoutReqDTO.setAssertionConsumerURL(value.getAssertionConsumerUrl()); } LogoutRequest logoutReq = logoutMsgBuilder.buildLogoutRequest( sessionInfoData.getSubject(key), sessionIndex, SAMLSSOConstants.SingleLogoutCodes.LOGOUT_USER, logoutReqDTO.getAssertionConsumerURL(), value.getNameIDFormat(), value.getTenantDomain(), value.getSigningAlgorithmUri(), value.getDigestAlgorithmUri()); String logoutReqString = SAMLSSOUtil.encode(SAMLSSOUtil.marshall(logoutReq)); logoutReqDTO.setLogoutResponse(logoutReqString); logoutReqDTO.setRpSessionId(rpSessionsList.get(key)); singleLogoutReqDTOs.add(logoutReqDTO); } else { reqValidationResponseDTO.setIssuer(value.getIssuer()); reqValidationResponseDTO.setDoSignResponse(value.isDoSignResponse()); reqValidationResponseDTO.setSigningAlgorithmUri(value.getSigningAlgorithmUri()); reqValidationResponseDTO.setDigestAlgorithmUri(value.getDigestAlgorithmUri()); if (StringUtils.isNotBlank(value.getSloResponseURL())) { reqValidationResponseDTO.setAssertionConsumerURL(value.getSloResponseURL()); } else { reqValidationResponseDTO.setAssertionConsumerURL(value.getAssertionConsumerUrl()); } } } reqValidationResponseDTO.setLogoutRespDTO( singleLogoutReqDTOs.toArray(new SingleLogoutRequestDTO[singleLogoutReqDTOs.size()])); LogoutResponse logoutResponse = logoutMsgBuilder.buildLogoutResponse( logoutRequest.getID(), SAMLSSOConstants.StatusCodes.SUCCESS_CODE, null, reqValidationResponseDTO.getAssertionConsumerURL(), reqValidationResponseDTO.isDoSignResponse(), SAMLSSOUtil.getTenantDomainFromThreadLocal(), reqValidationResponseDTO.getSigningAlgorithmUri(), reqValidationResponseDTO.getDigestAlgorithmUri()); reqValidationResponseDTO.setLogoutResponse( SAMLSSOUtil.encode(SAMLSSOUtil.marshall(logoutResponse))); reqValidationResponseDTO.setValid(true); } return reqValidationResponseDTO; } catch (UserStoreException | IdentityException e) { throw new IdentityException("Error Processing the Logout Request", e); } }