public void testResponseIdVerification() throws Exception {
// 1) CONFIGURATION AND INITIALIZATION OF TEST
// Create handlers
SAML2AuthenticationHandler authenticationHandler = new SAML2AuthenticationHandler();
SAML2InResponseToVerificationHandler verificationHandler = new SAML2InResponseToVerificationHandler();
// Create configuration for handlers
SAML2HandlerChainConfig chainConfig = new DefaultSAML2HandlerChainConfig();
SAML2HandlerConfig handlerConfig = new DefaultSAML2HandlerConfig();
handlerConfig.addParameter(GeneralConstants.NAMEID_FORMAT, JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get());
handlerConfig.addParameter(SAML2Handler.DISABLE_SENDING_ROLES, "true");
Map<String, Object> chainOptions = new HashMap<String, Object>();
ProviderType spType = new SPType();
chainOptions.put(GeneralConstants.CONFIGURATION, spType);
chainOptions.put(GeneralConstants.ROLE_VALIDATOR_IGNORE, "true");
chainConfig.set(chainOptions);
// Initialize the handlers
authenticationHandler.initChainConfig(chainConfig);
authenticationHandler.initHandlerConfig(handlerConfig);
verificationHandler.initChainConfig(chainConfig);
verificationHandler.initHandlerConfig(handlerConfig);
// Create a Protocol Context
MockHttpSession session = new MockHttpSession();
MockServletContext servletContext = new MockServletContext();
MockHttpServletRequest servletRequest = new MockHttpServletRequest(session, "POST");
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
HTTPContext httpContext = new HTTPContext(servletRequest, servletResponse, servletContext);
// Create handler request and response
IssuerInfoHolder issuerInfo = new IssuerInfoHolder("http://localhost:8080/sales/");
SAML2HandlerRequest request = new DefaultSAML2HandlerRequest(httpContext, issuerInfo.getIssuer(), null,
SAML2Handler.HANDLER_TYPE.SP);
request.setTypeOfRequestToBeGenerated(SAML2HandlerRequest.GENERATE_REQUEST_TYPE.AUTH);
SAML2HandlerResponse response = new DefaultSAML2HandlerResponse();
// 2) GENERATE SAML AUTHENTICATION REQUEST
// Generate SAML AuthnRequest with handlers
authenticationHandler.generateSAMLRequest(request, response);
verificationHandler.generateSAMLRequest(request, response);
// Parse document and verify that ID is saved in Http session
Document samlReqDoc = response.getResultingDocument();
SAMLParser parser = new SAMLParser();
AuthnRequestType authnRequest = (AuthnRequestType) parser.parse(DocumentUtil.getNodeAsStream(samlReqDoc));
assertEquals(authnRequest.getID(), servletRequest.getSession().getAttribute(GeneralConstants.AUTH_REQUEST_ID));
// 3) SEND SAML AUTHENTICATION REQUEST TO IDP
// Generate request and response for IDP
SAML2HandlerResponse handlerResponseFromIdp = sendRequestToIdp(authnRequest, samlReqDoc, httpContext, handlerConfig);
// Parse SAML response from IDP
Document doc2response = handlerResponseFromIdp.getResultingDocument();
assertNotNull(doc2response);
String responseString = DocumentUtil.asString(doc2response);
// 4) PROCESS SAML RESPONSE FROM IDP. VERIFICATION OF InResponseId SHOULD BE SUCCESSFUL
HandlerContext handlerContext = getHandlerRequestAndResponse(httpContext, issuerInfo, responseString);
// Assert that ID from session is not null
String inResponseIdFromSession = (String) servletRequest.getSession().getAttribute(GeneralConstants.AUTH_REQUEST_ID);
assertNotNull(inResponseIdFromSession);
// Handle response from IDP
authenticationHandler.handleStatusResponseType(handlerContext.request, handlerContext.response);
verificationHandler.handleStatusResponseType(handlerContext.request, handlerContext.response);
// Verify that Id is not in session anymore. Becaue it was removed by SAML2ResponseIdVerificationHandler
assertNull(servletRequest.getSession().getAttribute(GeneralConstants.AUTH_REQUEST_ID));
// 5) CHANGE InResponseId IN SAML RESPONSE. VALIDATION MUST FAIL NOW.
// Change InResponseId
String responseStringChangedId = responseString.replaceAll("InResponseTo=\"" + inResponseIdFromSession + "\"",
"InResponseTo=\"ID_101dcb5e-f432-4f45-87cb-47daff92edef\"");
HandlerContext handlerContextChangedId = getHandlerRequestAndResponse(httpContext, issuerInfo, responseStringChangedId);
// Set Id to session again as it was removed in previous processing
servletRequest.getSession().setAttribute(GeneralConstants.AUTH_REQUEST_ID, inResponseIdFromSession);
// Handle response with changed Id. This time it should fail
try {
authenticationHandler.handleStatusResponseType(handlerContextChangedId.request, handlerContextChangedId.response);
verificationHandler.handleStatusResponseType(handlerContextChangedId.request, handlerContextChangedId.response);
fail("Verification of InResponseTo should fail.");
} catch (ProcessingException pe) {
assertEquals(ErrorCodes.AUTHN_REQUEST_ID_VERIFICATION_FAILED, pe.getMessage());
}
// 6) REMOVE InResponseId FROM SAML RESPONSE. VALIDATION MUST FAIL NOW.
// Remove inResponseId
String responseStringRemovedId = responseString.replaceAll("InResponseTo=\"" + inResponseIdFromSession + "\"", "");
HandlerContext handlerContextRemovedId = getHandlerRequestAndResponse(httpContext, issuerInfo, responseStringRemovedId);
// Set Id to session again as it was removed in previous processing
servletRequest.getSession().setAttribute(GeneralConstants.AUTH_REQUEST_ID, inResponseIdFromSession);
// Now handle again response from IDP. This time it should also fail as InResponseTo is null
try {
authenticationHandler.handleStatusResponseType(handlerContextRemovedId.request, handlerContextRemovedId.response);
verificationHandler.handleStatusResponseType(handlerContextRemovedId.request, handlerContextRemovedId.response);
fail("Verification of InResponseTo should fail.");
} catch (ProcessingException pe) {
assertEquals(ErrorCodes.AUTHN_REQUEST_ID_VERIFICATION_FAILED, pe.getMessage());
}