Cognito 托管 UI

Posted

技术标签:

【中文标题】Cognito 托管 UI【英文标题】:Cognito hosted UI 【发布时间】:2018-02-06 03:45:37 【问题描述】:

我一直在考虑为 Web 应用程序设置登录名,让客户查看托管在 S3 中的数据,发现 AWS Cognito 有一个托管的 Web UI [link] 可以为我处理大部分身份验证流程,我的问题是我面临的是我无法找到如何将 Web UI 的输出集成到我的应用程序中。 Cognito 中的大多数现有文档仅引用了如何使用各种 API 来创建自己的 UI,这让我对我的问题的答案感到困惑。

是否有任何信息是在考虑 的情况下创建的?

亚马逊说您可以在几分钟内将经过身份验证的登录与 Cognito 集成,但我已经研究了几个星期,但无法弄清楚。

【问题讨论】:

您是否有指向有关托管 UI 的任何详细信息的链接? @BryceH 我一直在尝试修改 amazon-cognito-auth-js link 以允许托管 UI 与我的应用程序通信。不幸的是,我拥有的唯一其他信息是来自亚马逊的关于 UI 的促销“我们有一个新东西,看看它”的帖子 请使用更多描述性的问题标题。 【参考方案1】:

我也为此苦苦挣扎;我同意文档有点轻。

您提供的链接显示了您的 Cognito UI URL 的样子:

https://<your_domain>/login?response_type=code&client_id=<your_app_client_id>&redirect_uri=<your_callback_url>

想法是您将用户发送到此 URI,他们开展业务,然后使用某种令牌或代码将他们重定向回您。您可以通过点击左侧导航栏中的“域名”来查看您的域名。

应用客户端设置和 OAuth 授权类型

首先,检查您的应用客户端设置。您需要将回调 URL(Cognito 将重定向回的位置)列入白名单,并确保至少允许一个 OAuth 流。

Cognito App client settings

“授权码授予”将返回一个授权码,然后您将其发送到oauth2/token 端点以获取 access_token、id_token 和 refresh_token。如果您有后端应用程序并需要刷新令牌,这是一个不错的选择。

“隐式授权”是我在前端应用程序中使用的。它将直接向我的前端应用返回一个访问令牌和一个 ID 令牌。

要使用隐式授权,请将您的 Cognito UI URL 中的 response_type=code 更改为 response_type=token

隐式授权示例

因此,如果您的身份验证成功后的重定向如下所示:

https://localhost:3000/#access_token=eyJraWQiOiJG...&id_token=eyJraWQZNg....&token_type=Bearer&expires_in=3600

您只需从 URL 中剥离 id_token 并将其发送到 Cognito,并将您的用户池作为登录映射中的键。在 javascript 中:

AWS.config.credentials = new AWS.CognitoIdentityCredentials(
    IdentityPoolId: 'us-east-1:bxxxxxx6-cxxx-4xxx-8xxx-xxxxxxxxxx3c',
    Logins: 
        'cognito-idp.us-east-1.amazonaws.com/us-east-1_ixxxxxxx': idToken
    
);

idToken 是在重定向时返回给您的 id 令牌。

授权码授予类型

如果您改用授权代码授权类型 (response_type=code),您的后端将需要调用 /oauth2/token 端点以将代码交换为令牌。该调用看起来像这样:

curl -X POST \
  https://<my-cognito-domain>.auth.us-east-1.amazoncognito.com/oauth2/token \
  -H 'content-type: application/x-www-form-urlencoded' \
  -d 'grant_type=authorization_code&scope=email%20openid%20profile&redirect_uri=https%3A%2F%2Flocalhost%3A3000%2F&client_id=15xxxxxxxxxxxxxx810&code=54826355-b36e-4c8e-897c-d53d37869ee2'

然后你可以像上面一样把这个 id 令牌给 Cognito。

用户界面说明

当用户单击链接时,我的应用程序会在新选项卡中弹出 Cognito UI。当重定向返回到我的应用程序时,我使用 postMessage() 将令牌发送到父窗口,然后关闭新选项卡。我认为这是一种比较常见的模式。

我还没有尝试过,但我猜想将 UI 渲染到 iframe 中是不允许的,以缓解点击劫持。 Source


我希望这至少有点帮助。祝你好运!

【讨论】:

