Javascript 我应该联合cognito用户池和其他社交IDP,还是通过用户池本身进行社交登录

Javascript 我应该联合cognito用户池和其他社交IDP,还是通过用户池本身进行社交登录,javascript,amazon-web-services,jwt,amazon-cognito,aws-amplify,Javascript,Amazon Web Services,Jwt,Amazon Cognito,Aws Amplify,我正在构建一个社交聊天应用程序,最初有一个cognito用户池,与Google/Facebook联合。我是基于cognito用户的user sub和google/facebook的identity id来存储用户数据的。然后在我的lambda gql解析器中,我将通过AWS sdk进行身份验证: AWS.config.credentials = new AWS.CognitoIdentityCredentials({ IdentityPoolId: process.env.IDENT

我正在构建一个社交聊天应用程序,最初有一个cognito用户池,与Google/Facebook联合。我是基于cognito用户的user sub和google/facebook的identity id来存储用户数据的。然后在我的lambda gql解析器中,我将通过AWS sdk进行身份验证:

  AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: process.env.IDENTITY_POOL_ID,
    Logins: {
      [`cognito-idp.us-east-1.amazonaws.com/${
        process.env.COGNITO_USERPOOL_ID
      }`]: Authorization,
    },
  });
因为所有用户都是平等的,而且我不需要对aws资源的访问进行细粒度的控制,所以似乎更可取的做法是通过userpool处理所有身份验证,并完全取消标识池

例如,如果我想禁止一个用户的帐户,似乎我必须首先根据身份id查找提供者,然后根据提供者执行不同的操作

因此,我的问题是: 1.这可能吗? - -

这里似乎有很多混乱,aws文档也不像平常那么清晰(这在国际海事组织中并不多见)。

似乎有一种方法可以做到这一点。我遵循了上面的指南,发现托管UI端点出现错误,但这可能是我的错()。但是,我不希望托管UI端点,我希望cognito用户通过我的自定义表单登录,然后社会登录用户单击“continue with fb”按钮并自动填充我的用户池

然后用以下代码替换上述代码以验证所有用户:

