Преобразование AuthenticationHelper из SDK v1 в v2 не так уж сложен. Вызовы v1 просто необходимо обновить до версий v2. Все поколения SRP остаются прежними. Ниже показано, как я преобразовал основные методы этого класса для использования v2 sdk.
Выполнить аутентификацию SRP
public String PerformSRPAuthentication(String username, String password) {
String authresult = null;
InitiateAuthRequest authReq = initiateUserSrpAuthRequest(username);
try {
AnonymousCredentialsProvider creds = AnonymousCredentialsProvider.create();
CognitoIdentityProviderClient cognitoclient = CognitoIdentityProviderClient.builder()
.region(Region.of(this.region))
.credentialsProvider(creds)
.build();
InitiateAuthResponse authRes = cognitoclient.initiateAuth(authReq);
if(authRes.challengeName().equals(ChallengeNameType.PASSWORD_VERIFIER)) {
RespondToAuthChallengeRequest challengeRequest = userSrpAuthRequest(authRes, password);
RespondToAuthChallengeResponse result = cognitoclient.respondToAuthChallenge(challengeRequest);
authresult = result.authenticationResult().idToken();
}
} catch(Exception e) {
System.out.println("Exception: " + e);
}
return authresult;
}
инициироватьUserSrpAuthRequest
private InitiateAuthRequest initiateUserSrpAuthRequest(String username) {
HashMap<String, String> authParams = new HashMap<String, String>();
authParams.put("USERNAME", username);
authParams.put("SRP_A", this.getA().toString(16));
InitiateAuthRequest authReq = InitiateAuthRequest.builder()
.authFlow(AuthFlowType.USER_SRP_AUTH)
.clientId(this.clientId).authParameters(authParams).build();
return authReq;
}
userSrpAuthRequest
private RespondToAuthChallengeRequest userSrpAuthRequest(InitiateAuthResponse challenge,
String password
) {
String userIdForSRP = challenge.challengeParameters().get("USER_ID_FOR_SRP");
String usernameInternal = challenge.challengeParameters().get("USERNAME");
BigInteger B = new BigInteger(challenge.challengeParameters().get("SRP_B"), 16);
if (B.mod(AWSAuthenticationHelper.N).equals(BigInteger.ZERO)) {
throw new SecurityException("SRP error, B cannot be zero");
}
BigInteger salt = new BigInteger(challenge.challengeParameters().get("SALT"), 16);
byte[] key = getPasswordAuthenticationKey(userIdForSRP, password, B, salt);
Date timestamp = new Date();
byte[] hmac = null;
try {
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(key, "HmacSHA256");
mac.init(keySpec);
mac.update(this.userPoolID.split("_", 2)[1].getBytes(Charset.forName("UTF-8")));
mac.update(userIdForSRP.getBytes(Charset.forName("UTF-8")));
byte[] secretBlock = Base64.decode(challenge.challengeParameters().get("SECRET_BLOCK"));
mac.update(secretBlock);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy", Locale.US);
simpleDateFormat.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
String dateString = simpleDateFormat.format(timestamp);
byte[] dateBytes = dateString.getBytes(Charset.forName("UTF-8"));
hmac = mac.doFinal(dateBytes);
} catch (Exception e) {
System.out.println(e);
}
SimpleDateFormat formatTimestamp = new SimpleDateFormat("EEE MMM d HH:mm:ss z yyyy", Locale.US);
formatTimestamp.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
Map<String, String> srpAuthResponses = new HashMap<>();
srpAuthResponses.put("PASSWORD_CLAIM_SECRET_BLOCK", challenge.challengeParameters().get("SECRET_BLOCK"));
srpAuthResponses.put("PASSWORD_CLAIM_SIGNATURE", new String(Base64.encode(hmac), Charset.forName("UTF-8")));
srpAuthResponses.put("TIMESTAMP", formatTimestamp.format(timestamp));
srpAuthResponses.put("USERNAME", usernameInternal);
RespondToAuthChallengeRequest authChallengeRequest = RespondToAuthChallengeRequest.builder()
.challengeName(challenge.challengeName())
.clientId(clientId)
.session(challenge.session())
.challengeResponses(srpAuthResponses).build();
return authChallengeRequest;
}
Вам также потребуется заменить два служебных класса v1, com.amazonaws.util.Base64
и com.amazonaws.util.StringUtils
. Все экземпляры StringUtils.UTF8
можно заменить на java.nio.charset.Charset.forName("UTF-8")
. Замена Base64
немного сложнее. В итоге я просто скопировал 4 связанных класса в свой проект локально. Те, кто
com.amazonaws.util.Base64
com.amazonaws.util.CodecUtils
com.amazonaws.util.Codec
com.amazonaws.util.Base64Codec
Это не красиво, но это работает для меня. Я не уверен, почему AWS не может реализовать оболочку для аутентификации SRP, как и все другие SDK.
person
nos9
schedule
27.05.2021