本文只是对使用aws使用cognito自定义身份验证实践SNS的简单记录,参考文章如上。
- 用户在登录页面输入电话号码。
- 身份验证挑战定义 Lambda 被执行并确定身份验证流程。
- 身份验证质询创建 Lambda 被执行并发出一次性密码(OTP)。
- AmazonSNS被调用,SMS 被发送。
- 在登录页面输入用户收到的OTP。
- 身份验证质询验证 Lambda 被执行以确定输入的 OTP 是否正确
- 认证质询定义Lambda被执行,如果判断结果正确,则认证成功并颁发token
认证成功后,执行认证后Lambda,更新用户属性(验证电话号码)。
部署资源
从 AWS Serverless Application Repository 部署 Cognito 用户池和 Lambda 函数。但是这里创建的 Cognito 用户池将不会被使用,稍后会创建,因此您可以在部署后根据需要将其删除。
访问以下内容并单击 [部署]。
应用程序搜索 - AWS 无服务器应用程序存储库- 输入发件人邮箱和用户池名称(由于没有使用SES和用户池,可以任意),点击【部署】。
- 确认从部署历史中显示[创建完成]。
创建 Cognito 用户池
由于之前创建的用户池用于电子邮件身份验证,并且在登录选项中指定了电子邮件地址,因此使用为 SMS 身份验证指定的电话号码创建一个新用户池。
- 在AWS管理控制台中,转到 Cognito 下的用户池,然后单击创建用户池。
- 按照屏幕上的说明设置每个项目。但是,请务必如下设置以下项目。
Cognito 用户池登录选项:仅检查电话号码
密码策略:至少 8 个字符,取消选中所有密码要求
多因素身份验证:无 MFA
忘记密码
注册配置:
必需属性:电话号码 + 电子邮箱
配置消息发送
身份验证流程:ALLOW_CUSTOM_AUTH
- 完成设置后,单击[查看和创建]屏幕上的[创建用户池]。
- 选择创建的用户池,点击【用户池属性】中的【添加 Lambda 触发器】
设置 Lambda 触发器如下。
注册前 Lambda 触发器:PreSignUpVerify
定义身份验证质询 Lambda 触发器:VerifyAuthChallengeResponseCreate
创建身份验证质询Lambda 触发器:CreateAuthChallenge
身份验证质询Lambda 触发器:DefineAuthChallengePost
身份验证 Lambda 触发器:PostAuthentication
- 从下方检查您的用户池 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;
};