Skip to content

Commit

Permalink
initial version of spring-xsuaa-test lib SAP#29
Browse files Browse the repository at this point in the history
  • Loading branch information
nenaraab committed Jan 15, 2019
1 parent d3e0a36 commit 79ff15a
Show file tree
Hide file tree
Showing 18 changed files with 550 additions and 140 deletions.
9 changes: 6 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.sap.cloud.security.xsuaa</groupId>
Expand All @@ -10,7 +10,9 @@

<name>parent</name>
<url>https://github.com/SAP/cloud-security-xsuaa-integration</url>
<description>XSUAA authentication and authorization service integration libraries and samples for authenticating users and services </description>
<description>XSUAA authentication and authorization service integration libraries and samples for authenticating
users and services
</description>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
Expand Down Expand Up @@ -50,14 +52,15 @@
<spring.core.version>5.1.1.RELEASE</spring.core.version>
<junit.version>4.12</junit.version>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.source>1.8</maven.compiler.source>
<spring.security.version>5.1.1.RELEASE</spring.security.version>
</properties>

<modules>
<module>api</module>
<module>spring-xsuaa</module>
<module>spring-xsuaa-it</module>
<module>spring-xsuaa-test</module>
</modules>

<dependencyManagement>
Expand Down
1 change: 1 addition & 0 deletions spring-xsuaa-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# XSUAA Security Test library
142 changes: 142 additions & 0 deletions spring-xsuaa-test/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?xml version="1.0"?>
<project
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">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.sap.cloud.security.xsuaa</groupId>
<artifactId>parent</artifactId>
<version>1.2.0</version>
</parent>

<artifactId>spring-xsuaa-test</artifactId>
<name>spring-xsuaa-test</name>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring.core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>${spring.security.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.0.9.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
<execution>
<id>default-check</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<rules>
</rules>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.10.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>pmd</goal>
<goal>cpd</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>3.0.5</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>findbugs</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
/**
* 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.util.*;

import org.apache.commons.io.IOUtils;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaSigner;
import org.springframework.security.oauth2.jwt.Jwt;

import com.nimbusds.jwt.JWT;
import com.nimbusds.jwt.JWTClaimsSet;
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.
*/
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)
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 String[] scopes;
private String userName = "testuser";
private String jwtHeaderKeyId;
public Map<String, List<String>> attributes = new HashMap<>();

/**
* @param clientId
* the client ID that will be used for any created token
*/
public JwtGenerator(String clientId) {
this.clientId = clientId;
this.identityZone = IDENTITY_ZONE_ID;
}

public JwtGenerator() {
this(CLIENT_ID);
}

/**
* Changes the value of the jwt claim "user_name". The user name is also used for the "email" claim.
*
* @param userName
* @return
*/
public JwtGenerator setUserName(String userName) {
this.userName = userName;
return this;
}

/**
* Sets the roles as claim "scope" to the jwt.
*
* @param scopes
* the scopes that should be part of the token
* @return the JwtGenerator itself
*/
public JwtGenerator addScopes(String... scopes) {
this.scopes = scopes;
return this;
}

/**
* Adds the attributes as claim "xs.user.attribute" to the jwt.
*
* @param attributeName
* the attribute name that should be part of the token
* @param attributeValues
* the attribute value that should be part of the token
* @return the JwtGenerator itself
*/
public JwtGenerator addAttribute(String attributeName, String[] attributeValues) {
List<String> valueList = new ArrayList<>(Arrays.asList(attributeValues));
attributes.put(attributeName, valueList);
return this;
}

/**
* Sets the "keyId" value of the jwt token header.
*
* @param keyId
* the value of the signed jwt token header "keyId"
* @return the JwtGenerator itself
*/
public JwtGenerator setJwtHeaderKeyId(String keyId) {
this.jwtHeaderKeyId = keyId;
return this;
}

/**
* Returns an encoded JWT token for the `Authorization` header
*/
public String getTokenForAuthorizationHeader() {
try {
return "Bearer " + getToken().getTokenValue();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

/**
* Builds a basic Jwt with the given clientId, userName, scopes and attributes.
*
* @return jwt
*/
public Jwt getToken() throws Exception {
JWTClaimsSet.Builder claimsSetBuilder = getBasicClaimSet();

if (scopes != null && scopes.length > 0) {
claimsSetBuilder.claim("scope", scopes);
}
if (attributes.size() > 0) {
claimsSetBuilder.claim("xs.user.attributes", attributes);
}
return createFromClaims(claimsSetBuilder.build());
}

public Jwt createFromTemplate(String pathToTemplate) throws Exception {
String claimsFromTemplate = IOUtils.toString(JwtGenerator.class.getResourceAsStream(pathToTemplate), StandardCharsets.UTF_8);
String claimsWithReplacements = replacePlaceholders(claimsFromTemplate);
return createFromClaims(claimsWithReplacements, jwtHeaderKeyId);
}

public static Jwt createFromFile(String pathToJwt) throws Exception {
return convertTokenToOAuthJwt(IOUtils.resourceToString(pathToJwt, Charset.forName("UTF-8")));
}

public static Jwt createFromClaims(JWTClaimsSet claimsSet) throws Exception {
return createFromClaims(claimsSet.toString(), null);
}

/**
* Builds a basic set of claims
*
* @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 {
String token = signAndEncodeToken(claims, jwtHeaderKeyId);
return convertTokenToOAuthJwt(token);
}

private String replacePlaceholders(String claims) {
claims = claims.replace("$exp", String.valueOf(NO_EXPIRE));
claims = claims.replace("$clientid", clientId);
claims = claims.replace("$zid", identityZone);
claims = claims.replace("$username", userName);

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);

Map<String, String> 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<String, Object> headers = new LinkedHashMap<>(parsedJwt.getHeader().toJSONObject());
Jwt jwt = new Jwt(parsedJwt.getParsedString(), jwtClaimsSet.getIssueTime().toInstant(), jwtClaimsSet.getExpirationTime().toInstant(), headers, jwtClaimsSet.getClaims());
return jwt;
}
}
Loading

0 comments on commit 79ff15a

Please sign in to comment.