/** * Validates the authentication request according to IdP Initiated SAML SSO Web Browser * Specification * * @return SAMLSSOSignInResponseDTO * @throws org.wso2.carbon.identity.base.IdentityException */ public SAMLSSOReqValidationResponseDTO validate() throws IdentityException { SAMLSSOReqValidationResponseDTO validationResponse = new SAMLSSOReqValidationResponseDTO(); try { // spEntityID MUST NOT be null if (StringUtils.isNotBlank(spEntityID)) { validationResponse.setIssuer(spEntityID); } else { String errorResp = SAMLSSOUtil.buildErrorResponse( SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, "spEntityID parameter not found in request", null); if (log.isDebugEnabled()) { log.debug("spEntityID parameter not found in request"); } validationResponse.setResponse(errorResp); validationResponse.setValid(false); return validationResponse; } if (!SAMLSSOUtil.isSAMLIssuerExists( spEntityID, SAMLSSOUtil.getTenantDomainFromThreadLocal())) { String message = "A Service Provider with the Issuer '" + spEntityID + "' is not registered. Service " + "Provider should be registered in advance"; log.error(message); String errorResp = SAMLSSOUtil.buildErrorResponse( SAMLSSOConstants.StatusCodes.REQUESTOR_ERROR, message, null); validationResponse.setResponse(errorResp); validationResponse.setValid(false); return validationResponse; } // If SP has multiple ACS if (StringUtils.isNotBlank(acs)) { validationResponse.setAssertionConsumerURL(acs); } if (StringUtils.isBlank(SAMLSSOUtil.getTenantDomainFromThreadLocal())) { SAMLSSOUtil.setTenantDomainInThreadLocal(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME); } validationResponse.setValid(true); if (log.isDebugEnabled()) { log.debug("IdP Initiated SSO request validation is successful"); } return validationResponse; } catch (Exception e) { throw IdentityException.error("Error validating the IdP Initiated SSO request", e); } }
/** * Builds the SAML error response and sets the compressed value to the reqValidationResponseDTO * * @param id * @param status * @param statMsg * @param destination * @return * @throws IdentityException */ private SAMLSSOReqValidationResponseDTO buildErrorResponse( String id, String status, String statMsg, String destination, String responseSigningAlgorithmUri, String responseDigestAlgorithmUri) throws IdentityException { SAMLSSOReqValidationResponseDTO reqValidationResponseDTO = new SAMLSSOReqValidationResponseDTO(); LogoutResponse logoutResp = new SingleLogoutMessageBuilder() .buildLogoutResponse( id, status, statMsg, destination, false, null, responseSigningAlgorithmUri, responseDigestAlgorithmUri); reqValidationResponseDTO.setLogOutReq(true); reqValidationResponseDTO.setValid(false); try { reqValidationResponseDTO.setResponse( SAMLSSOUtil.compressResponse(SAMLSSOUtil.marshall(logoutResp))); } catch (IOException e) { throw new IdentityException("Error while creating logout response", e); } return reqValidationResponseDTO; }
/** * @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); } }