我无法让您的授权代码授予示例在 python Chalice lambda 中工作,使用 python“请求”库而不是 curl 来进行 POST。我确定用户池已设置好等作为使用 Warrant 库(需要应用程序 ID)的另一个方向的请求,不幸的是,您在此处提供的信息似乎是目前任何地方可用的最佳资源 :)这是我第一次发现有关 AWS 功能的文档如此疯狂 @Vorsprung 如果您想发布一个包含您的 python 代码和您遇到的任何错误的问题,我很乐意看看。 非常感谢,非常好的文档。但是您是如何将 postMessage() 集成到 Cognito UI 中的呢? 如果我正确,这需要设置一个身份池。你能为这个案例提供一个例子吗? 1)我使用 cognito ui 注册 2)然后我使用 cognito ui 登录 3)然后我加载存储在用户池中的有关用户的属性 @MikePatrick 这太有帮助了!在实现前端调用需要授权的后端的流程方面,让前端传递授权代码然后后端调用 /oauth2/token 端点是否有意义?【参考方案2】:

我实现了这个流程,没有使用 Amplify,只使用 Cognito 托管 UI:

    用户在我的网站(标签 1)中导航,并且在任何页面中用户单击登录/注册按钮。 使用我自己的域 (auth.example.com) 使用 cognito 托管 UI 打开一个新选项卡(选项卡 2) 然后用户在托管 ui 上开展业务(登录/新帐户/恢复密码等) Cognito 将 URL 中的 HASH(带有许多令牌)发送到我的站点回调。(https://example.com/login)

    我的网站处理令牌: 诀窍是创建一个 Auth 实例,这个实例可以解析哈希并在 LocalStorage 上创建用户:

    // mysite.com/login 
    import CognitoAuth from 'amazon-cognito-auth-js';
    
    // Configuration for Auth instance.
    var authData = 
        UserPoolId: 'us-east-1_xxxx',
        ClientId: '1vxxxxx',
        RedirectUriSignIn : 'https://example.com/login',
        RedirectUriSignOut : 'https://example.com/logout',
        AppWebDomain : 'example.com',
        TokenScopesArray: ['email']
        ;
    var auth = new CognitoAuth(authData);
    
    //Callbacks, you must declare, but can be empty. 
    auth.userhandler = 
        onSuccess: function(result) 
    
        ,
        onFailure: function(err) 
        
    ;
    
    //Get the full url with the hash data.
    var curUrl = window.location.href;
    
    
    //here is the trick, this step configure the LocalStorage with the user.
    auth.parseCognitoWebResponse(curUrl);
    window.top.close();
    

    在本地存储中设置用户后,回调(选项卡 2)关闭。

    在我的站点(选项卡 1)上,我配置了一个 EventListener 来监听本地存储是否发生变化。

          constructor() 
          window.addEventListener('storage', this.userLogged);
          
    
          userLogged(event) 
    
            if (event.key.indexOf('CognitoIdentityServiceProvider') !== -1) 
    
              var data = 
                          UserPoolId: 'us-east-1_xxxxx',
                          ClientId: 'xxxxx'
                          ;
    
             var userPool = new CognitoUserPool(data);
    
             //behind the scene getCurrentUser looks for the user on the local storage. 
             var cognitoUser = userPool.getCurrentUser();
                
           
    
    使用 cognitoUser 即可完成,因为您可以检索凭据或其他数据。

【讨论】:

您知道 localStorage 域是亚马逊的还是应用程序的(与 Cognito 联系的客户端)?谢谢。 本地存储是客户所在的域...所以您必须配置自己的域并且不要使用 aws 域 好的,谢谢!因为这是针对 Cognito 托管 UI 的问题,所以我不确定亚马逊是否在他们自己的域 [作为 3rd-party 存储] 在客户端(如我认为可能是使用 Cognito 的情况,例如:Google 身份验证,我认为会有 Google-3rd-party localStorage)。 这种方法将用户发送到选项卡 2 中的 cognito UI,在那里用户进行登录过程,如果它正在使用 google cognito 显示 google 登录页面等......并且在用户完成所有过程中,Cognito UI 会向您发送一个回调,其中包含您必须处理的令牌,因为处理数据存储在您的域的 localStorage 中,并可在选项卡 1 中使用。【参考方案3】:

此 AWS 博客介绍了使用托管 UI 将 Cognito 置于 S3 前面的用例:https://aws.amazon.com/blogs/networking-and-content-delivery/authorizationedge-using-cookies-protect-your-amazon-cloudfront-content-from-being-downloaded-by-unauthenticated-users/

该博客包含您可以从中窃取的示例代码。您可以使用无服务器应用程序存储库轻松部署示例解决方案。

免责声明:我撰写了该博客。希望对你有用!

【讨论】:

以上是关于Cognito 托管 UI的主要内容,如果未能解决你的问题,请参考以下文章

在 Cognito 托管 UI 中添加指向条款和条件的链接

AWS Cognito托管UI - 国际化

cognito 托管 UI 中的可选标识符不起作用

本地主机上 Cognito 托管 UI 的 Facebook 登录设置

如何利用 AWS Cognito 托管 UI 进行授权代码授予流程

AWS Amplify 与托管 Cognito UI 的联合 Okta 身份验证