Cognito 托管 UI

Cognito hosted UI

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

是否有使用 Cognito 托管 UI 创建的任何信息?

Amazon 说你可以在几分钟内将经过身份验证的登录与 Cognito 集成,但我已经研究了几个星期了,还是想不通。

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

您提供的 link 显示了您的 Cognito UI URL 可能的样子:

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

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

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

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

Cognito App client settings

"Authorization code grant" 将 return 一个授权代码,然后您将其发送到 oauth2/token 端点以获得 access_token、id_token 和 refresh_token。如果您有后端应用程序并想要刷新令牌,这是一个不错的选择。

"Implicit grant" 是我在前端应用程序中使用的。它将 return 一个访问令牌和一个 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

您只需将 id_token 从 URL 剥离并将其发送到 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 token给Cognito

UI 备注

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

我还没有尝试过,但我猜测将 UI 呈现到 iframe 中是不允许的,作为对点击劫持的缓解措施。


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

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

  1. 用户在我的网站(选项卡 1)中导航,并在任何页面中单击 login/register 按钮。
  2. 新标签页(标签页 2)已打开,其中使用我自己的域(auth.example.com)
  3. 托管 UI 的 Cognito
  4. 然后用户在托管 ui 上开展业务(login/new account/recover 密码等)
  5. Cognito 在 URL(带有许多标记)中向我的网站回调发送一个 HASH。(https://example.com/login
  6. 我的站点处理令牌: 诀窍是创建一个 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();
    
  7. 在本地存储中设置用户后,回调(选项卡 2)关闭。

  8. 在我的站点(选项卡 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();
                }
           }
    
  9. 使用 cognitoUser 就完成了,因为您可以检索凭据或其他数据。

这个用例,将 Cognito 放在 S3 前面,使用托管 UI,在这个 AWS 博客中有介绍:https://aws.amazon.com/blogs/networking-and-content-delivery/authorizationedge-using-cookies-protect-your-amazon-cloudfront-content-from-being-downloaded-by-unauthenticated-users/

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

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