Skip to content

Commit

Permalink
chore: use testcontainers for cognito tests
Browse files Browse the repository at this point in the history
wip: Cognito Local v3.7.1 unsupported feature: "AdminInitiateAuth"
  • Loading branch information
hei-teacher committed Dec 5, 2021
1 parent fcfe4b7 commit 74166d4
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 36 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Expand Up @@ -69,7 +69,7 @@ dependencies {
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:postgresql'

testImplementation 'software.amazon.awssdk:cognitoidentityprovider:2.17.96'
}

dependencyManagement {
Expand Down
Expand Up @@ -2,12 +2,10 @@

import com.nimbusds.jose.JOSEException;
import com.nimbusds.jose.proc.BadJOSEException;
import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jwt.JWTClaimsSet;
import java.net.MalformedURLException;
import java.text.ParseException;

import com.nimbusds.jwt.proc.ConfigurableJWTProcessor;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import school.hei.haapi.exception.ApiException;
Expand Down Expand Up @@ -38,7 +36,7 @@ private String getEmail(JWTClaimsSet claims) {
}

private void verifyToken(JWTClaimsSet claims) {
if (!claims.getIssuer().equals(this.jwtConfiguration.getCognitoIdentityPoolUrlFormat())) {
if (!claims.getIssuer().equals(this.jwtConfiguration.getCognitoUserPoolUrl())) {
throw new ForbiddenException("Not a valid Token");
}
}
Expand Down
@@ -1,36 +1,21 @@
package school.hei.haapi.security.cognito;

import java.io.Serializable;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Configuration
public class JwtConfiguration implements Serializable {
private final String userPoolId;
private final String region;
public static final String EMAIL_FIELD = "email";
@Getter private final String cognitoUserPoolUrl;

public JwtConfiguration(
@Value("${cognito.jwt.userPoolId}") final String userPoolId,
@Value("${cognito.jwt.region}") final String region) {
this.userPoolId = userPoolId;
this.region = region;
}

public String getCognitoIdentityPoolUrlFormat() {
return String.format(
"https://cognito-idp.%s.amazonaws.com/%s", this.getRegion(), this.getUserPoolId());
public JwtConfiguration(@Value("${cognito.userPool.url}") final String cognitoUserPoolUrl) {
this.cognitoUserPoolUrl = cognitoUserPoolUrl;
}

public String getCognitoJwksUrlFormat() {
return getCognitoIdentityPoolUrlFormat() + "/.well-known/jwks.json";
}

public String getUserPoolId() {
return this.userPoolId;
}

public String getRegion() {
return this.region;
return cognitoUserPoolUrl + "/.well-known/jwks.json";
}
}
4 changes: 1 addition & 3 deletions src/main/resources/application.properties
@@ -1,8 +1,6 @@
server.port=8080

#cognito.jwt.userPoolId=
#cognito.jwt.region=us-east-2
#test.cognito.jwt.studenttoken=
#cognito.userPool.url=https://cognito-idp.<region>.amazonaws.com/<userPoolId>
cognito.jwt.jwsAlgorithm=RS256
cognito.jwt.readTimeout=2000
cognito.jwt.connectTimeout=2000
Expand Down
Expand Up @@ -39,8 +39,6 @@ void user_is_unauthenticated() {

assertThrows(
ForbiddenException.class,
() -> {
cognitoComponent.findEmailByBearer(bearer);
});
() -> cognitoComponent.findEmailByBearer(bearer));
}
}
Expand Up @@ -3,28 +3,87 @@
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.utility.DockerImageName;
import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProviderChain;
import software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderClient;
import software.amazon.awssdk.services.cognitoidentityprovider.model.*;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import static software.amazon.awssdk.regions.Region.EU_WEST_3;

public class AuthenticationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {

private static final PostgreSQLContainer<? extends PostgreSQLContainer<?>> postgreSQLContainer;
private static final String FLYWAY_TESTDATA_PATH = "classpath:/db/testdata";

private static final GenericContainer<?> cognitoContainer;
private static final String COGNITO_USERPOOL_URL;

static {
postgreSQLContainer =
new PostgreSQLContainer<>("postgres:13.2")
.withDatabaseName("it-db")
.withUsername("sa")
.withPassword("sa");
postgreSQLContainer.start();

int cognitoExposedPort = 9229;
cognitoContainer = new GenericContainer<>(DockerImageName.parse("jagregory/cognito-local:3.7.1"))
.withExposedPorts(cognitoExposedPort);
cognitoContainer.start();
String cognitoUrl = "http://localhost:" + cognitoContainer.getMappedPort(cognitoExposedPort);

CognitoIdentityProviderClient cognitoClient = CognitoIdentityProviderClient.builder()
.endpointOverride(URI.create(cognitoUrl))
// aws-cli requires region and credentials: give him dummy values
.region(EU_WEST_3)
.credentialsProvider(AwsCredentialsProviderChain.of(AnonymousCredentialsProvider.create()))
.build();
CreateUserPoolResponse createUserPoolResponse = cognitoClient.createUserPool(
CreateUserPoolRequest.builder()
.poolName("testUserPool")
.build()
);
String userPoolId = createUserPoolResponse.userPool().id();
COGNITO_USERPOOL_URL = String.format("http://localhost:%d/%s", cognitoExposedPort, userPoolId);

String testEmail = "ryan@hei.school";
String testPassword = "testPassword";
AttributeType emailAttr = AttributeType.builder().name("email").value(testEmail).build();
AdminCreateUserRequest createUserRequest = AdminCreateUserRequest.builder()
.userPoolId(userPoolId)
.username(testEmail)
.desiredDeliveryMediums(DeliveryMediumType.EMAIL)
.userAttributes(emailAttr) //, emailVerifiedAttr)
.messageAction(MessageActionType.SUPPRESS).build();
AdminCreateUserResponse createUserResponse = cognitoClient.adminCreateUser(createUserRequest);

Map<String, String> authParams = new HashMap<>();
authParams.put("USERNAME", testEmail);
authParams.put("PASS_WORD", "TODO");
AdminInitiateAuthRequest adminInitiateAuthRequest = AdminInitiateAuthRequest.builder()
.authFlow(AuthFlowType.ADMIN_NO_SRP_AUTH)
.userPoolId(userPoolId)
.authParameters(authParams)
.build();
AdminInitiateAuthResponse adminInitiateAuthResponse =
// TODO: Cognito Local v3.7.1 unsupported feature: "AdminInitiateAuth"
cognitoClient.adminInitiateAuth(adminInitiateAuthRequest);
}

@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
applicationContext,
"server.port=8081",
"cognito.userPool.url=" + COGNITO_USERPOOL_URL,
"spring.datasource.url=" + postgreSQLContainer.getJdbcUrl(),
"spring.datasource.username=" + postgreSQLContainer.getUsername(),
"spring.datasource.password=" + postgreSQLContainer.getPassword(),
Expand Down
Expand Up @@ -14,9 +14,5 @@ public class CallerData {
public static final String STUDENT1_TOKEN = "student1_token";
public static final String TEACHER1_TOKEN = "teacher1_token";

@Getter private final String token;

public CallerData(@Value("${test.cognito.jwt.studenttoken}") final String token) {
this.token = token;
}
@Getter private String token = "token";
}

0 comments on commit 74166d4

Please sign in to comment.