forked from awspring/spring-cloud-aws
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
awspringgh-1246: AWS Cognito Integration 1.0
- Loading branch information
Showing
8 changed files
with
324 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
spring-cloud-aws-cognito/src/main/java/io/awspring/cloud/cognito/CognitoAuthOperations.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* Copyright 2013-2022 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.awspring.cloud.cognito; | ||
|
||
import java.util.List; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminCreateUserResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminInitiateAuthResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AttributeType; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.ConfirmForgotPasswordResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.ForgotPasswordResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.RespondToAuthChallengeResponse; | ||
|
||
/** | ||
* An Interface for the most common Cognito auth operations | ||
* | ||
* @author Oleh Onufryk | ||
* @since 3.3.0 | ||
*/ | ||
|
||
public interface CognitoAuthOperations { | ||
|
||
/** | ||
* Logs in a user using username and password | ||
* @param username - the username | ||
* @param password - the password | ||
* @return {@link AdminInitiateAuthResponse} a result of login operation from the AWS Cognito | ||
*/ | ||
AdminInitiateAuthResponse login(String username, String password); | ||
|
||
/** | ||
* Creates a new user with provided attributes | ||
* @param username - the username | ||
* @param attributeTypes - the list of user attributes defined by user pool | ||
* @return {@link AdminCreateUserResponse} a result of user creation operation from the AWS Cognito | ||
*/ | ||
AdminCreateUserResponse createUser(String username, List<AttributeType> attributeTypes); | ||
|
||
/** | ||
* Resets password for a user | ||
* @param username - the username | ||
* @return {@link ForgotPasswordResponse} a result of password reset operation from the AWS Cognito | ||
*/ | ||
ForgotPasswordResponse resetPassword(String username); | ||
|
||
/** | ||
* Confirms password reset | ||
* @param username - the username | ||
* @param confirmationCode - the confirmation code for password reset operation | ||
* @param newPassword - the new password | ||
* @return {@link ConfirmForgotPasswordResponse} a result of password reset confirmation operation from the AWS | ||
* Cognito | ||
*/ | ||
ConfirmForgotPasswordResponse confirmResetPassword(String username, String confirmationCode, String newPassword); | ||
|
||
/** | ||
* Sets a permanent password for a new user | ||
* @param session - the session id returned by the login operation | ||
* @param username - the username of the user | ||
* @param password - the permanent password for user's account | ||
* @return {@link RespondToAuthChallengeResponse} a result of setting permanent password operation from the AWS | ||
* Cognito | ||
*/ | ||
RespondToAuthChallengeResponse setPermanentPassword(String session, String username, String password); | ||
|
||
} |
49 changes: 49 additions & 0 deletions
49
spring-cloud-aws-cognito/src/main/java/io/awspring/cloud/cognito/CognitoParameters.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Copyright 2013-2022 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.awspring.cloud.cognito; | ||
|
||
/** | ||
* Parameters used in AWS Cognito operations. | ||
* | ||
* @author Oleh Onufryk | ||
* @since 3.3.0 | ||
*/ | ||
|
||
public final class CognitoParameters { | ||
|
||
private CognitoParameters() { | ||
} | ||
|
||
/** | ||
* Parameter represents username for a user. | ||
*/ | ||
public static final String USERNAME_PARAM_NAME = "USERNAME"; | ||
|
||
/** | ||
* Parameter represents password for a user. | ||
*/ | ||
public static final String PASSWORD_PARAM_NAME = "PASSWORD"; | ||
|
||
/** | ||
* Parameter represents a compute secret hash for a user. | ||
*/ | ||
public static final String SECRET_HASH_PARAM_NAME = "SECRET_HASH"; | ||
|
||
/** | ||
* Parameter represents a new password for a user. | ||
*/ | ||
public static final String NEW_PASSWORD_PARAM_NAME = "NEW_PASSWORD"; | ||
} |
110 changes: 110 additions & 0 deletions
110
spring-cloud-aws-cognito/src/main/java/io/awspring/cloud/cognito/CognitoTemplate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
/* | ||
* Copyright 2013-2022 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.awspring.cloud.cognito; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
import org.springframework.util.Assert; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderClient; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminCreateUserRequest; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminCreateUserResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminInitiateAuthRequest; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AdminInitiateAuthResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AttributeType; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.AuthFlowType; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.ChallengeNameType; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.ConfirmForgotPasswordRequest; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.ConfirmForgotPasswordResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.ForgotPasswordRequest; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.ForgotPasswordResponse; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.RespondToAuthChallengeRequest; | ||
import software.amazon.awssdk.services.cognitoidentityprovider.model.RespondToAuthChallengeResponse; | ||
|
||
/** | ||
* Higher level abstraction over {@link CognitoIdentityProviderClient} providing methods for the most common auth | ||
* operations | ||
* | ||
* @author Oleh Onufryk | ||
* @since 3.3.0 | ||
*/ | ||
|
||
public class CognitoTemplate implements CognitoAuthOperations { | ||
|
||
private final CognitoIdentityProviderClient cognitoIdentityProviderClient; | ||
private final String clientId; | ||
private final String userPoolId; | ||
private final String clientSecret; | ||
|
||
public CognitoTemplate(CognitoIdentityProviderClient cognitoIdentityProviderClient, String clientId, | ||
String userPoolId, String clientSecret) { | ||
Assert.notNull(cognitoIdentityProviderClient, "cognitoIdentityProviderClient is required"); | ||
Assert.notNull(clientId, "clientId is required"); | ||
Assert.notNull(userPoolId, "userPoolId is required"); | ||
this.cognitoIdentityProviderClient = cognitoIdentityProviderClient; | ||
this.clientId = clientId; | ||
this.userPoolId = userPoolId; | ||
this.clientSecret = clientSecret; | ||
} | ||
|
||
@Override | ||
public AdminInitiateAuthResponse login(String username, String password) { | ||
AdminInitiateAuthRequest adminInitiateAuthRequest = AdminInitiateAuthRequest.builder().userPoolId(userPoolId) | ||
.clientId(clientId).authFlow(AuthFlowType.ADMIN_USER_PASSWORD_AUTH) | ||
.authParameters(resolveAuthParameters(username, password)).build(); | ||
return cognitoIdentityProviderClient.adminInitiateAuth(adminInitiateAuthRequest); | ||
} | ||
|
||
@Override | ||
public AdminCreateUserResponse createUser(String username, List<AttributeType> attributeTypes) { | ||
AdminCreateUserRequest createUserRequest = AdminCreateUserRequest.builder().userPoolId(userPoolId) | ||
.username(username).userAttributes(attributeTypes).build(); | ||
return cognitoIdentityProviderClient.adminCreateUser(createUserRequest); | ||
} | ||
|
||
@Override | ||
public ForgotPasswordResponse resetPassword(String username) { | ||
ForgotPasswordRequest forgotPasswordRequest = ForgotPasswordRequest.builder().clientId(clientId) | ||
.username(username).build(); | ||
|
||
return cognitoIdentityProviderClient.forgotPassword(forgotPasswordRequest); | ||
} | ||
|
||
@Override | ||
public ConfirmForgotPasswordResponse confirmResetPassword(String username, String confirmationCode, | ||
String newPassword) { | ||
ConfirmForgotPasswordRequest confirmForgotPasswordRequest = ConfirmForgotPasswordRequest.builder() | ||
.clientId(clientId).username(username).password(newPassword).confirmationCode(confirmationCode) | ||
.secretHash(CognitoUtils.calculateSecretHash(clientId, clientSecret, username)).build(); | ||
return cognitoIdentityProviderClient.confirmForgotPassword(confirmForgotPasswordRequest); | ||
} | ||
|
||
@Override | ||
public RespondToAuthChallengeResponse setPermanentPassword(String session, String username, String password) { | ||
RespondToAuthChallengeRequest respondToAuthChallengeRequest = RespondToAuthChallengeRequest.builder() | ||
.clientId(clientId).challengeName(ChallengeNameType.NEW_PASSWORD_REQUIRED) | ||
.challengeResponses(Map.of(CognitoParameters.USERNAME_PARAM_NAME, username, | ||
CognitoParameters.NEW_PASSWORD_PARAM_NAME, password, CognitoParameters.SECRET_HASH_PARAM_NAME, | ||
CognitoUtils.calculateSecretHash(clientId, clientSecret, username))) | ||
.build(); | ||
return cognitoIdentityProviderClient.respondToAuthChallenge(respondToAuthChallengeRequest); | ||
} | ||
|
||
private Map<String, String> resolveAuthParameters(String username, String password) { | ||
return Map.of(CognitoParameters.USERNAME_PARAM_NAME, username, CognitoParameters.PASSWORD_PARAM_NAME, password, | ||
CognitoParameters.SECRET_HASH_PARAM_NAME, | ||
CognitoUtils.calculateSecretHash(clientId, clientSecret, username)); | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
spring-cloud-aws-cognito/src/main/java/io/awspring/cloud/cognito/CognitoUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright 2013-2022 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package io.awspring.cloud.cognito; | ||
|
||
import java.nio.charset.StandardCharsets; | ||
import java.util.Base64; | ||
import javax.crypto.Mac; | ||
import javax.crypto.spec.SecretKeySpec; | ||
|
||
/** | ||
* Utility class for Cognito operations. | ||
* | ||
* @author Oleh Onufryk | ||
* @since 3.3.0 | ||
*/ | ||
public class CognitoUtils { | ||
|
||
private CognitoUtils() { | ||
} | ||
|
||
// https://docs.aws.amazon.com/cognito/latest/developerguide/signing-up-users-in-your-app.html#cognito-user-pools-computing-secret-hash | ||
public static 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 secret hash for " + userName); | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
spring-cloud-aws-cognito/src/main/java/io/awspring/cloud/cognito/package-info.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright 2013-2022 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
/** | ||
* AWS Cognito integration. | ||
*/ | ||
@org.springframework.lang.NonNullApi | ||
@org.springframework.lang.NonNullFields | ||
package io.awspring.cloud.cognito; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters