Issue
I am making an application using AWS cognito and Spring Boot. After registering, users confirm their account by email or SMS activation code. After they confirm their account, can I do an automatic session login? Can I start a session without a password only for confirmation cases?
Solution
Yes, you can perform login for the user without a password using Custom Authentication Flow.
You will have to add Lambda Triggers to handle your custom auth flow. In application, you will have to use AdminInitiateAuth API call.
Here is some code example to understand the general idea:
public void auth(String username) {
AwsBasicCredentials awsCreds = AwsBasicCredentials.create(AWS_KEY,
AWS_SECRET);
CognitoIdentityProviderClient identityProviderClient =
CognitoIdentityProviderClient.builder()
.credentialsProvider(StaticCredentialsProvider.create(awsCreds))
.region(Region.of(REGION))
.build();
final Map<String, String> authParams = new HashMap<>();
authParams.put("USERNAME", username);
authParams.put("SECRET_HASH", calculateSecretHash(CLIENT_ID,
CLIENT_SECRET, username));
final AdminInitiateAuthRequest authRequest = AdminInitiateAuthRequest.builder()
.authFlow(AuthFlowType.CUSTOM_AUTH)
.clientId(CLIENT_ID)
.userPoolId(POOL_ID)
.authParameters(authParams)
.build();
AdminInitiateAuthResponse result = identityProviderClient.adminInitiateAuth(authRequest);
System.out.println(result.authenticationResult().accessToken());
System.out.println(result.authenticationResult().idToken());
}
private String calculateSecretHash(String userPoolClientId, String userPoolClientSecret, String userName) {
final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
SecretKeySpec signingKey = new SecretKeySpec(
userPoolClientSecret.getBytes(StandardCharsets.UTF_8),
HMAC_SHA256_ALGORITHM);
try {
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
mac.init(signingKey);
mac.update(userName.getBytes(StandardCharsets.UTF_8));
byte[] rawHmac = mac.doFinal(userPoolClientId.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(rawHmac);
} catch (Exception e) {
throw new RuntimeException("Error while calculating ");
}
}
You will also need to add dependecies for AWS SDK:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>aws-core</artifactId>
<version>2.13.57</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>cognitoidentityprovider</artifactId>
<version>2.13.57</version>
</dependency>
And add Lambda for "Define Auth Challange" trigger of you user pool:
exports.handler = async (event) => {
// Don't do any checks just say that authentication is successfull
event.response.issueTokens = true;
event.response.failAuthentication = false;
return event;
};
Answered By - Yuriy P
Answer Checked By - David Goodson (JavaFixing Volunteer)