private RequestedAuthnContext buildRequestedAuthnContext(AuthnRequest inboundAuthnRequest) throws SAMLSSOException { /* AuthnContext */ RequestedAuthnContextBuilder requestedAuthnContextBuilder = null; RequestedAuthnContext requestedAuthnContext = null; String includeAuthnContext = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.INCLUDE_AUTHN_CONTEXT); if (StringUtils.isNotEmpty(includeAuthnContext) && "as_request".equalsIgnoreCase(includeAuthnContext)) { if (inboundAuthnRequest != null) { RequestedAuthnContext incomingRequestedAuthnContext = inboundAuthnRequest.getRequestedAuthnContext(); if (incomingRequestedAuthnContext != null) { requestedAuthnContextBuilder = new RequestedAuthnContextBuilder(); requestedAuthnContext = requestedAuthnContextBuilder.buildObject(); requestedAuthnContext.setDOM(incomingRequestedAuthnContext.getDOM()); } } } else if (StringUtils.isEmpty(includeAuthnContext) || "yes".equalsIgnoreCase(includeAuthnContext)) { requestedAuthnContextBuilder = new RequestedAuthnContextBuilder(); requestedAuthnContext = requestedAuthnContextBuilder.buildObject(); /* AuthnContextClass */ AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder(); AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject( SAMLConstants.SAML20_NS, AuthnContextClassRef.DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML20_PREFIX); String authnContextClassProp = properties.get( IdentityApplicationConstants.Authenticator.SAML2SSO.AUTHENTICATION_CONTEXT_CLASS); if (StringUtils.isNotEmpty(authnContextClassProp)) { authnContextClassRef.setAuthnContextClassRef( IdentityApplicationManagementUtil.getSAMLAuthnContextClasses() .get(authnContextClassProp)); } else { authnContextClassRef.setAuthnContextClassRef(AuthnContext.PPT_AUTHN_CTX); } /* Authentication Context Comparison Level */ String authnContextComparison = properties.get( IdentityApplicationConstants.Authenticator.SAML2SSO .AUTHENTICATION_CONTEXT_COMPARISON_LEVEL); if (StringUtils.isNotEmpty(authnContextComparison)) { if (AuthnContextComparisonTypeEnumeration.EXACT .toString() .equalsIgnoreCase(authnContextComparison)) { requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT); } else if (AuthnContextComparisonTypeEnumeration.MINIMUM .toString() .equalsIgnoreCase(authnContextComparison)) { requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM); } else if (AuthnContextComparisonTypeEnumeration.MAXIMUM .toString() .equalsIgnoreCase(authnContextComparison)) { requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.MAXIMUM); } else if (AuthnContextComparisonTypeEnumeration.BETTER .toString() .equalsIgnoreCase(authnContextComparison)) { requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.BETTER); } } else { requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT); } requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef); } return requestedAuthnContext; }
/** * Returns the redirection URL with the appended SAML2 Request message * * @param request SAML 2 request * @return redirectionUrl */ @Override public String buildRequest( HttpServletRequest request, boolean isLogout, boolean isPassive, String loginPage, AuthenticationContext context) throws SAMLSSOException { doBootstrap(); String contextIdentifier = context.getContextIdentifier(); RequestAbstractType requestMessage; if (request.getParameter(SSOConstants.HTTP_POST_PARAM_SAML2_AUTH_REQ) == null) { String queryParam = context.getQueryParams(); if (queryParam != null) { String[] params = queryParam.split("&"); for (String param : params) { String[] values = param.split("="); if (values.length == 2 && SSOConstants.HTTP_POST_PARAM_SAML2_AUTH_REQ.equals(values[0])) { request.setAttribute(SSOConstants.HTTP_POST_PARAM_SAML2_AUTH_REQ, values[1]); break; } } } } if (!isLogout) { requestMessage = buildAuthnRequest(request, isPassive, loginPage, context); } else { String username = (String) request.getSession().getAttribute(SSOConstants.LOGOUT_USERNAME); String sessionIndex = (String) request.getSession().getAttribute(SSOConstants.LOGOUT_SESSION_INDEX); String nameQualifier = (String) request.getSession().getAttribute(SSOConstants.NAME_QUALIFIER); String spNameQualifier = (String) request.getSession().getAttribute(SSOConstants.SP_NAME_QUALIFIER); requestMessage = buildLogoutRequest(username, sessionIndex, loginPage, nameQualifier, spNameQualifier); } String idpUrl = null; boolean isSignAuth2SAMLUsingSuperTenant = false; String encodedRequestMessage = encodeRequestMessage(requestMessage); StringBuilder httpQueryString = new StringBuilder("SAMLRequest=" + encodedRequestMessage); try { httpQueryString.append("&RelayState=" + URLEncoder.encode(contextIdentifier, "UTF-8").trim()); } catch (UnsupportedEncodingException e) { throw new SAMLSSOException("Error occurred while url encoding RelayState", e); } if (SSOUtils.isAuthnRequestSigned(properties)) { String signatureAlgoProp = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.SIGNATURE_ALGORITHM); if (StringUtils.isEmpty(signatureAlgoProp)) { signatureAlgoProp = IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_SHA1; } String signatureAlgo = IdentityApplicationManagementUtil.getXMLSignatureAlgorithms().get(signatureAlgoProp); Map<String, String> parameterMap = FileBasedConfigurationBuilder.getInstance() .getAuthenticatorBean(SSOConstants.AUTHENTICATOR_NAME) .getParameterMap(); if (parameterMap.size() > 0) { isSignAuth2SAMLUsingSuperTenant = Boolean.parseBoolean(parameterMap.get(SIGN_AUTH2_SAML_USING_SUPER_TENANT)); } if (isSignAuth2SAMLUsingSuperTenant) { SSOUtils.addSignatureToHTTPQueryString( httpQueryString, signatureAlgo, new X509CredentialImpl(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, null)); } else { SSOUtils.addSignatureToHTTPQueryString( httpQueryString, signatureAlgo, new X509CredentialImpl(context.getTenantDomain(), null)); } } if (loginPage.indexOf("?") > -1) { idpUrl = loginPage.concat("&").concat(httpQueryString.toString()); } else { idpUrl = loginPage.concat("?").concat(httpQueryString.toString()); } return idpUrl; }
/** * @param request * @param isLogout * @param isPassive * @param loginPage * @return return encoded SAML Auth request * @throws SAMLSSOException */ public String buildPostRequest( HttpServletRequest request, boolean isLogout, boolean isPassive, String loginPage, AuthenticationContext context) throws SAMLSSOException { doBootstrap(); RequestAbstractType requestMessage; String signatureAlgoProp = null; String digestAlgoProp = null; String includeCertProp = null; String signatureAlgo = null; String digestAlgo = null; boolean includeCert = false; // get Signature Algorithm signatureAlgoProp = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.SIGNATURE_ALGORITHM); if (StringUtils.isEmpty(signatureAlgoProp)) { signatureAlgoProp = IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_SHA1; } signatureAlgo = IdentityApplicationManagementUtil.getXMLSignatureAlgorithms().get(signatureAlgoProp); // get Digest Algorithm digestAlgoProp = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.DIGEST_ALGORITHM); if (StringUtils.isEmpty(digestAlgoProp)) { digestAlgoProp = IdentityApplicationConstants.XML.DigestAlgorithm.SHA1; } digestAlgo = IdentityApplicationManagementUtil.getXMLDigestAlgorithms().get(digestAlgoProp); includeCertProp = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.INCLUDE_CERT); if (StringUtils.isEmpty(includeCertProp) || Boolean.parseBoolean(includeCertProp)) { includeCert = true; } if (!isLogout) { requestMessage = buildAuthnRequest(request, isPassive, loginPage, context); if (SSOUtils.isAuthnRequestSigned(properties)) { SSOUtils.setSignature( requestMessage, signatureAlgo, digestAlgo, includeCert, new X509CredentialImpl(context.getTenantDomain(), null)); } } else { String username = (String) request.getSession().getAttribute(SSOConstants.LOGOUT_USERNAME); String sessionIndex = (String) request.getSession().getAttribute(SSOConstants.LOGOUT_SESSION_INDEX); String nameQualifier = (String) request.getSession().getAttribute(SSOConstants.NAME_QUALIFIER); String spNameQualifier = (String) request.getSession().getAttribute(SSOConstants.SP_NAME_QUALIFIER); requestMessage = buildLogoutRequest(username, sessionIndex, loginPage, nameQualifier, spNameQualifier); if (SSOUtils.isLogoutRequestSigned(properties)) { SSOUtils.setSignature( requestMessage, signatureAlgo, digestAlgo, includeCert, new X509CredentialImpl(context.getTenantDomain(), null)); } } return SSOUtils.encode(SSOUtils.marshall(requestMessage)); }
/** * @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); } }