Skip to content

Commit 17610e0

Browse files
committed
awspringgh-1246: create some sample of using Cognito integration. Cover CognitoTemplate with tests. Support logout functionality
1 parent 84ffac1 commit 17610e0

File tree

13 files changed

+617
-44
lines changed

13 files changed

+617
-44
lines changed

spring-cloud-aws-cognito/src/main/java/io/awspring/cloud/cognito/CognitoAuthOperations.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ public interface CognitoAuthOperations {
4343
/**
4444
* Creates a new user with provided attributes
4545
* @param username - the username
46+
* @param password - the password
4647
* @param attributeTypes - the list of user attributes defined by user pool
4748
* @return {@link AdminCreateUserResponse} a result of user creation operation from the AWS Cognito
4849
*/
49-
AdminCreateUserResponse createUser(String username, List<AttributeType> attributeTypes);
50+
AdminCreateUserResponse createUser(String username, String password, List<AttributeType> attributeTypes);
5051

5152
/**
5253
* Resets password for a user
@@ -75,4 +76,10 @@ public interface CognitoAuthOperations {
7576
*/
7677
RespondToAuthChallengeResponse setPermanentPassword(String session, String username, String password);
7778

79+
/**
80+
* Invalidates user's access, id and refresh tokens
81+
* @param userName - the username
82+
*/
83+
void logout(String userName);
84+
7885
}

spring-cloud-aws-cognito/src/main/java/io/awspring/cloud/cognito/CognitoTemplate.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminCreateUserResponse;
2525
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminInitiateAuthRequest;
2626
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminInitiateAuthResponse;
27+
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminUserGlobalSignOutRequest;
2728
import software.amazon.awssdk.services.cognitoidentityprovider.model.AttributeType;
2829
import software.amazon.awssdk.services.cognitoidentityprovider.model.AuthFlowType;
2930
import software.amazon.awssdk.services.cognitoidentityprovider.model.ChallengeNameType;
@@ -69,9 +70,9 @@ public AdminInitiateAuthResponse login(String username, String password) {
6970
}
7071

