使用确认 URL 确认 amazon cognito 后如何重定向?

Posted

技术标签:

【中文标题】使用确认 URL 确认 amazon cognito 后如何重定向?【英文标题】:How to redirect after confirm amazon cognito using confirmation URL? 【发布时间】:2018-04-19 22:50:05 【问题描述】:

我想在amazon cognito中用户确认后重定向到特定的url。

当用户注册时,他将收到带有验证链接的确认邮件,如下所示 https://<>.auth.us-west-2.amazoncognito.com/confirmUser?client_id=<<>>&user_name=<<>>&confirmation_code=<<>>

如果用户点击上面的链接,它将重定向到确认页面。

用户确认完成后,页面应重定向到我的应用程序。

请给我一些想法来解决这个问题。

【问题讨论】:

【参考方案1】:

目前,无法使用电子邮件中的验证链接进行此重定向。不久前我尝试将 redirect_uri 添加到验证 URL,但它们不起作用。

解决方法

在 Api 网关中创建一个 API,它采用这 3 个参数和一个附加的 redirect_uri 参数。在后端 lambda 中,使用参数向实际链接发出 GET 请求并确认用户。成功后,使用 redirect_uri 作为参数从您的 API 返回 302 重定向。 在您的用户池中,使用自定义消息触发器来构建指向您的 API 网关 api 的链接,而不是默认的 cognito url 因此,验证链接类似于:https://myapi.abc.com/confirm?client_id=somevalue&user_name=some_user&confirmation_code=some_code&redirect_uri=https://myapp.com

这些值被传递给后端 lambda,后者向 https://your_domain.auth.us-west-2.amazoncognito.com/confirmUser?client_id=somevalue&user_name=some_user&confirmation_code=some_code 发出 GET 请求

成功后,从您的 API 网关返回 302 https://myapp.com

我知道对于如此简单的要求,这是一个复杂的解决方法。最好的方法是提出功能请求并希望他们支持 Cognito URL 中的 redirect_uri。

编辑

为了节省 lambda 成本,您还可以在 API 中使用 HTTP 端点并向您所在地区的 cognito service endpoint 发出请求。示例:

POST  HTTP/1.1
Host: cognito-idp.us-east-1.amazonaws.com
x-amz-target: AWSCognitoIdentityProviderService.ConfirmSignUp
Content-Type: application/x-amz-json-1.1


  "ClientId":"xxxxxxxxxxxxx",
  "ConfirmationCode":"123456",
  "Username":"username"

【讨论】:

URL 中用于确认代码、客户端 ID、用户名等的占位符是什么:myapi.abc.com/… - 我无法在 cognito 文档中找到它 您需要使用自定义消息 lambda 触发器设置此消息。确认代码将是“event.request.codeParameter”,用户名在“event.request.userAttributes”中。只需记录“事件”对象并查看所有可用值 docs.aws.amazon.com/cognito/latest/developerguide/… 还是这样吗?那为什么 cognito 的 App Client Settings 中会有回调 url? 回调用于身份验证,即登录而不是确认【参考方案2】:

在@agent420 的上述答案的帮助下,我得到了这个工作,并检查了 github 问题https://github.com/aws-amplify/amplify-js/issues/612

这是我遵循的完整过程。

首先我们需要将验证方式改为code from link 因为我们需要在通过确认用户时抓取代码 拉姆达。要在 Cognito(AWS 控制台)中执行此操作,请转到消息自定义 -> 验证类型,将其更改为“代码”。 接下来我们将添加一个在发送前触发的 lambda 触发器 电子邮件验证。要为此添加 lambda,请转到 Lambda(AWS 控制台)并创建一个函数。下面给出的是我使用的 lambda。

exports.handler = (event, context, callback) => 
    // Identify why was this function invoked
    if(event.triggerSource === "CustomMessage_SignUp") 
        console.log('function triggered');
        console.log(event);
        // Ensure that your message contains event.request.codeParameter. This is the placeholder for code that will be sent
        const  codeParameter  = event.request
        const  userName, region  = event
        const  clientId  = event.callerContext
        const  email  = event.request.userAttributes
        const url = 'https://example.com/api/dev/user/confirm'
        const link = `<a href="$url?code=$codeParameter&username=$userName&clientId=$clientId&region=$region&email=$email" target="_blank">here</a>`
        event.response.emailSubject = "Your verification link"; // event.request.codeParameter
        event.response.emailMessage = `Thank you for signing up. Click $link to verify your email.`;
    

    // Return to Amazon Cognito
    callback(null, event);
;

您的电子邮件将使用event.response.emailSubjectevent.response.emailMessage 中指定的主题和消息发送。用户将定向到 url 变量中指定的 url。

要添加触发器转到,Cognito(Aws-console) 触发器 -> 自定义 消息并选择您刚刚创建的 lambda。 由于用户将指向我们的 url,我们可以控制请求, 确认用户并重定向到您选择的网址。

我通过 AWS APIGateway 使用了 lambda。下面给出的是我在 nodejs 中编写的代码,其中我使用了 301 重定向。

'use strict';
var AWS = require('aws-sdk');
AWS.config.setPromisesDependency(require('bluebird'));
var CognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider( apiVersion: '2016-04-19', region: process.env.REGION );

