From 1aef40ee45b01e8ca84673fe08c07b767989e3d1 Mon Sep 17 00:00:00 2001 From: Nena Raab Date: Fri, 11 Jan 2019 19:40:24 +0100 Subject: [PATCH] minor change on test lib: formatting, exceptions, javadoc, README.md #29 --- spring-xsuaa-test/README.md | 17 +- spring-xsuaa-test/pom.xml | 268 +++++++++--------- .../security/xsuaa/test/JwtGenerator.java | 130 ++++++--- .../security/xsuaa/test/JwtGeneratorTest.java | 37 +-- .../security/xsuaa/test/TestConstants.java | 12 +- .../TokenAuthenticationConverterTest.java | 16 +- .../security/xsuaa/token/TokenImplTest.java | 53 ++-- .../XsuaaAudienceValidatorTest.java | 41 ++- .../security/container/UserInfoTestUtil.java | 5 +- 9 files changed, 343 insertions(+), 236 deletions(-) diff --git a/spring-xsuaa-test/README.md b/spring-xsuaa-test/README.md index ca8f0a4eb0..2308b319b1 100644 --- a/spring-xsuaa-test/README.md +++ b/spring-xsuaa-test/README.md @@ -1 +1,16 @@ -# XSUAA Security Test library \ No newline at end of file +# XSUAA Security Test library + +This library enhances the `spring-xsuaa` project. +This includes for example a `JwtGenerator` that generates JSON Web Tokens (JWT) that can be used for JUnit tests, as well as for local testing. + + `JwtGenerator` provides these helper functions to you: + 1. load an encoded **Jwt token from file** or + 1. create a **Jwt token from a template file**, whereas some placeholders gets replaced + 1. create a **basic Jwt token** that has minimal set of preconfigured claims, **which can be enhanced** with `scopes` and `xs.user.attributes` claims and `keyId` header. + 1. create an **individual Jwt token** based on a set of claims using Nimbus JOSE + JWT [`JWTClaimsSet.Builder()`](http://www.javadoc.io/doc/com.nimbusds/nimbus-jose-jwt/6.5.1). + + All of them are returned as [`Jwt`](https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/oauth2/jwt/Jwt.html), which offers you a `getTokenValue()` method that returns the encoded and signed Jwt token. You need to prefix this one with `Bearer ` in case you like to provide it via `Authorization` header to your application. + + > In most cases the Jwt gets Base64 encoded and signed with this [private key](/src/main/resources/privateKey.txt). + +Find examples on how to use the `JwtGenerator` [here](src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java). \ No newline at end of file diff --git a/spring-xsuaa-test/pom.xml b/spring-xsuaa-test/pom.xml index 244a98f91b..6e93fca314 100644 --- a/spring-xsuaa-test/pom.xml +++ b/spring-xsuaa-test/pom.xml @@ -1,142 +1,142 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + 4.0.0 - - com.sap.cloud.security.xsuaa - parent - 1.2.0 - + + com.sap.cloud.security.xsuaa + parent + 1.2.0 + - spring-xsuaa-test - spring-xsuaa-test - jar + spring-xsuaa-test + spring-xsuaa-test + jar - - - org.springframework.security - spring-security-core - ${spring.core.version} - provided - - - org.springframework.security - spring-security-oauth2-jose - ${spring.security.version} - provided - - - org.springframework.security - spring-security-jwt - 1.0.9.RELEASE - provided - - - commons-io - commons-io - 2.6 - provided - - - junit - junit - ${junit.version} - test - - - org.hamcrest - hamcrest-all - 1.3 - test - - + + + org.springframework.security + spring-security-core + ${spring.core.version} + provided + + + org.springframework.security + spring-security-oauth2-jose + ${spring.security.version} + provided + + + org.springframework.security + spring-security-jwt + 1.0.9.RELEASE + provided + + + commons-io + commons-io + 2.6 + provided + + + junit + junit + ${junit.version} + test + + + org.hamcrest + hamcrest-all + 1.3 + test + + - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-source-plugin - - - attach-sources - - jar - - - - - - org.jacoco - jacoco-maven-plugin - 0.8.2 - - - default-prepare-agent - - prepare-agent - - - - default-report - prepare-package - - report - - - - default-check - - check - - - - - - - - - - org.apache.maven.plugins - maven-pmd-plugin - 3.10.0 - - - verify - - pmd - cpd - - - - - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.5 - - - verify - - findbugs - - - - - - + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.2 + + + default-prepare-agent + + prepare-agent + + + + default-report + prepare-package + + report + + + + default-check + + check + + + + + + + + + + org.apache.maven.plugins + maven-pmd-plugin + 3.10.0 + + + verify + + pmd + cpd + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + + verify + + findbugs + + + + + + diff --git a/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java b/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java index 1a6d70283e..46ad4e1f8b 100644 --- a/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java +++ b/spring-xsuaa-test/src/main/java/com/sap/cloud/security/xsuaa/test/JwtGenerator.java @@ -1,17 +1,13 @@ -/** - * Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved. - * This file is licensed under the Apache Software License, - * v. 2 except as noted otherwise in the LICENSE file - * https://github.com/SAP/cloud-security-xsuaa-integration/blob/master/LICENSE - */ package com.sap.cloud.security.xsuaa.test; import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.text.ParseException; import java.util.*; import org.apache.commons.io.IOUtils; +import org.springframework.lang.Nullable; import org.springframework.security.jwt.JwtHelper; import org.springframework.security.jwt.crypto.sign.RsaSigner; import org.springframework.security.oauth2.jwt.Jwt; @@ -21,18 +17,21 @@ import com.nimbusds.jwt.JWTParser; /** - * Create tokens with a fixed private/public key and dummy values. The client ID, identity zone, and scopes are configurable. + * Create tokens with a fixed private/public key and dummy values. The client + * ID, identity zone, and scopes are configurable. */ public class JwtGenerator { public static final Date NO_EXPIRE_DATE = new Date(Long.MAX_VALUE); public static final int NO_EXPIRE = Integer.MAX_VALUE; public static final String CLIENT_ID = "sb-xsapplication!t895"; - public static final String IDENTITY_ZONE_ID = "uaa"; // must be 'uaa' to make use of mockserver (see XsuaaServiceConfigurationDefault.getTokenKeyUrl) + public static final String IDENTITY_ZONE_ID = "uaa"; // must be 'uaa' to make use of mockserver (see + // XsuaaServiceConfigurationDefault.getTokenKeyUrl) private static final String PRIVATE_KEY_FILE = "/privateKey.txt"; private final String clientId; private final String identityZone; - private static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:saml2-bearer"; // see TokenImpl.GRANTTYPE_SAML2BEARER; + private static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:saml2-bearer"; // see + // TokenImpl.GRANTTYPE_SAML2BEARER; private String[] scopes; private String userName = "testuser"; private String jwtHeaderKeyId; @@ -52,10 +51,12 @@ public JwtGenerator() { } /** - * Changes the value of the jwt claim "user_name". The user name is also used for the "email" claim. + * Changes the value of the jwt claim "user_name". The user name is also used + * for the "email" claim. * * @param userName - * @return + * the user name + * @return the JwtGenerator itself */ public JwtGenerator setUserName(String userName) { this.userName = userName; @@ -90,10 +91,10 @@ public JwtGenerator addAttribute(String attributeName, String[] attributeValues) } /** - * Sets the "keyId" value of the jwt token header. + * Sets the keyId value as "kid" header to the jwt. * * @param keyId - * the value of the signed jwt token header "keyId" + * the value of the signed jwt token header "kid" * @return the JwtGenerator itself */ public JwtGenerator setJwtHeaderKeyId(String keyId) { @@ -102,7 +103,9 @@ public JwtGenerator setJwtHeaderKeyId(String keyId) { } /** - * Returns an encoded JWT token for the `Authorization` header + * Returns an encoded JWT token for the "Authorization" REST header + * + * @return jwt token String with "Bearer " prefix */ public String getTokenForAuthorizationHeader() { try { @@ -114,11 +117,12 @@ public String getTokenForAuthorizationHeader() { } /** - * Builds a basic Jwt with the given clientId, userName, scopes and attributes. + * Builds a basic Jwt with the given clientId, userName, scopes, user attributes + * claims and the keyId header. * * @return jwt */ - public Jwt getToken() throws Exception { + public Jwt getToken() { JWTClaimsSet.Builder claimsSetBuilder = getBasicClaimSet(); if (scopes != null && scopes.length > 0) { @@ -127,20 +131,51 @@ public Jwt getToken() throws Exception { if (attributes.size() > 0) { claimsSetBuilder.claim("xs.user.attributes", attributes); } - return createFromClaims(claimsSetBuilder.build()); + return createFromClaims(claimsSetBuilder.build().toString(), jwtHeaderKeyId); } - public Jwt createFromTemplate(String pathToTemplate) throws Exception { - String claimsFromTemplate = IOUtils.toString(JwtGenerator.class.getResourceAsStream(pathToTemplate), StandardCharsets.UTF_8); + /** + * Creates a Jwt from a template file, which contains the claims. Optionally, + * configure the "keyId" header via {@link #setJwtHeaderKeyId(String)} + *