7172
@Override
72-
public AdminCreateUserResponse createUser(String username, List<AttributeType> attributeTypes) {
73+
public AdminCreateUserResponse createUser(String username, String password, List<AttributeType> attributeTypes) {
7374
AdminCreateUserRequest createUserRequest = AdminCreateUserRequest.builder().userPoolId(userPoolId)
74-
.username(username).userAttributes(attributeTypes).build();
75+
.username(username).temporaryPassword(password).userAttributes(attributeTypes).build();
7576
return cognitoIdentityProviderClient.adminCreateUser(createUserRequest);
7677
}
7778

@@ -107,6 +108,14 @@ public RespondToAuthChallengeResponse setPermanentPassword(String session, Strin
107108
return cognitoIdentityProviderClient.respondToAuthChallenge(respondToAuthChallengeRequest);
108109
}
109110

111+
@Override
112+
public void logout(String userName) {
113+
var signOutRequest = AdminUserGlobalSignOutRequest.builder().userPoolId(this.userPoolId).username(userName)
114+
.build();
115+
116+
cognitoIdentityProviderClient.adminUserGlobalSignOut(signOutRequest);
117+
}
118+
110119
private Map<String, String> resolveAuthParameters(String username, String password) {
111120
Map<String, String> parametersMap = new HashMap<>();
112121
parametersMap.put(CognitoParameters.USERNAME_PARAM_NAME, username);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
* Copyright 2013-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.awspring.cloud.cognito;
17+
18+
import static org.mockito.Mockito.mock;
19+
import static org.mockito.Mockito.verify;
20+
21+
import java.util.HashMap;
22+
import java.util.List;
23+
import java.util.Map;
24+
import org.junit.jupiter.api.Test;
25+
import software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderClient;
26+
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminCreateUserRequest;
27+
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminInitiateAuthRequest;
28+
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminUserGlobalSignOutRequest;
29+
import software.amazon.awssdk.services.cognitoidentityprovider.model.AttributeType;
30+
import software.amazon.awssdk.services.cognitoidentityprovider.model.AuthFlowType;
31+
import software.amazon.awssdk.services.cognitoidentityprovider.model.ChallengeNameType;
32+
import software.amazon.awssdk.services.cognitoidentityprovider.model.ConfirmForgotPasswordRequest;
33+
import software.amazon.awssdk.services.cognitoidentityprovider.model.ForgotPasswordRequest;
34+
import software.amazon.awssdk.services.cognitoidentityprovider.model.RespondToAuthChallengeRequest;
35+
36+
/**
37+
* Tests for {@link CognitoTemplate}.
38+
*
39+
* @author Oleh Onufryk
40+
* @since 3.3.0
41+
*/
42+
class CognitoTemplateTest {
43+
44+
private static final String USERNAME = "[email protected]";
45+
private static final String PASSWORD = "password";
46+
private final CognitoIdentityProviderClient cognitoIdentityProviderClient = mock(
47+
CognitoIdentityProviderClient.class);
48+
49+
private final CognitoTemplate cognitoTemplate = new CognitoTemplate(cognitoIdentityProviderClient, "clientId",
50+
"userPoolId", "clientSecret");
51+
52+
@Test
53+
void createUser() {
54+
AdminCreateUserRequest request = AdminCreateUserRequest.builder().userPoolId("userPoolId").username(USERNAME)
55+
.temporaryPassword(PASSWORD).userAttributes(createAttributes()).build();
56+
cognitoTemplate.createUser(USERNAME, PASSWORD, createAttributes());
57+
58+
verify(cognitoIdentityProviderClient).adminCreateUser(request);
59+
}
60+
61+
@Test
62+
void login() {
63+
AdminInitiateAuthRequest initiateAuthRequest = AdminInitiateAuthRequest.builder().userPoolId("userPoolId")
64+
.clientId("clientId").authFlow(AuthFlowType.ADMIN_USER_PASSWORD_AUTH)
65+
.authParameters(resolveAuthParameters()).build();
66+
67+
cognitoTemplate.login(USERNAME, PASSWORD);
68+
69+
verify(cognitoIdentityProviderClient).adminInitiateAuth(initiateAuthRequest);
70+
}
71+
72+
@Test
73+
void resetPassword() {
74+
ForgotPasswordRequest forgotPasswordRequest = ForgotPasswordRequest.builder().clientId("clientId")
75+
.secretHash(CognitoUtils.calculateSecretHash("clientId", "clientSecret", USERNAME)).username(USERNAME)
76+
.build();
77+
78+
cognitoTemplate.resetPassword(USERNAME);
79+
80+
verify(cognitoIdentityProviderClient).forgotPassword(forgotPasswordRequest);
81+
}
82+
83+
@Test
84+
void confirmResetPassword() {
85+
ConfirmForgotPasswordRequest forgotPasswordRequest = ConfirmForgotPasswordRequest.builder().clientId("clientId")
86+
.username(USERNAME).password("newPassword").confirmationCode("confirmationCode")
87+
.secretHash(CognitoUtils.calculateSecretHash("clientId", "clientSecret", USERNAME)).build();
88+
89+
cognitoTemplate.confirmResetPassword(USERNAME, "confirmationCode", "newPassword");
90+
91+
verify(cognitoIdentityProviderClient).confirmForgotPassword(forgotPasswordRequest);
92+
}
93+
94+
@Test
95+
void setPermanentPassword() {
96+
RespondToAuthChallengeRequest permanentPasswordRequest = RespondToAuthChallengeRequest.builder()
97+
.clientId("clientId").challengeName(ChallengeNameType.NEW_PASSWORD_REQUIRED).session("session")
98+
.challengeResponses(Map.of(CognitoParameters.USERNAME_PARAM_NAME, USERNAME,
99+
CognitoParameters.NEW_PASSWORD_PARAM_NAME, PASSWORD, CognitoParameters.SECRET_HASH_PARAM_NAME,
100+
CognitoUtils.calculateSecretHash("clientId", "clientSecret", USERNAME)))
101+
.build();
102+
103+
cognitoTemplate.setPermanentPassword("session", USERNAME, PASSWORD);
104+
105+
verify(cognitoIdentityProviderClient).respondToAuthChallenge(permanentPasswordRequest);
106+
}
107+
108+
@Test
109+
void logout() {
110+
AdminUserGlobalSignOutRequest logoutRequest = AdminUserGlobalSignOutRequest.builder().userPoolId("userPoolId")
111+
.username(USERNAME).build();
112+
113+
cognitoTemplate.logout(USERNAME);
114+
115+
verify(cognitoIdentityProviderClient).adminUserGlobalSignOut(logoutRequest);
116+
}
117+
118+
private List<AttributeType> createAttributes() {
119+
return List.of(AttributeType.builder().name("email").value("[email protected]").build());
120+
}
121+
122+
private Map<String, String> resolveAuthParameters() {
123+
Map<String, String> parametersMap = new HashMap<>();
124+
parametersMap.put(CognitoParameters.USERNAME_PARAM_NAME, CognitoTemplateTest.USERNAME);
125+
parametersMap.put(CognitoParameters.PASSWORD_PARAM_NAME, CognitoTemplateTest.PASSWORD);
126+
parametersMap.put(CognitoParameters.SECRET_HASH_PARAM_NAME,
127+
CognitoUtils.calculateSecretHash("clientId", "clientSecret", CognitoTemplateTest.USERNAME));
128+
return parametersMap;
129+
}
130+
131+
}

spring-cloud-aws-samples/spring-cloud-aws-cognito-sample/pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
<groupId>org.springframework.boot</groupId>
1717
<artifactId>spring-boot-starter-web</artifactId>
1818
</dependency>
19+
<dependency>
20+
<groupId>org.springframework.boot</groupId>
21+
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
22+
</dependency>
1923
<dependency>
2024
<groupId>io.awspring.cloud</groupId>
2125
<artifactId>spring-cloud-aws-starter-cognito</artifactId>

0 commit comments

Comments
 (0)