[AWS] 使用 Cognito 自定义身份验证实现 SNS 身份验证

 参考文章:【AWS】Cognitoのカスタム認証チャレンジを用いたSMS認証を実装する方法 - BFT名古屋 TECH BLOG

本文只是对使用aws使用cognito自定义身份验证实践SNS的简单记录,参考文章如上。

  1. 用户在登录页面输入电话号码。
  2. 身份验证挑战定义 Lambda 被执行并确定身份验证流程。
  3. 身份验证质询创建 Lambda 被执行并发出一次性密码(OTP)。
  4. AmazonSNS被调用,SMS 被发送。
  5. 在登录页面输入用户收到的OTP。
  6. 身份验证质询验证 Lambda 被执行以确定输入的 OTP 是否正确
  7. 认证质询定义Lambda被执行,如果判断结果正确,则认证成功并颁发token
  8. 认证成功后,执行认证后Lambda,更新用户属性(验证电话号码)。

部署资源

从 AWS Serverless Application Repository 部署 Cognito 用户池和 Lambda 函数。但是这里创建的 Cognito 用户池将不会被使用,稍后会创建,因此您可以在部署后根据需要将其删除。

  1. 访问以下内容并单击 [部署]。
    应用程序搜索 - AWS 无服务器应用程序存储库

  2. 输入发件人邮箱和用户池名称(由于没有使用SES和用户池,可以任意),点击【部署】。

  3. 确认从部署历史中显示[创建完成]。

创建 Cognito 用户池

由于之前创建的用户池用于电子邮件身份验证,并且在登录选项中指定了电子邮件地址,因此使用为 SMS 身份验证指定的电话号码创建一个新用户池。

  1. 在AWS管理控制台中,转到 Cognito 下的用户池,然后单击创建用户池

  2. 按照屏幕上的说明设置每个项目。但是,请务必如下设置以下项目。
    Cognito 用户池登录选项:仅检查电话号码

    密码策略:至少 8 个字符,取消选中所有密码要求
    多因素身份验证:无 MFA
    忘记密码

注册配置:

必需属性:电话号码 + 电子邮箱

配置消息发送

身份验证流程:ALLOW_CUSTOM_AUTH

  1. 完成设置后,单击[查看和创建]屏幕上的[创建用户池]。

  2. 选择创建的用户池,点击【用户池属性】中的【添加 Lambda 触发器】

设置 Lambda 触发器如下。
注册前 Lambda 触发器:PreSignUpVerify


定义身份验证质询 Lambda 触发器:VerifyAuthChallengeResponseCreate

创建身份验证质询Lambda 触发器:CreateAuthChallenge

身份验证质询Lambda 触发器:DefineAuthChallengePost

身份验证 Lambda 触发器:PostAuthentication

  1. 从下方检查您的用户池 ID 和用户池客户端 ID。保存这两个以备后用。
    用户池 ID:用户池概览

    用户池客户端 ID:[用户池]-[应用程序集成]-[客户端 ID]

修改Lambda函数

创建身份验证(创建身份验证 Lambda)

要授予对SNS的访问权限,请从 [Settings]-[Access Permissions] 添加以下 IAM 策略。允许sns发布

与原始代码的主要变化是将发送电子邮件的部分替换为发送 SNS。

"use strict";
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_secure_random_digit_1 = require("crypto-secure-random-digit");
const aws_sdk_1 = require("aws-sdk");
const sns = new aws_sdk_1.SNS();
exports.handler = async (event) => {
    let secretLoginCode;
    if (!event.request.session || !event.request.session.length) {
        // This is a new auth session
        // Generate a new secret login code and mail it to the user
        console.log(event.request.session);
        secretLoginCode = crypto_secure_random_digit_1.randomDigits(6).join('');
        await sendSMSviaSNS(event.request.userAttributes.phone_number, secretLoginCode);
    }
    else {
        // There's an existing session. Don't generate new digits but
        // re-use the code from the current session. This allows the user to
        // make a mistake when keying in the code and to then retry, rather
        // then needing to e-mail the user an all new code again.
        console.log(event.request.session);
        const previousChallenge = event.request.session.slice(-1)[0];
        secretLoginCode = previousChallenge.challengeMetadata.match(/CODE-(\d*)/)[1];
    }
    // This is sent back to the client app
    event.response.publicChallengeParameters = { phone: event.request.userAttributes.phone_number };
    // Add the secret login code to the private challenge parameters
    // so it can be verified by the "Verify Auth Challenge Response" trigger
    event.response.privateChallengeParameters = { secretLoginCode };
    // Add the secret login code to the session so it is available
    // in a next invocation of the "Create Auth Challenge" trigger
    event.response.challengeMetadata = `CODE-${secretLoginCode}`;
    return event;
};
async function sendSMSviaSNS(phoneNumber, secretLoginCode) {
    const params = { "Message": "Your secret code: " + secretLoginCode, "PhoneNumber": phoneNumber };
    await sns.publish(params).promise();
}

身份验证后Lambda

post-authentication.js,原代码更新了邮箱地址的属性,但是这次我们用的是电话号码,所以我们改成更新电话号码。

"use strict";
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
Object.defineProperty(exports, "__esModule", { value: true });
const aws_sdk_1 = require("aws-sdk");
const cup = new aws_sdk_1.CognitoIdentityServiceProvider();
exports.handler = async (event) => {
    if (event.request.userAttributes.phone_number_verified !== 'true') {
        const params = {
            UserPoolId: event.userPoolId,
            UserAttributes: [{
                    Name: 'phone_number_verified',
                    Value: 'true',
                }],
            Username: event.userName,
        };
        await cup.adminUpdateUserAttributes(params).promise();
    }
    return event;
};

猜你喜欢

转载自blog.csdn.net/jexxx/article/details/128680764