diff --git a/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java b/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java index ec3b0abf..282b20dd 100644 --- a/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java +++ b/core/src/main/java/com/onelogin/saml2/authn/SamlResponse.java @@ -72,6 +72,11 @@ public class SamlResponse { */ private Map nameIdData = null; + /** + * Context class (AuthnContextClassRef) in the response + */ + private String contextClass = null; + /** * URL of the current host + current view */ @@ -88,7 +93,7 @@ public class SamlResponse { private Exception validationException; /** - * The respone status code and messages + * The response status code and messages */ private SamlResponseStatus responseStatus; @@ -576,6 +581,18 @@ public String getNameIdSPNameQualifier() throws Exception { return spNameQualifier; } + public String getContextClass() throws XPathExpressionException, ValidationError { + if (this.contextClass == null) { + NodeList nodes = this.queryAssertion("/saml:AuthnStatement/saml:AuthnContext/saml:AuthnContextClassRef"); + switch(nodes.getLength()) { + case 0: break; // None defined. There should be one, but no big deal if an IDP fails to provide it + case 1: this.contextClass = nodes.item(0).getTextContent(); break; + default: throw new ValidationError("Multiple AuthnContextClassRef found in the Assertion.", ValidationError.WRONG_NUMBER_OF_CONTEXT_CLASSES); + } + } + return this.contextClass; + } + /** * Gets the Attributes from the AttributeStatement element. * diff --git a/core/src/main/java/com/onelogin/saml2/exception/ValidationError.java b/core/src/main/java/com/onelogin/saml2/exception/ValidationError.java index 7af9fac7..f3e7967e 100644 --- a/core/src/main/java/com/onelogin/saml2/exception/ValidationError.java +++ b/core/src/main/java/com/onelogin/saml2/exception/ValidationError.java @@ -54,6 +54,7 @@ public class ValidationError extends SAMLException { public static final int KEY_ALGORITHM_ERROR = 47; public static final int MISSING_ENCRYPTED_ELEMENT = 48; public static final int INVALID_ISSUE_INSTANT_FORMAT = 49; + public static final int WRONG_NUMBER_OF_CONTEXT_CLASSES = 50; private int errorCode; diff --git a/toolkit/src/main/java/com/onelogin/saml2/Auth.java b/toolkit/src/main/java/com/onelogin/saml2/Auth.java index 9d8f29cb..8e83697f 100644 --- a/toolkit/src/main/java/com/onelogin/saml2/Auth.java +++ b/toolkit/src/main/java/com/onelogin/saml2/Auth.java @@ -91,6 +91,11 @@ public class Auth { */ private String nameidSPNameQualifier; + /** + * AuthnContextClassRef - extracted from the AuthnStatement of the SAML Response + */ + private String contextClass; + /** * SessionIndex. When the user is logged, this stored it from the AuthnStatement of the SAML Response */ @@ -1209,6 +1214,7 @@ public void processResponse(String requestId) throws Exception { nameidFormat = samlResponse.getNameIdFormat(); nameidNameQualifier = samlResponse.getNameIdNameQualifier(); nameidSPNameQualifier = samlResponse.getNameIdSPNameQualifier(); + contextClass = samlResponse.getContextClass(); authenticated = true; attributes = samlResponse.getAttributes(); sessionIndex = samlResponse.getSessionIndex(); @@ -1442,6 +1448,11 @@ public final String getNameIdSPNameQualifier() { return nameidSPNameQualifier; } + /** + * @return the context class (AuthnContextClassRef) of the assertion + */ + public String getContextClass() { return contextClass; } + /** * @return the SessionIndex of the assertion */ diff --git a/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java b/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java index 53c82ef5..c9c44a43 100644 --- a/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java +++ b/toolkit/src/test/java/com/onelogin/saml2/test/AuthTest.java @@ -528,9 +528,11 @@ public void testProcessResponse() throws Exception { Auth auth = new Auth(settings, request, response); assertFalse(auth.isAuthenticated()); assertTrue(auth.getErrors().isEmpty()); + assertNull(auth.getContextClass()); auth.processResponse(); assertFalse(auth.isAuthenticated()); assertTrue(auth.getAttributes().isEmpty()); + assertNull(auth.getContextClass()); samlResponseEncoded = Util.getFileAsString("data/responses/valid_response.xml.base64"); when(request.getParameterMap()).thenReturn(singletonMap("SAMLResponse", new String[]{samlResponseEncoded})); @@ -564,6 +566,7 @@ public void testProcessResponse() throws Exception { assertEquals(attrValues, auth2.getAttribute("uid")); assertEquals(attrValues2, auth2.getAttribute("mail")); assertEquals(attrValues3, auth2.getAttribute("eduPersonAffiliation")); + assertEquals("urn:oasis:names:tc:SAML:2.0:ac:classes:Password", auth2.getContextClass()); assertEquals(keys, auth2.getAttributesName()); }