没有密码的 AWS Cognito 用户池
Posted
技术标签:
【中文标题】没有密码的 AWS Cognito 用户池【英文标题】:AWS Cognito User Pool without a password 【发布时间】:2018-01-21 20:04:17 【问题描述】:我想使用电话号码作为我的应用程序的用户名,并且我希望能够通过每次他们想要登录时验证电话号码来简化注册 - 没有混乱的密码记住业务。
如何使用 AWS Cognito 用户池执行此操作,因为它要求我强制为每个用户配置密码。
我想为每个用户使用一个虚拟密码并配置强制用户验证。每次用户退出时,我都可以“取消验证”用户,以便下次自动要求他们验证电话号码。此外,如果用户经过验证,我会将我的应用程序连接到仅“登录”。
如果这是最好的方法,请告诉我:(我是 AWS 新手,我找不到任何适合这种情况的帖子。
谢谢!!
【问题讨论】:
最近亚马逊出一个解决方案:aws.amazon.com/blogs/mobile/… 【参考方案1】:由于 AWS Cognito 当前不支持无密码身份验证,因此您需要使用存储在外部的随机密码来实施解决方法。您可以按如下方式实现身份验证流程。
用户注册后(还要求提供手机号码并强制填写),将手机号码、用户名和密码也存储在使用AWS KMS 加密的 Dynamodb 中(以提高安全性)。 您可以使用MFA与手机号码进行身份验证挑战,以便用户输入手机号码并按登录后(在前端),在后端您可以自动进行用户名密码匹配(Passthrough)并触发MFA发送代码用于用户的移动设备并使用 AWS Cognito 开发工具包进行验证(不实施自定义移动消息和质询)。 如果您计划手动实施流程(无 MFA)以发送 SMS 和验证,您可以使用 AWS SNS。查看以下代码示例以了解 MFA 的见解,并参考 this link 了解更多详细信息。
var userData =
Username : 'username',
Pool : userPool
;
cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
var authenticationData =
Username : 'username',
Password : 'password',
;
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
cognitoUser.authenticateUser(authenticationDetails,
onSuccess: function (result)
alert('authentication successful!')
,
onFailure: function(err)
alert(err);
,
mfaRequired: function(codeDeliveryDetails)
var verificationCode = prompt('Please input verification code' ,'');
cognitoUser.sendMFACode(verificationCode, this);
);
注意:此处带有手机号码的 MFA 并非用于 MFA 的目的,而是作为一种解决方法以满足您的要求。
【讨论】:
非常感谢阿山。这回答了我的问题:) 将每个用户的唯一随机密码存储在外部数据库中,而不是只为所有用户使用一个秘密虚拟密码,有什么安全优势? 我遇到了这样一种情况:getsession 发送 OTP,然后委托调用我不知道调用哪个函数来设置接收到的 OTP 并再次获取令牌。 这取自以下文章:aws.amazon.com/blogs/mobile/…【参考方案2】:这与 OP 要求的内容略有不同,因为它使用单个密钥,但我认为它可能会帮助其他解决这个问题的人。
我能够通过为 Cognito 触发器创建自定义 lambda 来做到这一点:定义身份验证挑战、创建身份验证挑战和验证身份验证挑战。
我的要求是我希望我的后端使用 secret
然后为任何 Cognito 用户获取访问和刷新令牌。
定义身份验证挑战 Lambda
exports.handler = async event =>
if (
event.request.session &&
event.request.session.length >= 3 &&
event.request.session.slice(-1)[0].challengeResult === false
)
// The user provided a wrong answer 3 times; fail auth
event.response.issueTokens = false;
event.response.failAuthentication = true;
else if (
event.request.session &&
event.request.session.length &&
event.request.session.slice(-1)[0].challengeResult === true
)
// The user provided the right answer; succeed auth
event.response.issueTokens = true;
event.response.failAuthentication = false;
else
// The user did not provide a correct answer yet; present challenge
event.response.issueTokens = false;
event.response.failAuthentication = false;
event.response.challengeName = 'CUSTOM_CHALLENGE';
return event;
;
创建身份验证挑战 Lambda
exports.handler = async event =>
if (event.request.challengeName == 'CUSTOM_CHALLENGE')
// The value set for publicChallengeParameters is arbitrary for our
// purposes, but something must be set
event.response.publicChallengeParameters = foo: 'bar' ;
return event;
;
验证身份验证挑战 Lambda
exports.handler = async event =>
if (event.request.challengeName == 'CUSTOM_CHALLENGE')
// The value set for publicChallengeParameters is arbitrary for our
// purposes, but something must be set
event.response.publicChallengeParameters = foo: 'bar' ;
return event;
;
然后我可以使用一些 JS,使用 amazon-cognito-identity-js,来提供秘密并获取令牌:
var authenticationData =
Username : 'username'
;
var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(authenticationData);
var poolData =
UserPoolId : '...', // Your user pool id here
ClientId : '...' // Your client id here
;
var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
var userData =
Username : 'username',
Pool : userPool
;
var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.setAuthenticationFlowType('CUSTOM_AUTH');
cognitoUser.initiateAuth(authenticationDetails,
onSuccess: function(result)
// User authentication was successful
,
onFailure: function(err)
// User authentication was not successful
,
customChallenge: function(challengeParameters)
// User authentication depends on challenge response
var challengeResponses = 'secret'
cognitoUser.sendCustomChallengeAnswer(challengeResponses, this);
);
【讨论】:
这对我正在处理的需求最有用。欣赏详细的见解。【参考方案3】:这可能有效,但考虑到安全性,将密码存储在 dynamoDB 中可能会出现问题。相反,我们可以这样尝试:
选项#1:- 用户使用用户名和密码注册。
-
设置认知触发器 - 我们可以使用 lambda 函数。
A.创建身份验证挑战
B. 定义身份验证挑战
C. 验证身份验证挑战响应
客户端应用应实现 CUSTOM_CHALLENGE 身份验证流程。
要求用户输入注册的电话号码,在用户名字段中传递。触发器 B 将了解请求并将流程传递给触发器 A,触发器 A 将生成随机码 5. 使用 AWS SNS 服务向用户手机号码发送短信
触发器 C 将验证 OTP 并允许登录
需要考虑的要点:
一种。将电话号码设置为别名(选择还允许使用经过验证的电话号码登录)
湾。将电话号码字段设为可验证(这允许用户接收 OTP)
选项#1:- 用户无需用户名和密码即可注册。 认知设置
-
将电话号码设置为别名(选择还允许使用经过验证的电话号码登录)
将电话号码字段设为可验证(这允许用户接收 OTP)
在注册过程中不要要求用户提供用户名和密码,只需询问电话号码
为用户名和密码生成唯一的 UUID,并将它们与电话号码一起传递给 cognito
Cognito 向用户发送 OTP 代码以确认帐户。
对于具有 OTP 登录设置触发器的电话号码,如上述选项中所述。
有关触发器代码,请参阅 aws cognito pool with multiple sign in options
【讨论】:
以上是关于没有密码的 AWS Cognito 用户池的主要内容,如果未能解决你的问题,请参考以下文章
AWS CloudFormation 脚本失败 - 不允许 Cognito 使用您的电子邮件身份