如何使用 Cognito 身份池和 Amplify 连接到 AWS AppSync

How to connect to AWS AppSync using Cognito Identity Pools and Amplify

我有一个使用 IAM 角色进行身份验证的 AWS AppSync API。我正在使用 Amplify GraphQL 客户端连接到 AppSync 服务器。下图描述了获取 IAM 凭证所需执行的步骤,我假设 Amplify 能够执行这些步骤。但是,我找不到任何关于如何设置工作示例的文档。

请注意,我直接使用 Cognito 用户池进行身份验证,而不是 Google 或 Facebook 等外部提供商。

到目前为止,我能够对用户进行身份验证并获得 JWT 令牌(第 1 步):

const Amplify = require('aws-amplify').default
const { Auth } = require('aws-amplify')


Amplify.configure({
  Auth: {
    region: process.env.AWS_REGION,
    userPoolId: process.env.COGNITO_USERPOOL_ID,
    userPoolWebClientId: process.env.COGNITO_WEBCLIENT_ID,
  },
})

Auth.signin(username, password)
  .then((user) => {
    const token = user.idToken.jwtToken
    // I've got the token - what next?
  })

如何从身份池请求 IAM 凭据(第 2 步),并使用它们通过 Amplify 访问 AppSync API(第 3 步)?

如果 Amplify 本身无法获取凭据,我可以使用 AWS.CognitoIdentityCredentials 通过 AWS SDK 请求它们,但是,我看不到将它们传递给 Amplify 以验证API 个请求(有关详细信息,请参阅 this issue I created)。

如果您的 amplify 配置具有带 AWS_IAM 身份验证的 AppSync API 和 cognito 用户池,Amplify 将使用 id 令牌自动获取 AWS 凭证。

要实际调用 AppSync API,您只需:

API.graphql({query})

我能够使用 cognito 对我的客户端进行身份验证,然后将 jwtToken 传递给 aws-appsync 客户端,以便能够通过 AMAZON_COGINITO_USER_POOLS 使用 APPSYNC。同样在代码中,您将看到我在哪里使用 API_KEY 作为替代。我把 API_KEY 注释掉了。我将此作为替代方案分享给那些也想尝试使用 Apollo 客户端和 aws-appsync 进行访问的人。

if (!process.browser) {
  global.fetch = require('node-fetch')
}

const appSyncClientOptions = {
  url: awsConfig.aws_appsync_graphqlEndpoint, 
  region: awsConfig.aws_appsync_region,
  auth: {
    // type: 'API_KEY',
    // apiKey: awsConfig.aws_appsync_apiKey,
    type: awsConfig.aws_appsync_authenticationType,   // 'AMAZON_COGNITO_USER_POOLS'
    jwtToken: async () => (await Auth.currentSession()).getAccessToken().getJwtToken()
  },
  disableOffline: true,
};

const apolloClientOptions = {
  link: createAppSyncLink({
    ...appSyncClientOptions,
    resultsFetcherLink: createHttpLink({ uri: appSyncClientOptions.url, fetch })
  })  
};

const client = new Client(appSyncClientOptions, apolloClientOptions);

const WithProvider = () => (
  <ApolloProvider client={client}>
    <Rehydrated>
      <GqlList />
    </Rehydrated>
  </ApolloProvider>
)

export default WithProvider;