module.exports.verifyEmailAddress = (req, context, callback) => 

  console.log('req');
  console.log(req);
  const confirmationCode = req.queryStringParameters.code
  const username = req.queryStringParameters.username
  const clientId = req.queryStringParameters.clientId
  const region = req.queryStringParameters.region
  const email = req.queryStringParameters.email

  let params = 
    ClientId: clientId,
    ConfirmationCode: confirmationCode,
    Username: username
  

  var confirmSignUp = CognitoIdentityServiceProvider.confirmSignUp(params).promise()

  confirmSignUp.then(
    (data) => 
      let redirectUrl = process.env.POST_REGISTRATION_VERIFICATION_REDIRECT_URL;
      const response = 
        statusCode: 301,
        headers: 
          Location: redirectUrl,
        
      ;
    
      return callback(null, response);
    
  ).catch(
    (error) => 
      callback(error)
    
  )

根据需求将环境变量REGIONPOST_REGISTRATION_VERIFICATION_REDIRECT_URL替换成你自己的值。

【讨论】:

有没有办法“重新发送验证邮件”。所以例如重新触发 CustomMessage_SignUp?【参考方案3】:

完整的设置指南。

完整文章链接: https://medium.com/@jacobjoy/redirect-user-using-amazon-cognito-confirmation-url-d8ccb11bac75

谢谢@yasith,从简单的图片开始,让我们清楚地了解我们是如何解决这个问题的,

第 1 步: 使用您选择的语言创建一个 lambda 函数,我将在以下示例中使用 node.js。 请在继续之前阅读自定义消息 Lambda 触发器,https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-custom-message.html 在此示例中,我仅处理 CustomMessage_SignUp 您可以根据您的要求为 CustomMessage_ForgotPassword 等其他人进行自定义。 将以下代码复制到您的 lambda 函数中,

// Creating a custom URL for the user
exports.handler = (event, context, callback) => 
    if(event.triggerSource === "CustomMessage_SignUp") 
        const  codeParameter  = event.request;
        const  userName, region  = event;
        const  clientId  = event.callerContext;
        const  email  = event.request.userAttributes;
        const url = 'https://xxxxxxx.execute-api.eu-west-2.amazonaws.com/prod/redirect'
        const link = `<a href="$url?code=$codeParameter&username=$userName&clientId=$clientId&region=$region&email=$email" target="_blank">Click the link to verify</a>`;
        event.response.emailSubject = "Your verification link";
        event.response.emailMessage = `Thank you for signing up. Click $link to verify your email.`;
    
// CallBack to the lambda for the email trigger
    callback(null, event);
;

注意:一旦您设置了 API Gateway,就应该更新 const URL。

第 2 步:在 Cognito Trigger 下选择自定义消息并选择您创建的 lambda 函数

第 3 步: 在您的 API 网关中创建一个 GET API 请勿设置任何授权或启用所需的任何 API 密钥。

第 4 步: 创建另一个 Lambda 函数来验证和确认用户。

'use strict';
var AWS = require('aws-sdk');
AWS.config.setPromisesDependency(require('bluebird'));
var CognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider(
    apiVersion: '2019-11-07',
    region: process.env.REGION
);
exports.handler = (req, context, callback) => 
console.log(req);
    const confirmationCode = req.code;
    const username = req.username;
    const clientId = req.clientId;
let params = 
        ClientId: clientId,
        ConfirmationCode: confirmationCode,
        Username: username
    ;
//Validating the user
let confirmSignUp = CognitoIdentityServiceProvider.confirmSignUp(params).promise();
//Returning the redirect url
confirmSignUp.then(
        (data) => 
            context.succeed(
                location: process.env.POST_REGISTRATION_VERIFICATION_REDIRECT_URL
            );
        
    ).catch(
        (error) => 
            callback(error.message)
        
    )
;

在您选择的 IDE 中创建一个节点应用程序,然后使用 npm install 进行构建,一旦您的应用程序构建完成。 创建一个 zip(在根文件夹 5 文件中,大约基于您的 IDE)并上传到您的 lambda 应用程序。

Lambda Handler 方法应该是 = index.handler

在 lambda 环境变量中设置以下内容

POST_REGISTRATION_VERIFICATION_REDIRECT_URL 区域

在您的应用程序中,您正在验证 cognito 用户池中的用户并返回重定向的 URL。 不在范围内:错误场景也可以根据您的要求处理。

Step5:回到API Gateway,创建一个GET请求并放入您必须在Step4中创建的Lambda函数并更新映射模板。

第 6 步: 现在我们必须根据您的 lambda 响应重定向请求, 在 API Gateway 中的 Method Response 下删除 200 并创建一个 302 并根据图像添加响应标头 Location,

然后在集成响应中,您需要删除 200 并添加 302,然后将标题映射值添加为 integration.response.body.location (注意字符大小写)

最重要的步骤:完成所有设置后部署 API 并更新 Lambda 函数中的 const URL API,在 step1 中创建。

尝试创建一个测试用户,用户必须有类似这样的电子邮件链接, https://xxxx-api.eu-west-2.amazonaws.com/xx/xx/xx/redirect?code=xx&username=xxxxx;clientId=xxxxx;region=eu-west-2&email=test@gmail.com

【讨论】:

非常感谢您正在寻找这样的东西。无论如何,当我从电子邮件中打开收到的链接时,我得到了 "message":"Missing Authentication Token"。你知道如何解决这个问题吗? 如何创建第四步提到的节点应用?【参考方案4】:

您现在可以在将身份验证资源添加到项目时手动配置确认重定向 lambda 函数:amplify add auth。 Check it out

【讨论】:

以上是关于使用确认 URL 确认 amazon cognito 后如何重定向?的主要内容,如果未能解决你的问题,请参考以下文章

使用Javascript确认操作

django-allauth:如何修改电子邮件确认 url?

如何在 MailChimp 确认页面 url 中包含 URL 参数

使用DeleteView删除模板中的对象而不确认

iOS中的拨号真的需要确认吗?

java HttpClient 方法(加载、确认)