diff --git a/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java b/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java index b36972a531..a1097c4672 100644 --- a/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java +++ b/src/main/java/com/amazon/dlic/auth/http/jwt/AbstractHTTPJwtAuthenticator.java @@ -22,6 +22,8 @@ import java.util.Map.Entry; import java.util.regex.Pattern; +import com.google.common.annotations.VisibleForTesting; +import org.apache.commons.lang3.StringEscapeUtils; import org.apache.cxf.rs.security.jose.jwt.JwtClaims; import org.apache.cxf.rs.security.jose.jwt.JwtToken; import org.apache.http.HttpHeaders; @@ -163,7 +165,8 @@ protected String getJwtTokenString(RestRequest request) { return jwtToken; } - protected String extractSubject(JwtClaims claims) { + @VisibleForTesting + public String extractSubject(JwtClaims claims) { String subject = claims.getSubject(); if (subjectKey != null) { @@ -185,7 +188,7 @@ protected String extractSubject(JwtClaims claims) { subject = (String) subjectObject; } } - return subject; + return StringEscapeUtils.unescapeJava(subject); } @SuppressWarnings("unchecked") diff --git a/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java b/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java index 96beff9051..5d73f24c7a 100644 --- a/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java +++ b/src/main/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticator.java @@ -22,6 +22,7 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import com.google.common.annotations.VisibleForTesting; import net.shibboleth.utilities.java.support.xml.BasicParserPool; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.cxf.rs.security.jose.jwk.JsonWebKey; @@ -95,7 +96,8 @@ public class HTTPSamlAuthenticator implements HTTPAuthenticator, Destroyable { private Saml2SettingsProvider saml2SettingsProvider; private MetadataResolver metadataResolver; private AuthTokenProcessorHandler authTokenProcessorHandler; - private HTTPJwtAuthenticator httpJwtAuthenticator; + @VisibleForTesting + protected HTTPJwtAuthenticator httpJwtAuthenticator; private Settings jwtSettings; private static int resolverIdCounter = 0; diff --git a/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java b/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java index d8efce92db..b343d45e90 100644 --- a/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java +++ b/src/test/java/com/amazon/dlic/auth/http/saml/HTTPSamlAuthenticatorTest.java @@ -193,6 +193,45 @@ public void decryptAssertionsTest() throws Exception { Assert.assertEquals("horst", jwt.getClaim("sub")); } + @Test + public void unescapeUsernameTest() throws Exception { + mockSamlIdpServer.setAuthenticateUser("Amazon\\User1"); + mockSamlIdpServer.setEndpointQueryString(null); + mockSamlIdpServer.setSpSignatureCertificate(spSigningCertificate); + mockSamlIdpServer.setEncryptAssertion(true); + + Settings settings = Settings.builder().put(IDP_METADATA_URL, mockSamlIdpServer.getMetadataUri()) + .put("kibana_url", "http://wherever").put("idp.entity_id", mockSamlIdpServer.getIdpEntityId()) + .put("sp.signature_private_key", "-BEGIN PRIVATE KEY-\n" + + Base64.getEncoder().encodeToString(spSigningPrivateKey.getEncoded()) + "-END PRIVATE KEY-") + .put("exchange_key", "abc").put("roles_key", "roles").put("path.home", ".").build(); + + HTTPSamlAuthenticator samlAuthenticator = new HTTPSamlAuthenticator(settings, null); + + AuthenticateHeaders authenticateHeaders = getAutenticateHeaders(samlAuthenticator); + + String encodedSamlResponse = mockSamlIdpServer.handleSsoGetRequestURI(authenticateHeaders.location); + + RestRequest tokenRestRequest = buildTokenExchangeRestRequest(encodedSamlResponse, authenticateHeaders); + TestRestChannel tokenRestChannel = new TestRestChannel(tokenRestRequest); + + samlAuthenticator.reRequestAuthentication(tokenRestChannel, null); + + String responseJson = new String(BytesReference.toBytes(tokenRestChannel.response.content())); + HashMap response = DefaultObjectMapper.objectMapper.readValue(responseJson, + new TypeReference>() { + }); + String authorization = (String) response.get("authorization"); + + Assert.assertNotNull("Expected authorization attribute in JSON: " + responseJson, authorization); + + JwsJwtCompactConsumer jwtConsumer = new JwsJwtCompactConsumer(authorization.replaceAll("\\s*bearer\\s*", "")); + JwtToken jwt = jwtConsumer.getJwtToken(); + + Assert.assertEquals("Amazon\\\\User1", jwt.getClaim("sub")); + Assert.assertEquals("Amazon\\User1", samlAuthenticator.httpJwtAuthenticator.extractSubject(jwt.getClaims())); + } + @Test public void testMetadataBody() throws Exception { mockSamlIdpServer.setSignResponses(true);