AWS Cognito用户池无需密码

40
我想在我的应用程序中使用电话号码作为用户名,并希望通过仅需验证电话号码即可登录来简化注册流程——不需要记住混乱的密码。但是,AWS Cognito用户池要求我强制配置每个用户的密码,该怎么做呢?
我考虑为每个用户使用虚拟密码并配置强制用户验证。每次用户退出时,我都可以“取消验证”用户,这样下次他们就会自动被要求验证电话号码。此外,我会将我的应用程序连接到仅在用户经过验证后才“登录”。
请让我知道这是否是最佳方法:(我对AWS还很陌生,并且找不到任何相关的帖子。
谢谢!

2
最近亚马逊推出了一种解决方案:https://aws.amazon.com/blogs/mobile/implementing-passwordless-email-authentication-with-amazon-cognito/ - Ulad Kasach
3个回答

20

由于 AWS Cognito 目前不支持无密码身份验证,因此您需要使用外部存储的随机密码实现解决方法。您可以按照以下方式实现身份验证流程。

  • 用户注册后(还要求输入手机号并强制执行),使用 AWS KMS 进行加密,并在 Dynamodb 中存储手机号、用户名和密码。
  • 您可以使用移动电话号码进行 MFA 验证,以便在用户输入手机号并按下登录按钮(在前端)后,在后端自动进行用户名密码匹配(Passthrough)并触发发送代码到用户手机上的 MFA 验证,然后使用 AWS Cognito SDK 进行验证(无需实现自定义移动消息和挑战)。
  • 如果您计划手动实现流程(无 MFA),则可以使用 AWS SNS 进行 SMS 和验证。

请检查以下代码示例,了解 MFA 的洞察力,并参考此链接了解更多详细信息。

    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目的,而是作为解决方法来满足您的要求。

注意:此处所指的具有移动电话号码的MFA并不用于MFA目的,而是用作一种解决方法,以满足您的需求。


非常感谢,Ashan。这回答了我的问题 :) - spar
8
将每个用户的唯一随机密码存储在外部数据库中,相较于为所有用户仅设置一个秘密虚拟密码,有哪些安全好处? - jonixj
我遇到了这样的情况:getsession发送了一个OTP,然后调用了一个委托函数,但我不知道要调用哪个函数来设置接收到的OTP并再次获取令牌。 - Shanu Singh
1
这是从以下文章中摘录的: https://aws.amazon.com/blogs/mobile/accessing-your-user-pools-using-the-amazon-cognito-identity-sdk-for-javascript - klaxon

10
这是一个略微不同的方法,因为它只使用一个秘密,但我认为它可能有助于其他遇到这个问题的人。我通过为Cognito触发器创建自定义lambda(Define Auth Challenge、Create Auth Challenge和Verify Auth Challenge)来实现这一点。
我的需求是,我希望我的后端使用一个“秘密”来获取任何Cognito用户的访问和刷新令牌。
“Define Auth Challenge 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;
};

我随后使用amazon-cognito-identity-js编写了一些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);
  }
});

这对我正在处理的需求非常有用。感谢详细的见解。 - Logus Graphics

5

这种方法可能可行,但在DynamoDB中存储密码可能存在安全问题。我们可以尝试以下方法:

选项#1:用户使用用户名和密码注册。

  1. 设置Cognito触发器 - 我们可以使用Lambda函数。
  2. A. 创建身份验证挑战 B. 定义身份验证挑战 C. 验证身份验证挑战响应
  3. 客户端应用程序应实现CUSTOM_CHALLENGE身份验证流程。
  4. 要求用户输入已注册的电话号码,并将其传递到用户名字段中。触发器B将理解请求并将流程传递到触发器A,触发器A将生成随机代码5。使用AWS SNS服务向用户手机发送短信
  5. 触发器C将验证OTP并允许登录 需要考虑的要点: a. 将电话号码设置为别名(选择“还允许使用已验证的电话号码登录”) b. 将电话号码字段设置为可验证(这允许用户接收OTP)

选项#2:用户无需用户名和密码进行注册。 Cognito设置

  1. 将电话号码设置为别名(选择“还允许使用已验证的电话号码登录”)
  2. 将电话号码字段设置为可验证(这允许用户接收OTP)
  3. 在注册过程中不要要求用户提供用户名和密码,只需要求提供电话号码
  4. 为用户名和密码生成UUID以使其唯一,并将其与电话号码一起传递给Cognito
  5. Cognito向用户发送OTP代码以进行帐户确认。
  6. 对于设置了OTP登录的电话号码,请按上述选项设置触发器。

有关触发器代码,请参见aws cognito pool with multiple sign in options


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接