【问题标题】:Firebase as Identity Provider with Cognito / AWSFirebase 作为 Cognito / AWS 的身份提供者
【发布时间】:2017-11-13 02:10:24
【问题描述】:

我很难将 Firebase 用作 Open ID Connect 提供程序。 您能否进一步描述您在完成这项工作之前和之后所经历的步骤?

有关信息,这是我迄今为止所做的: 在 AWS 控制台中:

1 - 创建一个 IAM 身份提供商 ( OpenID Connect ) 并使用 securetoken.google.com/<FIREBASE_PROJECT_ID> 作为 URL,<FIREBASE_PROJECT_ID>for Audience

2 - 手动检查指纹(与 AWS 生成的指纹匹配)

3 - 创建一个具有访问所需服务权限的角色

4 - 在 Cognito 中创建了一个身份池,并在“已验证角色”下拉列表中选择了我新创建的角色

5 - 在身份验证提供者 > OpenID 类别下选择了我的身份提供者(因此格式为):securetoken.google.com/<FIREBASE_PROJECT_ID>

在我的代码中(我使用的是 Vue.js),这是我经历的合乎逻辑的步骤:

  • 导入/设置 AWS SDK

  • 调用 Firebase 身份验证服务

  • 创建新的 CognitoIdentity
  • 使用 getOpenIdTokenForDeveloperIdentity 并推送从 Firebase 收到的 tokenID

问题是我不断收到“配置中缺少凭据”错误。

代码:

import axios from 'axios';
const AWS = require('aws-sdk');

AWS.config.region = 'eu-west-1';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
  IdentityPoolId: 'MY_COGNITO_POOL_ID',
});

export default {
  name: 'My Vue.js component name',
  data() {
    return {
      email: '',
      password: '',
      msg: '',
    };
  },
  methods: {
    submit() {
      axios
        .post(
          'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=MY_KEY',
        {
          email: this.email,
          password: password,
          returnSecureToken: true,
        },
        )
        .then((res) => {
         // stores tokens locally
          localStorage.setItem('jwt', JSON.stringify(res.data));
          const cognitoidentity = new AWS.CognitoIdentity();
          const params = {
            IdentityPoolId: 'MY_COGNITO_POOL_ID',
            Logins: {
              'securetoken.google.com/<PROJECT_ID>': res.data.idToken,
            },
            IdentityId: null,
            TokenDuration: 3600,
          };
          cognitoidentity.getOpenIdTokenForDeveloperIdentity(params, (err, data) => {
            if (err) console.log(err, err.stack); // an error occurred
            else console.log(data);           // successful response
          });
        });
    },
  },
};

以下是迄今为止我在尝试完成这项工作时使用的资源:

http://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html

Using Firebase OpenID Connect provider as AWS IAM Identity Provider

https://github.com/aws/amazon-cognito-identity-js/blob/master/examples/babel-webpack/src/main.jsx

http://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html

https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication/

https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-2-developer-authenticated-identities/

https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-3-roles-and-policies/

https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-authentication-part-4-enhanced-flow/

【问题讨论】:

  • 您是否必须在 Firebase 项目方面进行任何配置才能使其正常工作?似乎,鉴于 Firebase 项目 ID、用户的电子邮件和密码,他们可以在 Firebase 项目所有者不知道的情况下使用此方法。

标签: amazon-web-services firebase-authentication aws-sdk amazon-cognito amazon-iam


【解决方案1】:

如果对任何人都有帮助的话,最后的代码:

import axios from 'axios';

const AWS = require('aws-sdk');
const aws4 = require('aws4');

