【问题标题】:AWS Cognito User Pool without a password没有密码的 AWS Cognito 用户池
【发布时间】:2018-01-21 20:04:17
【问题描述】:

我想使用电话号码作为我的应用程序的用户名,并且我希望能够通过每次他们想要登录时验证电话号码来简化注册 - 没有混乱的密码记住业务。

如何使用 AWS Cognito 用户池执行此操作,因为它要求我强制为每个用户配置密码。

我想为每个用户使用一个虚拟密码并配置强制用户验证。每次用户退出时,我都可以“取消验证”用户,以便下次自动要求他们验证电话号码。此外,如果用户经过验证,我会将我的应用程序连接到仅“登录”。

如果这是最好的方法,请告诉我:(我是 AWS 新手,我找不到任何适合这种情况的帖子。

谢谢!!

【问题讨论】:

标签: amazon-web-services amazon-cognito


【解决方案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:- 用户使用用户名和密码注册。

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

选项#1:- 用户无需用户名和密码即可注册。 认知设置

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

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

【讨论】:

    猜你喜欢
    • 2020-06-14
    • 2019-03-29
    • 2018-01-31
    • 2018-11-07
    • 1970-01-01
    • 2017-06-17
    • 2018-02-22
    • 2019-05-18
    • 2020-09-14
    相关资源
    最近更新 更多