const validate = token => new Promise(async (resolve) => {
  const {
    data: { keys },
  } = await axios(url);

  const { sub, ...res } = decode(token, { complete: true });
  const { kid } = decode(token, { header: true });
  const jwk = R.find(R.propEq('kid', kid))(keys);
  const pem = jwkToPem(jwk);
  const response = res && res['cognito:username']
    ? { sub, user: res['cognito:username'] }
    : { sub };
  try {
    await verify(token, pem);
    resolve(response);
  } catch (error) {
    resolve(false);
  }
});
  • 如果可能,什么样的正确机制可以替代以下内容:
  • 从我所看到的,似乎没有一种方法与放大来实现这一点。使用aws sdk有什么方法可以做到这一点吗?从facebookapi映射回调来创建cognito用户客户端怎么样?看起来可能会变得很混乱

  • 如果没有实现上述功能的机制,我是否应该将cognito用户与社交登录联合起来

  • 那么我应该用什么来识别数据库中的用户呢?我目前使用username和sub作为cognito,使用identity id作为联邦用户。从身份验证令牌服务器端然后在客户端上提取sub:


  • 如果有人能提供我尚未找到的关于使用cognito用户池代替联邦的详细权威答案,那将是非常好的。否则,我将非常感谢您提供一份正确方法的总体概述。

    以下是我最终为处于类似职位的任何人所做的工作,这并不全面:

  • 创建用户池,不要指定客户端机密或任何可能与Facebook/Google返回的内容冲突的必需属性
  • 在“域”下的Cognito侧栏中,添加您想要的内容
  • 添加Cognito提供的您的身份,对于FB,您希望它们以逗号分隔,如:openid、电话、电子邮件、个人资料、aws.Cognito.signin.user.admin
  • 从应用程序客户端设置启用FB,选择隐式授权。我相信,但不是肯定的,openid是生成访问密钥所必需的,signin.user.admin是获取RS256令牌以验证公钥的所必需的
  • 来自FB dev控制台的,作为有效的oauth重定向
  • 然后,仍然在FB上,转到设置(常规而非特定于应用程序),然后输入
  • 为您的网站url
  • 然后,对于登录按钮,您可以添加以下代码
  • 然后在重定向页面上:
  • 然后可以使用Auth.currentSession()从客户端获取用户属性

  • 然后,服务器端您可以验证所有用户,如下所示:
  •       Auth.federatedSignIn('facebook', { token: accessToken, expires_at }, user)
            .then(credentials => Auth.currentAuthenticatedUser())
            .then((user) => {
              onStateChange('signedIn', {});
            })
            .catch((e) => {
              console.log(e);
            });
    
      Auth.currentSession()
        .then((data) => {
          const userSub = R.path(['accessToken', 'payload', 'sub'], data);
          resolve(userSub);
        })
        .catch(async () => {
          try {
            const result = await Auth.currentCredentials();
            const credentials = Auth.essentialCredentials(result);
            resolve(removeRegionFromId(credentials.identityId));
          } catch (error) {
            resolve(false);
          }
        });
    
    const authenticate = callbackFn => () => {
      const domain = process.env.COGNITO_APP_DOMAIN;
      const clientId = process.env.COGNITO_USERPOOL_CLIENT_ID;
      const type = 'token';
      const scope = 'openid phone email profile aws.cognito.signin.user.admin';
      const verification = generateVerification();
      const provider = 'Facebook';
      const callback = `${window.location.protocol}//${
        window.location.host
      }/callback`;
    
      const url = `${domain}/authorize?identity_provider=${provider}&response_type=${type}&client_id=${clientId}&redirect_uri=${callback}&state=${verification}&scope=${scope}`;
      window.open(url, '_self');
    };
    
      useEffect(() => {
        // eslint-disable-next-line no-undef
        if (window.location.href.includes('#access_token')) {
          const callback = () => history.push('/');
          newAuthUser(callback);
        }
      }, []);
    
    /* eslint-disable no-undef */
    import { CognitoAuth } from 'amazon-cognito-auth-js';
    import setToast from './setToast';
    
    export default (callback) => {
      const AppWebDomain = process.env.COGNITO_APP_DOMAIN;
      // https://yourdomainhere.auth.us-east-1.amazoncognito.com'
      const TokenScopesArray = [
        'phone',
        'email',
        'profile',
        'openid',
        'aws.cognito.signin.user.admin',
      ];
      const redirect = 'http://localhost:8080/auth';
      const authData = {
        ClientId: process.env.COGNITO_USERPOOL_CLIENT_ID,
        AppWebDomain,
        TokenScopesArray,
        RedirectUriSignIn: redirect,
        RedirectUriSignOut: redirect,
        IdentityProvider: 'Facebook',
        UserPoolId: process.env.COGNITO_USERPOOL_ID,
        AdvancedSecurityDataCollectionFlag: true,
      };
      const auth = new CognitoAuth(authData);
    
      auth.userhandler = {
        onSuccess() {
          setToast('logged-in');
          callback();
        },
        onFailure(error) {
          setToast('auth-error', error);
          callback();
        },
      };
    
      const curUrl = window.location.href;
      auth.parseCognitoWebResponse(curUrl);
    };
    
    const decode = require('jwt-decode');
    const jwt = require('jsonwebtoken');
    const jwkToPem = require('jwk-to-pem');
    const axios = require('axios');
    const R = require('ramda');
    const logger = require('./logger');
    
    const url = `https://cognito-idp.us-east-1.amazonaws.com/${
      process.env.COGNITO_USERPOOL_ID
    }/.well-known/jwks.json`;
    
    const verify = (token, n) => new Promise((resolve, reject) => {
      jwt.verify(token, n, { algorithms: ['RS256'] }, (err, decoded) => {
        if (err) {
          reject(new Error('invalid_token', err));
        } else {
          resolve(decoded);
        }
      });
    });
    
    const validate = token => new Promise(async (resolve) => {
      const {
        data: { keys },
      } = await axios(url);
    
      const { sub, ...res } = decode(token, { complete: true });
      const { kid } = decode(token, { header: true });
      const jwk = R.find(R.propEq('kid', kid))(keys);
      const pem = jwkToPem(jwk);
      const response = res && res['cognito:username']
        ? { sub, user: res['cognito:username'] }
        : { sub };
      try {
        await verify(token, pem);
    
        resolve(response);
      } catch (error) {
        logger['on-failure']('CHECK_CREDENTIALS', error);
        resolve(false);
      }
    });
    
    const checkCredentialsCognito = Authorization => validate(Authorization);