微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 AWS Java SDK v2.x 的 Cognito SRP

如何解决使用 AWS Java SDK v2.x 的 Cognito SRP

我需要使用 AWS Cognito 获取令牌,然后调用秘密 API。我有这个有效的 python 脚本。如何将其转换为 Java SDK v2?

我发现了一个使用 Java SDK V1 的 sample,但它不适用于 v2。

from warrant.aws_srp import AWSSRP
username = "user"
password = "pass"
client_id = "xxxxxxxxxxxxxxxxx"
user_pool_id = "us-east-1_xxx123445"
region = "us-east-1"
aws = AWSSRP(username=username,password=password,pool_id=user_pool_id,client_id=client_id)
tokens = aws.authenticate_user()
print(tokens)

解决方法

AuthenticationHelper 示例类从 v1 sdk 转换为 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;
}

initiateUserSrpAuthRequest

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.Base64com.amazonaws.util.StringUtilsStringUtils.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 不能像所有其他 SDK 一样为 SRP 身份验证实现包装器。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?