export default {
  name: 'VUE_CPNT_NAME',
  data() {
    return {
      email: '',
      password: '',
      msg: '',
      idToken: '',
    };
  },
  methods: {
    submit() {
      // Firebase SignIn API
      // Doc: https://firebase.google.com/docs/reference/rest/auth/
      axios
        .post(
          'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=[MY_KEY]',
        {
          email: this.email,
          password: this.password,
          returnSecureToken: true,
        },
        )
        .then((res) => {
          this.idToken = res.data.idToken;
          localStorage.setItem('jwt', JSON.stringify(res.data));
          AWS.config.credentials = new AWS.CognitoIdentityCredentials({
            IdentityPoolId: 'IDENTITY_POOL_ID',
            Logins: {
              'securetoken.google.com/<FIREBASE_PROJECT_ID>': res.data.idToken,
            },
          }, {
            region: 'eu-west-1',
          });
          // AWS.config.crendentials.get() methods works as well
          // or a call to cognitoidentity.getId() followed by a call to getCredentialsForIdentity() 
          // will achieve the same thing. Cool. But why!?
          AWS.config.getCredentials((err) => {
            if (err) {
              console.log(err);
            }
            const request = {
              host: 'API_GATEWAY_ENDPOINT.eu-west-1.amazonaws.com',
              method: 'GET',
              url: 'https://API_GATEWAY_ENDPOINT.eu-west-1.amazonaws.com/PATH',
              path: '/API_ENDPOINT_PATH',
            };
            // Signing the requests to API Gateway when the Authorization is set AWS_IAM.
            // Not required when Cognito User Pools are used
            const signedRequest = aws4.sign(request,
              {
                secretAccessKey: AWS.config.credentials.secretAccessKey,
                accessKeyId: AWS.config.credentials.accessKeyId,
                sessionToken: AWS.config.credentials.sessionToken,
              });
            // removing the Host header to avoid errors in Chrome
            delete signedRequest.headers.Host;
            axios(signedRequest);
          });
        });
    },
  },
};

【讨论】:

  • 很好的答案。但在纯客户端身份验证逻辑的情况下,最好通过调用 cognito api 而不是硬编码私钥来获取 aws 凭据。只是为了在浏览器上保持安全
【解决方案2】:
  • 尝试设置登录映射,即 CognitoIdentityCredentials 对象中的 firebase 令牌。请参阅this doc。

    AWS.config.credentials = 新 AWS.CognitoIdentityCredentials({
          IdentityPoolId: 'MY_COGNITO_POOL_ID',
          登录:{
            'securetoken.google.com/':
          }
    });
  • 在初始化 Cognito 客户端之前,尝试在凭证对象上调用 get 方法。您也可以改用getCredentials
  • 如果上述步骤不起作用并且它们应该起作用,请在初始化 Cognito 客户端时将凭据作为选项传递。有关使用 CognitoIdentity 构造函数时可用的选项,请参阅this doc。

    const cognitoidentity = new AWS.CognitoIdentity({credentials: AWS.config.credentials});
  • 如果您仍然收到错误,请在调用 get() 方法后尝试在控制台中记录凭据对象。理想情况下,它应该有临时凭证(accessKey、secretKey 和 sessionToken)

【讨论】:

  • 您好agent420,谢谢。我之前没有时间跟进,但今天早上我最终设法通过您上面描述的解决方案完成了这项工作。让我困惑的是documentation 建议使用 GetID 和 GetCredentialsForIdentity 方法。我已经尝试了这两种实现(getCredentials 或 GetID + GetCredentialsForIdentity)并且都可以工作。我只是不知道哪种实现是“最好的”以及何时应该使用其中一种。任何想法?谢谢,Stf
  • 嗯,GetId 和 GetCredentialsForIdentity 是获取凭据的实际低级 REST API 调用。任何其他获取凭据的方法都在后端使用它们。至于哪个是最好的,这取决于您的偏好,但我通常更喜欢 getCredentials 之类的高级方法(根据文档,SDK 在内部使用它)。在编写简短示例时,我使用 GetId 和 GetCredentialsForIdentity。如果想了解更多细节,可以在 Github 上分析 getCredentials 的实现
  • 您甚至可以尝试在 CognitoIdentityCredentials 对象上使用 refresh() 方法,该方法使用 getCredentialsForIdentity 在后端获取/刷新凭据
猜你喜欢
  • 2022-07-28
  • 2019-05-15
  • 2020-04-25
  • 2017-01-05
  • 2016-10-07
  • 2017-10-14
  • 1970-01-01
  • 2019-03-30
  • 1970-01-01
相关资源
最近更新 更多