使用AWS Cognito和Sub Domains进行SSO

时间:2017-10-14 22:59:01

标签: amazon-web-services single-sign-on aws-cognito

我可以使用AWS Cognito轻松将身份信息传递到多个子域吗?如果我有三个应用程序(app1.example.com,app2.example.com,app3.example.com),我如何登录app1,然后将身份信息传递给app2和app3?我已经阅读了文档和看过getIdToken().getJwtToken之类的方法,但我还没有看到如何传递这些数据,所以我可以使用这个数据。

//Login.ts
let cognitoUser = new CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, function(){
    onSuccess: function(result){
        let jwt = result.getIdToken().getJwtToken();
        //Is it possible to pass this jwt token (or something else)
        //to app2 and app3 so I can later fetch the user from the identity pool from those apps?
    }
});

2 个答案:

答案 0 :(得分:0)

首先,应用程序子域名与AWS Cognito没有直接连接。

如果您有子域并且需要使用单个Cognito Userpool对用户进行身份验证,同时还要检查身份与子域的链接(假设用户注册后,他们从特定的子域应用程序注册),您需要存储Cognito用户或您的存储后端中的自定义属性中的信息与Cognito ID和子域链接,并在用户进行身份验证时在代码中对其进行验证。

//Login.ts
let cognitoUser = new CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, function(){
    onSuccess: function(result){
        // Also check the user custom attribute comparing with the request subdomain.
        let jwt = result.getIdToken().getJwtToken();
        //You can pass this jwt token back to the client
        //Each app can later fetch user data from identity pool
    }
});

注意:如果您使用Hosted UI进行登录,则流程可能略有不同,因为您需要为每个子域创建三个具有不同回调网址的客户端应用。

  

我正在尝试开发类似于Google的身份验证流程的解决方案。   您只需登录accounts.google.com,然后该会话即可使用   mail.google.com,news.google.com等。您无需登录   每个应用程序手动一旦我登录accounts.myapp.com,我需要   将用户的身份验证传递给mail.myapp.com和news.myapp.com。我没有   请参阅AWS文档,了解如何创建Cognito客户端的实例   (来自mail.myapp.com,或news.myapp.com)来自创建的身份   accounts.myapp.com

使用Cognito UserPools可以实现这一点。

  • 创建一个API端点,在验证用户凭据(例如用户名和密码)后将发出JWT令牌。请查看this示例中的“验证用户”部分。
  • 从您的前端应用程序调用此API并将JWT存储在浏览器存储中(例如LocalStorage,SessionStorage)。
  • 对于将来的API调用,请在标头中包含JWT并发送到API,API将验证JWT令牌。有关更多详细信息,请查看this文档中的Web API部分中的使用ID标记和访问标记。

答案 1 :(得分:0)

通过在创建CookieStorage class对象的同时使用JS SDK中的CognitoUserPool,可以在所有子域中实现SSO。当从Cognito收到的身份验证令牌存储在cookie(而不是LocalStorage)中时,它们也可在所有子域上使用。因此,调用CognitoUserPool.getCurrentUser()和CognitoUserPool.getSession()将从所有子域返回令牌。

下面的TypeScript代码段

可以找到here的完整实现。可以here查看正在运行的应用程序。

要对用户进行身份验证(在主域上,例如example.com)-

signIn(email: string, password: string): Observable<any> {
    let userPool = new CognitoUserPool({
       UserPoolId: environment._USER_POOL_ID,
       ClientId: environment._CLIENT_ID,
       Storage: new CookieStorage({secure: false, domain: "example.com"}),
    });
    let authenticationDetails = new AuthenticationDetails({
      Username: email,
      Password: password,
    });

    let userData = {
        Username: email,
        Pool: userPool,
        Storage: new CookieStorage({secure: false, domain: "example.com"}),
    };
    let cognitoUser = new CognitoUser(userData);
    return Observable.create((observer: Observer<any>) => {
      cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: result => {
          observer.next(result);
          observer.complete();
        },
        onFailure: error => observer.error(error),
      });
    });
}

要检查用户是否已通过身份验证(在子域,例如sub.example.com上)

isAuthenticated(): Observable<boolean> {
    let userPool = new CognitoUserPool({
       UserPoolId: environment._USER_POOL_ID,
       ClientId: environment._CLIENT_ID,
       Storage: new CookieStorage({secure: false, domain: "example.com"}),
    });
    let cognitoUser = userPool.getCurrentUser();
    if (cognitoUser != null) {
      return Observable.create((observer: Observer<boolean>) => {
        cognitoUser.getSession((error, session) => {
          if (error) {
            console.error(error);
            observer.next(false);
            observer.complete();
          }
          console.log(session, session.isValid(), session.isAuthenticated);
          observer.next(session.isValid());
          observer.complete();
        });
      })
}