+ * This replaces these placeholders - "$exp" with a date, that will not expire - + * "$clientid" with the configured client id {@link #JwtGenerator(String)} - + * "$zid" with "uaa" - "$username" with the configured user name + * {@link #setUserName(String)} + * + * @param pathToTemplate + * classpath resource + * @return a jwt + * @throws IOException + * in case the template file can not be read + */ + public Jwt createFromTemplate(String pathToTemplate) throws IOException { + String claimsFromTemplate = IOUtils.resourceToString(pathToTemplate, StandardCharsets.UTF_8); String claimsWithReplacements = replacePlaceholders(claimsFromTemplate); return createFromClaims(claimsWithReplacements, jwtHeaderKeyId); } - public static Jwt createFromFile(String pathToJwt) throws Exception { + /** + * Creates a Jwt from a file, which contains an encoded Jwt token. + * + * @param pathToJwt + * classpath resource + * @return a jwt + * @throws IOException + * in case the template file can not be read + */ + public static Jwt createFromFile(String pathToJwt) throws IOException { return convertTokenToOAuthJwt(IOUtils.resourceToString(pathToJwt, Charset.forName("UTF-8"))); } - public static Jwt createFromClaims(JWTClaimsSet claimsSet) throws Exception { + /** + * Creates an individual Jwt based on the provided set of claims. + * + * @param claimsSet + * that can be created with Nimbus JOSE + JWT JWTClaimsSet.Builder + * @return a jwt + */ + public static Jwt createFromClaims(JWTClaimsSet claimsSet) { return createFromClaims(claimsSet.toString(), null); } @@ -150,10 +185,20 @@ public static Jwt createFromClaims(JWTClaimsSet claimsSet) throws Exception { * @return a basic set of claims */ private JWTClaimsSet.Builder getBasicClaimSet() { - return new JWTClaimsSet.Builder().issueTime(new Date()).expirationTime(JwtGenerator.NO_EXPIRE_DATE).claim("client_id", clientId).claim("origin", "userIdp").claim("cid", clientId).claim("user_name", userName).claim("user_id", "D012345").claim("email", userName + "@test.org").claim("zid", identityZone).claim("grant_type", GRANT_TYPE); - } - - private static Jwt createFromClaims(String claims, String jwtHeaderKeyId) throws Exception { + return new JWTClaimsSet.Builder() + .issueTime(new Date()) + .expirationTime(JwtGenerator.NO_EXPIRE_DATE) + .claim("client_id", clientId) + .claim("origin", "userIdp") + .claim("cid", clientId) + .claim("user_name", userName) + .claim("user_id", "D012345") + .claim("email", userName + "@test.org") + .claim("zid", identityZone) + .claim("grant_type", GRANT_TYPE); + } + + private static Jwt createFromClaims(String claims, String jwtHeaderKeyId) { String token = signAndEncodeToken(claims, jwtHeaderKeyId); return convertTokenToOAuthJwt(token); } @@ -167,25 +212,42 @@ private String replacePlaceholders(String claims) { return claims; } - private static String signAndEncodeToken(String claims, String keyId) throws IOException { - String privateKey = IOUtils.toString(JwtGenerator.class.getResourceAsStream(PRIVATE_KEY_FILE), StandardCharsets.UTF_8); // PEM format - RsaSigner signer = new RsaSigner(privateKey); + private static String signAndEncodeToken(String claims, String keyId) { + RsaSigner signer = new RsaSigner(readPrivateKeyFromFile()); Map headers = Collections.emptyMap(); if (keyId != null) { headers = new HashMap<>(); headers.put("kid", keyId); } + org.springframework.security.jwt.Jwt jwt = JwtHelper.encode(claims, signer, headers); return jwt.getEncoded(); } - public static Jwt convertTokenToOAuthJwt(String token) throws java.text.ParseException { - JWT parsedJwt = JWTParser.parse(token); - JWTClaimsSet jwtClaimsSet = parsedJwt.getJWTClaimsSet(); - Map headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject()); - Jwt jwt = new Jwt(parsedJwt.getParsedString(), jwtClaimsSet.getIssueTime().toInstant(), jwtClaimsSet.getExpirationTime().toInstant(), headers, jwtClaimsSet.getClaims()); + protected static String readPrivateKeyFromFile() { + String privateKey; + try { + privateKey = IOUtils.resourceToString(PRIVATE_KEY_FILE, StandardCharsets.UTF_8); // PEM format + } catch (IOException e) { + throw new RuntimeException("privateKey could not be read from " + PRIVATE_KEY_FILE, e); + } + return privateKey; + } + + @Nullable + public static Jwt convertTokenToOAuthJwt(String token) { + Jwt jwt; + try { + JWT parsedJwt = JWTParser.parse(token); + JWTClaimsSet jwtClaimsSet = parsedJwt.getJWTClaimsSet(); + Map headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject()); + jwt = new Jwt(parsedJwt.getParsedString(), jwtClaimsSet.getIssueTime().toInstant(), + jwtClaimsSet.getExpirationTime().toInstant(), headers, jwtClaimsSet.getClaims()); + } catch (ParseException e) { + throw new IllegalArgumentException("token can not be parsed. ", e); + } return jwt; } -} +} \ No newline at end of file diff --git a/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java b/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java index c91c8ccb10..3eb8a80577 100644 --- a/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java +++ b/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/JwtGeneratorTest.java @@ -1,9 +1,3 @@ -/** - * Copyright (c) 2018 SAP SE or an SAP affiliate company. All rights reserved. - * This file is licensed under the Apache Software License, - * v. 2 except as noted otherwise in the LICENSE file - * https://github.com/SAP/cloud-security-xsuaa-integration/blob/master/LICENSE - */ package com.sap.cloud.security.xsuaa.test; import static com.sap.cloud.security.xsuaa.test.TestConstants.*; @@ -12,6 +6,7 @@ import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.startsWith; +import java.io.IOException; import java.util.Map; import org.junit.Before; @@ -26,19 +21,19 @@ public class JwtGeneratorTest { private static final String MY_USER_NAME = "UserName"; @Before - public void setUp() throws Exception { + public void setUp() { jwtGenerator = new JwtGenerator(MY_CLIENT_ID); } @Test - public void testBasicJwtToken() throws Exception { + public void testBasicJwtToken() { Jwt jwt = new JwtGenerator().getToken(); assertThat(jwt.getClaimAsString("zid"), equalTo("uaa")); assertThat(jwt.getExpiresAt(), not(equals(nullValue()))); } @Test - public void testParameterizedJwtToken() throws Exception { + public void testParameterizedJwtToken() { jwtGenerator.setUserName(MY_USER_NAME); Jwt jwt = jwtGenerator.getToken(); assertThat(jwt.getClaimAsString("client_id"), equalTo(MY_CLIENT_ID)); @@ -50,27 +45,37 @@ public void testParameterizedJwtToken() throws Exception { } @Test - public void testBasicJwtTokenForHeader() throws Exception { + public void testBasicJwtTokenForHeader() { String tokenForHeader = jwtGenerator.getTokenForAuthorizationHeader(); assertThat(tokenForHeader, startsWith("Bearer ")); } @Test - public void testTokenWithScopes() throws Exception { + public void testTokenWithScopes() { Jwt jwt = jwtGenerator.addScopes(new String[] { DUMMY_SCOPE, ANOTHER_SCOPE }).getToken(); assertThat(jwt.getClaimAsStringList("scope"), hasItems(DUMMY_SCOPE, ANOTHER_SCOPE)); } @Test - public void testTokenWithAttributes() throws Exception { - Jwt jwt = jwtGenerator.addAttribute(DUMMY_ATTRIBUTE, new String[] { DUMMY_ATTRIBUTE }).addAttribute(ANOTHER_ATTRIBUTE, new String[] { ANOTHER_ATTRIBUTE_VALUE, ANOTHER_ATTRIBUTE_VALUE_2 }).getToken(); + public void testTokenWithAttributes() { + Jwt jwt = jwtGenerator.addAttribute(DUMMY_ATTRIBUTE, new String[] { DUMMY_ATTRIBUTE }) + .addAttribute(ANOTHER_ATTRIBUTE, new String[] { ANOTHER_ATTRIBUTE_VALUE, ANOTHER_ATTRIBUTE_VALUE_2 }) + .getToken(); Map attributes = jwt.getClaimAsMap("xs.user.attributes"); assertThat((JSONArray) attributes.get(DUMMY_ATTRIBUTE), contains(DUMMY_ATTRIBUTE)); - assertThat((JSONArray) attributes.get(ANOTHER_ATTRIBUTE), contains(ANOTHER_ATTRIBUTE_VALUE, ANOTHER_ATTRIBUTE_VALUE_2)); + assertThat((JSONArray) attributes.get(ANOTHER_ATTRIBUTE), + contains(ANOTHER_ATTRIBUTE_VALUE, ANOTHER_ATTRIBUTE_VALUE_2)); } @Test - public void testTokenFromTemplateWithScopesAndAttributes() throws Exception { + public void testTokenWithKeyId() { + Jwt jwt = jwtGenerator.setJwtHeaderKeyId("keyIdValue").getToken(); + assertThat(jwt.getHeaders().containsKey("kid"), is(true)); + assertThat(jwt.getHeaders().get("kid"), is("keyIdValue")); + } + + @Test + public void testTokenFromTemplateWithScopesAndAttributes() throws IOException { jwtGenerator.setUserName(MY_USER_NAME); Jwt jwt = jwtGenerator.createFromTemplate("/claims_template.txt"); @@ -87,7 +92,7 @@ public void testTokenFromTemplateWithScopesAndAttributes() throws Exception { } @Test - public void testTokenFromFile() throws Exception { + public void testTokenFromFile() throws IOException { Jwt jwtFromTemplate = jwtGenerator.createFromTemplate("/claims_template.txt"); String jwtTokenFromTemplate = jwtFromTemplate.getTokenValue(); Jwt jwtFromFile = JwtGenerator.createFromFile("/token_cc.txt"); diff --git a/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/TestConstants.java b/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/TestConstants.java index c86e11ea68..8e8db1c114 100644 --- a/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/TestConstants.java +++ b/spring-xsuaa-test/src/test/java/com/sap/cloud/security/xsuaa/test/TestConstants.java @@ -1,10 +1,10 @@ package com.sap.cloud.security.xsuaa.test; public interface TestConstants { - String DUMMY_SCOPE = "someScope"; - String ANOTHER_SCOPE = "someOtherScope"; - String DUMMY_ATTRIBUTE = "dummy-attribute"; - String ANOTHER_ATTRIBUTE = "another-attribute"; - String ANOTHER_ATTRIBUTE_VALUE = "100"; - String ANOTHER_ATTRIBUTE_VALUE_2 = "200"; + String DUMMY_SCOPE = "someScope"; + String ANOTHER_SCOPE = "someOtherScope"; + String DUMMY_ATTRIBUTE = "dummy-attribute"; + String ANOTHER_ATTRIBUTE = "another-attribute"; + String ANOTHER_ATTRIBUTE_VALUE = "100"; + String ANOTHER_ATTRIBUTE_VALUE_2 = "200"; } diff --git a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenAuthenticationConverterTest.java b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenAuthenticationConverterTest.java index 602fb54ade..b4ee4af61d 100644 --- a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenAuthenticationConverterTest.java +++ b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenAuthenticationConverterTest.java @@ -23,12 +23,12 @@ public class TokenAuthenticationConverterTest { String scopeOther = "other-app!234" + "." + "Other"; @Before - public void setup() throws Exception { + public void setup() { tokenConverter = new TokenAuthenticationConverter(xsAppName); } @Test - public void extractAuthoritiesWithoutScopes() throws Exception { + public void extractAuthoritiesWithoutScopes() { Jwt jwt = new JwtGenerator().getToken(); AbstractAuthenticationToken authenticationToken = tokenConverter.convert(jwt); @@ -36,7 +36,7 @@ public void extractAuthoritiesWithoutScopes() throws Exception { } @Test - public void extractAuthoritiesIgnoresForeignScopes() throws Exception { + public void extractAuthoritiesIgnoresForeignScopes() { Jwt jwt = new JwtGenerator().addScopes(scopeAdmin, scopeOther, scopeRead).getToken(); AbstractAuthenticationToken authenticationToken = tokenConverter.convert(jwt); @@ -45,7 +45,7 @@ public void extractAuthoritiesIgnoresForeignScopes() throws Exception { } @Test - public void extractAuthoritiesWithScopes() throws Exception { + public void extractAuthoritiesWithScopes() { Jwt jwt = new JwtGenerator().addScopes(scopeAdmin, scopeRead).getToken(); AbstractAuthenticationToken authenticationToken = tokenConverter.convert(jwt); @@ -55,10 +55,14 @@ public void extractAuthoritiesWithScopes() throws Exception { } @Test - public void extractCustomAuthoritiesWithScopes() throws Exception { + public void extractCustomAuthoritiesWithScopes() { tokenConverter = new MyTokenAuthenticationConverter(xsAppName, "cost-center", "country"); - Jwt jwt = new JwtGenerator().addScopes(scopeAdmin).addAttribute("cost-center", new String[] { "0815" }).addAttribute("country", new String[] { "DE", "IL" }).getToken(); + Jwt jwt = new JwtGenerator() + .addScopes(scopeAdmin) + .addAttribute("cost-center", new String[] { "0815" }) + .addAttribute("country", new String[] { "DE", "IL" }) + .getToken(); AbstractAuthenticationToken authenticationToken = tokenConverter.convert(jwt); assertThat(authenticationToken.getAuthorities().size(), is(4)); diff --git a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenImplTest.java b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenImplTest.java index 746c3ce4d2..ea9d5ef20f 100644 --- a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenImplTest.java +++ b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/TokenImplTest.java @@ -5,7 +5,9 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.eq; +import java.io.IOException; import java.net.URI; +import java.net.URISyntaxException; import java.util.*; import org.junit.Assert; @@ -41,8 +43,14 @@ public class TokenImplTest { private String zoneId = "e2f7fbdb-0326-40e6-940f-dfddad057ff3"; @Before - public void setup() throws Exception { - claimsSetBuilder = new JWTClaimsSet.Builder().issueTime(new Date()).expirationTime(JwtGenerator.NO_EXPIRE_DATE).claim(TokenImpl.CLAIM_USER_NAME, userName).claim(TokenImpl.CLAIM_EMAIL, userName + "@test.org").claim(TokenImpl.CLAIM_ZONE_ID, zoneId).claim(TokenImpl.CLAIM_CLIENT_ID, "sb-java-hello-world").claim(TokenImpl.CLAIM_ORIGIN, "userIdp").claim(TokenImpl.CLAIM_GRANT_TYPE, TokenImpl.GRANTTYPE_SAML2BEARER); + public void setup() throws IOException { + claimsSetBuilder = new JWTClaimsSet.Builder() + .issueTime(new Date()) + .expirationTime(JwtGenerator.NO_EXPIRE_DATE) + .claim(TokenImpl.CLAIM_USER_NAME, userName).claim(TokenImpl.CLAIM_EMAIL, userName + "@test.org") + .claim(TokenImpl.CLAIM_ZONE_ID, zoneId).claim(TokenImpl.CLAIM_CLIENT_ID, "sb-java-hello-world") + .claim(TokenImpl.CLAIM_ORIGIN, "userIdp") + .claim(TokenImpl.CLAIM_GRANT_TYPE, TokenImpl.GRANTTYPE_SAML2BEARER); jwtSaml = new JwtGenerator().createFromTemplate("/saml.txt"); jwtCC = JwtGenerator.createFromFile("/token_cc.txt"); @@ -50,7 +58,7 @@ public void setup() throws Exception { } @Test - public void checkBasicJwtWithoutScopes() throws Exception { + public void checkBasicJwtWithoutScopes() { token = createToken(claimsSetBuilder); assertThat(token.getPassword(), nullValue()); @@ -70,7 +78,7 @@ public void checkBasicJwtWithoutScopes() throws Exception { } @Test - public void getAuthoritiesReturnsApplicationScopes() throws Exception { + public void getAuthoritiesReturnsApplicationScopes() { List scopesList = new ArrayList<>(); scopesList.add(scopeWrite); scopesList.add(scopeRead); @@ -86,7 +94,7 @@ public void getAuthoritiesReturnsApplicationScopes() throws Exception { } @Test - public void getScopesReturnsAllScopes() throws Exception { + public void getScopesReturnsAllScopes() { List scopesList = new ArrayList<>(); scopesList.add(scopeWrite); scopesList.add(scopeRead); @@ -95,7 +103,7 @@ public void getScopesReturnsAllScopes() throws Exception { token = createToken(claimsSetBuilder); - Collection scopes = token.getScopes(); + Collection scopes = token.getScopes(); assertThat(scopes.size(), is(3)); assertThat(scopes, hasItem(scopeRead)); assertThat(scopes, hasItem(scopeWrite)); @@ -103,7 +111,7 @@ public void getScopesReturnsAllScopes() throws Exception { } @Test - public void getZoneIdAsTenantGuid() throws Exception { + public void getZoneIdAsTenantGuid() { claimsSetBuilder.claim(TokenImpl.CLAIM_ZONE_ID, zoneId); token = createToken(claimsSetBuilder); @@ -112,7 +120,7 @@ public void getZoneIdAsTenantGuid() throws Exception { } @Test - public void getAuthoritiesNoScopeClaimReturnsEmptyList() throws Exception { + public void getAuthoritiesNoScopeClaimReturnsEmptyList() { claimsSetBuilder.claim(Token.CLAIM_SCOPES, new ArrayList<>()); token = createToken(claimsSetBuilder); @@ -122,7 +130,7 @@ public void getAuthoritiesNoScopeClaimReturnsEmptyList() throws Exception { } @Test - public void isCredentialsExpiredWhenExpiryDateExceeded() throws Exception { + public void isCredentialsExpiredWhenExpiryDateExceeded() { claimsSetBuilder.issueTime(new Date(System.currentTimeMillis() - 300000)); claimsSetBuilder.expirationTime(new Date(System.currentTimeMillis() - 20000)); token = createToken(claimsSetBuilder); @@ -130,19 +138,19 @@ public void isCredentialsExpiredWhenExpiryDateExceeded() throws Exception { } @Test - public void getUserNameIsUniqueWithOrigin() throws Exception { + public void getUserNameIsUniqueWithOrigin() { token = createToken(claimsSetBuilder); assertThat(token.getUsername(), is("user/userIdp/testUser")); } @Test - public void toStringShouldReturnUserName() throws Exception { + public void toStringShouldReturnUserName() { token = createToken(claimsSetBuilder); assertThat(token.toString(), is(token.getUsername())); } @Test(expected = IllegalArgumentException.class) - public void getUserNameReturnsErrorWhenOriginContainsDelimeter() throws Exception { + public void getUserNameReturnsErrorWhenOriginContainsDelimeter() { claimsSetBuilder.claim(TokenImpl.CLAIM_ORIGIN, "my/Idp"); token = createToken(claimsSetBuilder); token.getUsername(); @@ -179,17 +187,17 @@ public void getPrincipalNameReturnUniqueClientId() { } @Test - public void getAuthoritiesReturnsAllAppScopes() { + public void getAuthoritiesReturnsAllAppScopes() { Token token = new TokenImpl(jwtSaml, "java-hello-world"); Collection authorities = (Collection) token.getAuthorities(); - assertThat(authorities.size(), is(3)); //no openid scope + assertThat(authorities.size(), is(3)); // no openid scope assertThat(authorities, hasItem(new SimpleGrantedAuthority("Delete"))); assertThat(authorities, hasItem(new SimpleGrantedAuthority("Display"))); assertThat(authorities, hasItem(new SimpleGrantedAuthority("Create"))); } @Test - public void getXsUserAttributeValues() throws Exception { + public void getXsUserAttributeValues() { Token token = new TokenImpl(jwtSaml, xsAppName); String[] userAttrValues = token.getXSUserAttribute("cost-center"); assertThat(userAttrValues.length, is(2)); @@ -198,7 +206,7 @@ public void getXsUserAttributeValues() throws Exception { } @Test - public void getServiceInstanceIdFromExtAttr() throws Exception { + public void getServiceInstanceIdFromExtAttr() { claimsSetBuilder.claim(TokenImpl.CLAIM_EXTERNAL_ATTR, new SamlExternalAttrClaim()); token = createToken(claimsSetBuilder); @@ -206,7 +214,7 @@ public void getServiceInstanceIdFromExtAttr() throws Exception { } @Test - public void getSubdomainFromExtAttr() throws Exception { + public void getSubdomainFromExtAttr() { claimsSetBuilder.claim(TokenImpl.CLAIM_EXTERNAL_ATTR, new SamlExternalAttrClaim()); token = createToken(claimsSetBuilder); @@ -214,7 +222,7 @@ public void getSubdomainFromExtAttr() throws Exception { } @Test - public void getSomeAdditionalAttributeValueFromAuthorizationAttr() throws Exception { + public void getSomeAdditionalAttributeValueFromAuthorizationAttr() { claimsSetBuilder.claim(TokenImpl.CLAIM_ADDITIONAL_AZ_ATTR, new AdditionalAuthorizationAttrClaim()); token = createToken(claimsSetBuilder); @@ -222,13 +230,13 @@ public void getSomeAdditionalAttributeValueFromAuthorizationAttr() throws Except } @Test - public void getAppToken() throws Exception { + public void getAppToken() { token = createToken(claimsSetBuilder); assertThat(token.getAppToken(), startsWith("eyJhbGciOiJSUzI1NiIsInR5")); } @Test - public void requestClientCredentialsToken() throws Exception { + public void requestClientCredentialsToken() throws URISyntaxException { // prepare response Map ccToken = new HashMap<>(); ccToken.put("access_token", "cc_token"); @@ -237,7 +245,8 @@ public void requestClientCredentialsToken() throws Exception { // http://myuaa.com/oauth/token?grant_type=client_credentials&authorities=%7B%22az_attr%22:%7B%22a%22:%22b%22,%22c%22:%22d%22%7D%7D RestTemplate mockRestTemplate = Mockito.mock(RestTemplate.class); ResponseEntity response = new ResponseEntity<>(ccToken, HttpStatus.OK); - Mockito.when(mockRestTemplate.postForEntity(any(URI.class), any(HttpEntity.class), eq(Map.class))).thenReturn(response); + Mockito.when(mockRestTemplate.postForEntity(any(URI.class), any(HttpEntity.class), eq(Map.class))) + .thenReturn(response); token = createToken(claimsSetBuilder); @@ -254,7 +263,7 @@ public void requestClientCredentialsToken() throws Exception { assertThat(token.requestToken(tokenRequest), is("cc_token")); } - private Token createToken(JWTClaimsSet.Builder claimsBuilder) throws Exception { + private Token createToken(JWTClaimsSet.Builder claimsBuilder) { Jwt jwt = JwtGenerator.createFromClaims(claimsBuilder.build()); return new TokenImpl(jwt, xsAppName); } diff --git a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java index fd942365f6..4be1da91a5 100644 --- a/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java +++ b/spring-xsuaa/src/test/java/com/sap/cloud/security/xsuaa/token/authentication/XsuaaAudienceValidatorTest.java @@ -1,5 +1,6 @@ package com.sap.cloud.security.xsuaa.token.authentication; +import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -25,7 +26,7 @@ public class XsuaaAudienceValidatorTest { private JWTClaimsSet.Builder claimsBuilder; @Before - public void setup() throws Exception { + public void setup() throws IOException { serviceConfigurationSameClientId = new DummyXsuaaServiceConfiguration("sb-test1!t1", "test1!t1"); serviceConfigurationOtherGrantedClientId = new DummyXsuaaServiceConfiguration("sb-test2!t1", "test2!t1"); serviceConfigurationUnGrantedClientId = new DummyXsuaaServiceConfiguration("sb-test3!t1", "test3!t1"); @@ -38,74 +39,84 @@ public void setup() throws Exception { @Test public void testSameClientId() { - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationSameClientId).validate(tokenWithAudience); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationSameClientId) + .validate(tokenWithAudience); Assert.assertFalse(result.hasErrors()); } @Test public void testSameClientIdWithoutAudience() { - OAuth2TokenValidatorResult result2 = new XsuaaAudienceValidator(serviceConfigurationSameClientId).validate(tokenWithoutAudience); + OAuth2TokenValidatorResult result2 = new XsuaaAudienceValidator(serviceConfigurationSameClientId) + .validate(tokenWithoutAudience); Assert.assertFalse(result2.hasErrors()); } @Test public void testOtherGrantedClientIdWithoutAudience() { - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId).validate(tokenWithoutAudience); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId) + .validate(tokenWithoutAudience); Assert.assertFalse(result.hasErrors()); } @Test public void testOtherGrantedClientIdWithoutAudienceAndDot() { - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(new DummyXsuaaServiceConfiguration("sb-test4!t1", "test4!t1")).validate(tokenWithAudience); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator( + new DummyXsuaaServiceConfiguration("sb-test4!t1", "test4!t1")).validate(tokenWithAudience); Assert.assertFalse(result.hasErrors()); } @Test public void testOtherGrantedClientId() { - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationUnGrantedClientId).validate(tokenWithAudience); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationUnGrantedClientId) + .validate(tokenWithAudience); Assert.assertTrue(result.hasErrors()); } @Test public void testUnGrantedClientId() { - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationUnGrantedClientId).validate(tokenWithAudience); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationUnGrantedClientId) + .validate(tokenWithAudience); Assert.assertTrue(result.hasErrors()); } @Test - public void testOtherGrantedClientIdWithoutAudienceButScopes() throws Exception { + public void testOtherGrantedClientIdWithoutAudienceButScopes() { List scopes = new ArrayList(); scopes.add("test2!t1.Display"); claimsBuilder.claim(Token.CLAIM_SCOPES, scopes); Jwt tokenWithoutAudienceButScopes = JwtGenerator.createFromClaims(claimsBuilder.build()); - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId).validate(tokenWithoutAudienceButScopes); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId) + .validate(tokenWithoutAudienceButScopes); Assert.assertFalse(result.hasErrors()); } @Test - public void testOtherGrantedClientIdWithoutAudienceAndMatchingScopes() throws Exception { + public void testOtherGrantedClientIdWithoutAudienceAndMatchingScopes() { List scopes = new ArrayList(); scopes.add("test3!t1.Display"); claimsBuilder.claim(Token.CLAIM_SCOPES, scopes); Jwt tokenWithoutAudienceButScopes = JwtGenerator.createFromClaims(claimsBuilder.build()); - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId).validate(tokenWithoutAudienceButScopes); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId) + .validate(tokenWithoutAudienceButScopes); Assert.assertTrue(result.hasErrors()); } @Test - public void testOtherGrantedClientIdWithoutAudienceAndScopes() throws Exception { + public void testOtherGrantedClientIdWithoutAudienceAndScopes() { Jwt tokenWithoutAudienceAndScopes = JwtGenerator.createFromClaims(claimsBuilder.build()); - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId).validate(tokenWithoutAudienceAndScopes); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId) + .validate(tokenWithoutAudienceAndScopes); Assert.assertTrue(result.hasErrors()); } @Test - public void testOtherGrantedClientIdWithoutAudienceAndEmptyScopes() throws Exception { + public void testOtherGrantedClientIdWithoutAudienceAndEmptyScopes() { claimsBuilder.claim(Token.CLAIM_SCOPES, "[]"); Jwt tokenWithoutAudienceAndScopes = JwtGenerator.createFromClaims(claimsBuilder.build()); - OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId).validate(tokenWithoutAudienceAndScopes); + OAuth2TokenValidatorResult result = new XsuaaAudienceValidator(serviceConfigurationOtherGrantedClientId) + .validate(tokenWithoutAudienceAndScopes); Assert.assertTrue(result.hasErrors()); } diff --git a/spring-xsuaa/src/test/java/com/sap/xs2/security/container/UserInfoTestUtil.java b/spring-xsuaa/src/test/java/com/sap/xs2/security/container/UserInfoTestUtil.java index e6e6a9494b..4bb3fed103 100644 --- a/spring-xsuaa/src/test/java/com/sap/xs2/security/container/UserInfoTestUtil.java +++ b/spring-xsuaa/src/test/java/com/sap/xs2/security/container/UserInfoTestUtil.java @@ -1,5 +1,6 @@ package com.sap.xs2.security.container; +import java.io.IOException; import java.nio.charset.Charset; import org.apache.commons.io.IOUtils; @@ -9,12 +10,12 @@ public class UserInfoTestUtil { - public static UserInfo createFromTemplate(String pathToTemplate, String appName) throws Exception { + public static UserInfo createFromTemplate(String pathToTemplate, String appName) throws IOException { Jwt jwt = new JwtGenerator().createFromTemplate(pathToTemplate); return new UserInfo(jwt, appName); } - public static UserInfo createFromJwtFile(String pathToJwt, String appName) throws Exception { + public static UserInfo createFromJwtFile(String pathToJwt, String appName) throws IOException { String token = IOUtils.resourceToString(pathToJwt, Charset.forName("UTF-8")); Jwt jwt = JwtGenerator.convertTokenToOAuthJwt(token); return new UserInfo(jwt, appName);