protected Extensions getSAMLExtensions(HttpServletRequest request) { try { String samlRequest = request.getParameter(SSOConstants.HTTP_POST_PARAM_SAML2_AUTH_REQ); if (samlRequest == null) { samlRequest = (String) request.getAttribute(SSOConstants.HTTP_POST_PARAM_SAML2_AUTH_REQ); } if (samlRequest != null) { XMLObject xmlObject; if (SSOConstants.HTTP_POST.equals(request.getMethod())) { xmlObject = unmarshall(SSOUtils.decodeForPost(samlRequest)); } else { xmlObject = unmarshall(SSOUtils.decode(samlRequest)); } if (xmlObject instanceof AuthnRequest) { AuthnRequest authnRequest = (AuthnRequest) xmlObject; Extensions oldExtensions = authnRequest.getExtensions(); if (oldExtensions != null) { ExtensionsBuilder extBuilder = new ExtensionsBuilder(); Extensions extensions = extBuilder.buildObject( SAMLConstants.SAML20P_NS, Extensions.LOCAL_NAME, SAMLConstants.SAML20P_PREFIX); extensions.setDOM(oldExtensions.getDOM()); return extensions; } } } } catch (Exception e) { // TODO IDENTITY-2421 // ignore log.debug("Error while loading SAML Extensions", e); } return null; }
/** * Validate the signature of a SAML2 Response and Assertion * * @param response SAML2 Response * @return true, if signature is valid. */ private void validateSignature(Response response, Assertion assertion) throws SAMLSSOException { if (SSOUtils.isAuthnResponseSigned(properties)) { if (identityProvider.getCertificate() == null || identityProvider.getCertificate().isEmpty()) { throw new SAMLSSOException( "SAMLResponse signing is enabled, but IdP doesn't have a certificate"); } if (response.getSignature() == null) { throw new SAMLSSOException( "SAMLResponse signing is enabled, but signature element " + "not found in SAML Response element."); } else { try { X509Credential credential = new X509CredentialImpl(tenantDomain, identityProvider.getCertificate()); SignatureValidator validator = new SignatureValidator(credential); validator.validate(response.getSignature()); } catch (ValidationException e) { throw new SAMLSSOException("Signature validation failed for SAML Response", e); } } } if (SSOUtils.isAssertionSigningEnabled(properties)) { if (identityProvider.getCertificate() == null || identityProvider.getCertificate().isEmpty()) { throw new SAMLSSOException( "SAMLAssertion signing is enabled, but IdP doesn't have a certificate"); } if (assertion.getSignature() == null) { throw new SAMLSSOException( "SAMLAssertion signing is enabled, but signature element " + "not found in SAML Assertion element."); } else { try { X509Credential credential = new X509CredentialImpl(tenantDomain, identityProvider.getCertificate()); SignatureValidator validator = new SignatureValidator(credential); validator.validate(assertion.getSignature()); } catch (ValidationException e) { throw new SAMLSSOException("Signature validation failed for SAML Assertion", e); } } } }
protected AuthnRequest getAuthnRequest(AuthenticationContext context) throws SAMLSSOException { AuthnRequest authnRequest = null; AuthenticationRequest authenticationRequest = context.getAuthenticationRequest(); String[] samlRequestParams = authenticationRequest.getRequestQueryParam(SSOConstants.HTTP_POST_PARAM_SAML2_AUTH_REQ); String samlRequest = null; if (samlRequestParams != null && samlRequestParams.length > 0) { samlRequest = samlRequestParams[0]; XMLObject xmlObject; if (authenticationRequest.isPost()) { xmlObject = unmarshall(SSOUtils.decodeForPost(samlRequest)); } else { xmlObject = unmarshall(SSOUtils.decode(samlRequest)); } if (xmlObject instanceof AuthnRequest) { authnRequest = (AuthnRequest) xmlObject; } } return authnRequest; }
private LogoutRequest buildLogoutRequest( String user, String sessionIndexStr, String idpUrl, String nameQualifier, String spNameQualifier) throws SAMLSSOException { LogoutRequest logoutReq = new LogoutRequestBuilder().buildObject(); logoutReq.setID(SSOUtils.createID()); logoutReq.setDestination(idpUrl); DateTime issueInstant = new DateTime(); logoutReq.setIssueInstant(issueInstant); logoutReq.setNotOnOrAfter(new DateTime(issueInstant.getMillis() + 5 * 60 * 1000)); IssuerBuilder issuerBuilder = new IssuerBuilder(); Issuer issuer = issuerBuilder.buildObject(); String spEntityId = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.SP_ENTITY_ID); if (spEntityId != null && !spEntityId.isEmpty()) { issuer.setValue(spEntityId); } else { issuer.setValue("carbonServer"); } logoutReq.setIssuer(issuer); NameID nameId = new NameIDBuilder().buildObject(); nameId.setFormat(NameIDType.UNSPECIFIED); nameId.setValue(user); nameId.setNameQualifier(nameQualifier); nameId.setSPNameQualifier(spNameQualifier); logoutReq.setNameID(nameId); SessionIndex sessionIndex = new SessionIndexBuilder().buildObject(); if (sessionIndexStr != null) { sessionIndex.setSessionIndex(sessionIndexStr); } else { sessionIndex.setSessionIndex(UUID.randomUUID().toString()); } logoutReq.getSessionIndexes().add(sessionIndex); logoutReq.setReason("Single Logout"); return logoutReq; }
private AuthnRequest buildAuthnRequest( HttpServletRequest request, boolean isPassive, String idpUrl, AuthenticationContext context) throws SAMLSSOException { IssuerBuilder issuerBuilder = new IssuerBuilder(); Issuer issuer = issuerBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:assertion", "Issuer", "samlp"); String spEntityId = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.SP_ENTITY_ID); if (spEntityId != null && !spEntityId.isEmpty()) { issuer.setValue(spEntityId); } else { issuer.setValue("carbonServer"); } DateTime issueInstant = new DateTime(); /* Creation of AuthRequestObject */ AuthnRequestBuilder authRequestBuilder = new AuthnRequestBuilder(); AuthnRequest authRequest = authRequestBuilder.buildObject( "urn:oasis:names:tc:SAML:2.0:protocol", "AuthnRequest", "samlp"); authRequest.setForceAuthn(isForceAuthenticate(context)); authRequest.setIsPassive(isPassive); authRequest.setIssueInstant(issueInstant); String includeProtocolBindingProp = properties.get( IdentityApplicationConstants.Authenticator.SAML2SSO.INCLUDE_PROTOCOL_BINDING); if (StringUtils.isEmpty(includeProtocolBindingProp) || Boolean.parseBoolean(includeProtocolBindingProp)) { authRequest.setProtocolBinding(SAMLConstants.SAML2_POST_BINDING_URI); } String acsUrl = IdentityUtil.getServerURL(FrameworkConstants.COMMONAUTH); authRequest.setAssertionConsumerServiceURL(acsUrl); authRequest.setIssuer(issuer); authRequest.setID(SSOUtils.createID()); authRequest.setVersion(SAMLVersion.VERSION_20); authRequest.setDestination(idpUrl); String attributeConsumingServiceIndexProp = properties.get( IdentityApplicationConstants.Authenticator.SAML2SSO.ATTRIBUTE_CONSUMING_SERVICE_INDEX); if (StringUtils.isNotEmpty(attributeConsumingServiceIndexProp)) { try { authRequest.setAttributeConsumingServiceIndex( Integer.valueOf(attributeConsumingServiceIndexProp)); } catch (NumberFormatException e) { log.error( "Error while populating SAMLRequest with AttributeConsumingServiceIndex: " + attributeConsumingServiceIndexProp, e); } } String includeNameIDPolicyProp = properties.get(IdentityApplicationConstants.Authenticator.SAML2SSO.INCLUDE_NAME_ID_POLICY); if (StringUtils.isEmpty(includeNameIDPolicyProp) || Boolean.parseBoolean(includeNameIDPolicyProp)) { NameIDPolicyBuilder nameIdPolicyBuilder = new NameIDPolicyBuilder(); NameIDPolicy nameIdPolicy = nameIdPolicyBuilder.buildObject(); nameIdPolicy.setFormat(NameIDType.UNSPECIFIED); // nameIdPolicy.setSPNameQualifier("Issuer"); nameIdPolicy.setAllowCreate(true); authRequest.setNameIDPolicy(nameIdPolicy); } // Get the inbound SAMLRequest AuthnRequest inboundAuthnRequest = getAuthnRequest(context); RequestedAuthnContext requestedAuthnContext = buildRequestedAuthnContext(inboundAuthnRequest); if (requestedAuthnContext != null) { authRequest.setRequestedAuthnContext(requestedAuthnContext); } Extensions extensions = getSAMLExtensions(request); if (extensions != null) { authRequest.setExtensions(extensions); } return authRequest; }
private void processSSOResponse(HttpServletRequest request) throws SAMLSSOException { Response samlResponse = (Response) unmarshall( new String( Base64.decode(request.getParameter(SSOConstants.HTTP_POST_PARAM_SAML2_RESP)))); Assertion assertion = null; if (SSOUtils.isAssertionEncryptionEnabled(properties)) { List<EncryptedAssertion> encryptedAssertions = samlResponse.getEncryptedAssertions(); EncryptedAssertion encryptedAssertion = null; if (CollectionUtils.isNotEmpty(encryptedAssertions)) { encryptedAssertion = encryptedAssertions.get(0); try { assertion = getDecryptedAssertion(encryptedAssertion); } catch (Exception e) { throw new SAMLSSOException("Unable to decrypt the SAML Assertion", e); } } } else { List<Assertion> assertions = samlResponse.getAssertions(); if (CollectionUtils.isNotEmpty(assertions)) { assertion = assertions.get(0); } } if (assertion == null) { if (samlResponse.getStatus() != null && samlResponse.getStatus().getStatusCode() != null && samlResponse .getStatus() .getStatusCode() .getValue() .equals(SSOConstants.StatusCodes.IDENTITY_PROVIDER_ERROR) && samlResponse.getStatus().getStatusCode().getStatusCode() != null && samlResponse .getStatus() .getStatusCode() .getStatusCode() .getValue() .equals(SSOConstants.StatusCodes.NO_PASSIVE)) { return; } throw new SAMLSSOException("SAML Assertion not found in the Response"); } // Get the subject name from the Response Object and forward it to login_action.jsp String subject = null; String nameQualifier = null; String spNameQualifier = null; if (assertion.getSubject() != null && assertion.getSubject().getNameID() != null) { subject = assertion.getSubject().getNameID().getValue(); } if (subject == null) { throw new SAMLSSOException("SAML Response does not contain the name of the subject"); } request.getSession().setAttribute("username", subject); // get the subject nameQualifier = assertion.getSubject().getNameID().getNameQualifier(); spNameQualifier = assertion.getSubject().getNameID().getSPNameQualifier(); // validate audience restriction validateAudienceRestriction(assertion); // validate signature this SP only looking for assertion signature validateSignature(samlResponse, assertion); request.getSession(false).setAttribute("samlssoAttributes", getAssertionStatements(assertion)); // For removing the session when the single sign out request made by the SP itself if (SSOUtils.isLogoutEnabled(properties)) { String sessionId = assertion.getAuthnStatements().get(0).getSessionIndex(); if (sessionId == null) { throw new SAMLSSOException( "Single Logout is enabled but IdP Session ID not found in SAML Assertion"); } request.getSession().setAttribute(SSOConstants.IDP_SESSION, sessionId); request.getSession().setAttribute(SSOConstants.LOGOUT_USERNAME, nameQualifier); request.getSession().setAttribute(SSOConstants.SP_NAME_QUALIFIER, spNameQualifier); } }
/** * @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)); }
/** * 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; }