Skip to content

Commit

Permalink
Added tests for AuthServer to see if cache is working
Browse files Browse the repository at this point in the history
  • Loading branch information
Mme-adorsys committed Dec 12, 2023
1 parent e3657ae commit ea569e3
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 36 deletions.
4 changes: 2 additions & 2 deletions postgres.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ services:
POSTGRES_USER: db_user
POSTGRES_PASSWORD: db_user@123
POSTGRES_DB: sts
volumes:
- "./.docker/sts-db/postgres:/var/lib/postgresql/data"
# volumes:
# - "./.docker/sts-db/postgres:/var/lib/postgresql/data"
ports:
- 5432:5432
# networks:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
public class JpaSecret {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String subject;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import java.util.Arrays;
Expand Down Expand Up @@ -95,23 +92,23 @@ void setup() {
}


// @Test
@Test
void shouldReturnTheSameSecretForSameUser() {
String firstSecret = getDecryptedSecret(USERNAME_ONE, PASSWORD_ONE);
String secondSecret = getDecryptedSecret(USERNAME_ONE, PASSWORD_ONE);

assertThat(firstSecret, is(equalTo(secondSecret)));
}

// @Test
@Test
void shouldReturnDifferentSecretsForDifferentUsers() throws Exception {
String firstSecret = getDecryptedSecret(USERNAME_ONE, PASSWORD_ONE);
String secondSecret = getDecryptedSecret(USERNAME_TWO, PASSWORD_TWO);

assertThat(firstSecret, is(not(equalTo(secondSecret))));
}

// @Test
@Test
void shouldNotReturnTheSameTokenForSameUser() throws Exception {
TokenResponse firstTokenResponse = getSecretServerToken(USERNAME_ONE, PASSWORD_ONE);
assertThat(firstTokenResponse.getAccess_token(), is(notNullValue()));
Expand All @@ -122,7 +119,7 @@ void shouldNotReturnTheSameTokenForSameUser() throws Exception {
assertThat(firstTokenResponse, is(not(equalTo(secondTokenResponse))));
}

// @Test
@Test
void shouldNotGetSecretForInvalidAccessToken() throws Exception {
final String invalidAccessToken = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJvVjU2Uk9namthbTVzUmVqdjF6b1JVNmY" +
"1R3YtUGRTdjN2b1ZfRVY5MmxnIn0.eyJqdGkiOiI5NWY2MzQ4NC04MTk2LTQ2NzYtYjI4Ni1lYjY4YTFmOTZmYTAiLCJleHAiOjE1N" +
Expand Down Expand Up @@ -158,7 +155,7 @@ void shouldNotGetSecretForFakeAccessToken() throws Exception {
assertThat(((HttpClientErrorException) caughtException).getStatusCode(), is(equalTo(HttpStatus.FORBIDDEN)));
}

// @Test
@Test
void shouldGetEmptySecretsForUnknownAudience() throws Exception {
Authentication.AuthenticationToken authToken = authentication.login(USERNAME_ONE, PASSWORD_ONE);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ private AuthServer mapFromProperties(AuthServerConfigurationProperties.AuthServe
properties.getName(),
properties.getIssUrl(),
properties.getJwksUrl(),
properties.getRefreshIntervalSeconds(),
objectMapper
properties.getRefreshIntervalSeconds()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,9 @@
import java.util.List;

public class LoggingAuthServer extends AuthServer {
private static final Logger LOG = LoggerFactory.getLogger(LoggingBearerTokenValidator.class);
private final ObjectMapper objectMapper;

public LoggingAuthServer(String name, String issUrl, String jwksUrl, ObjectMapper objectMapper) {
super(name, issUrl, jwksUrl);
this.objectMapper = objectMapper;
}

public LoggingAuthServer(String name, String issUrl, String jwksUrl, int refreshIntervalSeconds, ObjectMapper objectMapper) {
public LoggingAuthServer(String name, String issUrl, String jwksUrl, int refreshIntervalSeconds) {
super(name, issUrl, jwksUrl, refreshIntervalSeconds);
this.objectMapper = objectMapper;
}

@Override
Expand Down
12 changes: 12 additions & 0 deletions sts-token-auth/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,17 @@
<artifactId>backport-util-concurrent</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,53 @@
import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.jwk.*;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.RemoteJWKSet;
import com.nimbusds.jose.jwk.source.JWKSourceBuilder;
import com.nimbusds.jose.proc.SecurityContext;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.net.URL;
import java.security.Key;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class AuthServer {
@Setter
@Getter
private String name;
@Getter
private final String issUrl;
private final String jwksUrl;
private int refreshIntervalSeconds = 600;
private final int refreshIntervalSeconds;

private final ConcurrentHashMap<String, JWK> jwkCache = new ConcurrentHashMap<>();
private long lastCacheUpdate = 0;
@Setter
JWKSource<SecurityContext> jwkSource;

final ConcurrentHashMap<String, JWK> jwkCache = new ConcurrentHashMap<>();
long lastCacheUpdate = 0;

public AuthServer(String name, String issUrl, String jwksUrl) {
super();
this.name = name;
this.issUrl = issUrl;
this.jwksUrl = jwksUrl;
this(name, issUrl, jwksUrl, 600);
}

@SneakyThrows
public AuthServer(String name, String issUrl, String jwksUrl, int refreshIntervalSeconds) {
super();
this.name = name;
this.issUrl = issUrl;
this.jwksUrl = jwksUrl;
this.refreshIntervalSeconds = refreshIntervalSeconds;

jwkSource = JWKSourceBuilder.create(new URL(this.jwksUrl)).build();
}

private void updateJwkCache() throws JsonWebKeyRetrievalException {
try {
JWKSource<SecurityContext> jwkSource = new RemoteJWKSet<>(new URL(this.jwksUrl));

List<JWK> jwks = jwkSource.get(new JWKSelector(new JWKMatcher.Builder().build()), null);
onJsonWebKeySetRetrieved(jwks);

Expand Down Expand Up @@ -83,11 +91,8 @@ public Key getJWK(String keyID) throws JsonWebKeyRetrievalException {
}
}

public void setName(String name) {
this.name = name;
}

protected void onJsonWebKeySetRetrieved(List<JWK> jwks) {
log.info("Retrieved {} keys from {}", jwks.size(), jwksUrl);
}

public static class JsonWebKeyRetrievalException extends RuntimeException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package de.adorsys.sts.tokenauth;

import com.nimbusds.jose.RemoteKeySourceException;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSelector;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.RemoteJWKSet;
import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jose.util.Base64URL;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPublicKey;
import java.util.Collections;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

class AuthServerTest {

private AuthServer authServer;
private RemoteJWKSet<SecurityContext> mockRemoteJWKSet;

@BeforeEach
void setUp() throws Exception {
authServer = new AuthServer("TestServer", "https://example.com/iss", "https://example.com/jwks", 10);
mockRemoteJWKSet = Mockito.mock(RemoteJWKSet.class);
JWK jwk = new RSAKey.Builder(new Base64URL("n"), new Base64URL("e")).keyID("testKey").build();
when(mockRemoteJWKSet.get(any(JWKSelector.class), any(SecurityContext.class))).thenReturn(Collections.singletonList(jwk));
}

@Test
void testCacheInitialization() {
assertTrue(authServer.jwkCache.isEmpty(), "Cache should be initially empty");
}

@Test
void testCacheUpdateAfterInterval() throws Exception {
// Simulieren, dass die letzte Aktualisierung lange zurückliegt
JWKSource<SecurityContext> mockJwkSource = Mockito.mock(JWKSource.class);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512); // 512-bit RSA key pair
KeyPair keyPair = keyPairGenerator.generateKeyPair();

// Create a mock RSAKey from the generated key pair
RSAKey rsaKey = new RSAKey.Builder((RSAPublicKey) keyPair.getPublic()).keyID("testKey").build();

// Configure your AuthServer instance
AuthServer authServer = new AuthServer("TestServer", "https://example.com/iss", "https://example.com/jwks");
authServer.setJwkSource(mockJwkSource); // Inject the mock

// Mock the JWKSource and configure it to return the mock RSAKey
Mockito.when(mockJwkSource.get(any(), any())).thenReturn(Collections.singletonList(rsaKey));
authServer.lastCacheUpdate = 0;
authServer.getJWK("testKey");

assertFalse(authServer.jwkCache.isEmpty(), "Cache should be updated after interval");
}

@Test
void testCacheUpdateOnNonExistingKey() {
assertThrows(AuthServer.JsonWebKeyRetrievalException.class, () -> authServer.getJWK("nonExistingKey"));
}

@Test
void testValidKeyRetrieval() throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512); // 512-bit RSA key pair
KeyPair keyPair = keyPairGenerator.generateKeyPair();

// Create a mock RSAKey from the generated key pair
RSAKey rsaKey = new RSAKey.Builder((RSAPublicKey) keyPair.getPublic()).keyID("testKey").build();

// Mock the JWKSource and configure it to return the mock RSAKey
JWKSource<SecurityContext> mockJwkSource = Mockito.mock(JWKSource.class);
Mockito.when(mockJwkSource.get(any(), any())).thenReturn(Collections.singletonList(rsaKey));

// Inject the mock JWKSource into your AuthServer
AuthServer authServer = new AuthServer("TestServer", "https://example.com/iss", "https://example.com/jwks");
// Assuming you have a method to set the JWKSource
authServer.setJwkSource(mockJwkSource);
// Now you can test your method
Key key = authServer.getJWK("testKey");

assertNotNull(key, "Should return a valid key for a valid keyID");
}

@Test
void testExceptionHandling() throws RemoteKeySourceException {
// Konfigurieren Sie das Mock-Objekt, um eine Ausnahme zu werfen
when(mockRemoteJWKSet.get(any(JWKSelector.class), any(SecurityContext.class))).thenThrow(new RuntimeException("Test Exception"));

assertThrows(AuthServer.JsonWebKeyRetrievalException.class, () -> authServer.getJWK("testKey"));
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mock-maker-inline

0 comments on commit ea569e3

Please sign in to comment.