如何将Amplify配置为使用多个AppSync端点?

时间:2019-01-20 02:41:59

标签: react-native apollo-client aws-appsync aws-amplify

我需要在React Native应用程序中支持经过身份验证和未经身份验证的AppSync请求。由于AppSync每个API仅允许一种授权类型,因此我要设置两种API:一种用于经过身份验证的用户(认知用户池),另一种用于来宾(API密钥)。

我认为要完成这项工作,我需要在同一应用程序中具有两个不同的AWSAppSyncClient配置。

  // authenticated user    
  const appSyncAuthenticatedClient = new AWSAppSyncClient({
    url: Config.APPSYNC_AUTHENTICATED_ENDPOINT,
    region: Config.APPSYNC_REGION,
    auth: {
      type: 'AMAZON_COGNITO_USER_POOLS',
      jwtToken: async () =>
        (await Auth.currentSession()).getAccessToken().getJwtToken()
    }
  });

  // guest    
  const appSyncUnauthenticatedClient = new AWSAppSyncClient({
    url: Config.APPSYNC_UNAUTHENTICATED_ENDPOINT,
    region: Config.APPSYNC_REGION,
    auth: {
      type: 'API_KEY',
      apiKey: Config.APPSYNC_API_ID
    }
  });

,然后根据是否已登录确定使用哪个

    Auth.currentAuthenticatedUser()
      .then(user => this.appSyncRunningClient = appSyncAuthenticatedClient)
      .catch(err => this.appSyncRunningClient = appSyncUnauthenticatedClient);

    const App = props => {
      return (
        <ApolloProvider client={this.appSyncRunningClient}>
          <Rehydrated>
              <RootStack/>
            </Root>
          </Rehydrated>
        </ApolloProvider>
      );
    };

    export default App;

这失败了,因为currentAuthenticatedUser返回了一个Promise,我被困在如何在应用程序的顶级实例中解决Promise的问题。在身份验证事件期间,我还需要换出此配置。

在启动和身份验证事件中,可以通过哪种方式动态选择和更改ApolloProvider配置?

2 个答案:

答案 0 :(得分:1)

目前无法实现。在正式支持顶层等待之前,您应该创建两个Apollo客户端,一个用于API,一个用于Cognito。

例如:在您的App.js中

export default function App(props) {
  const [client, setClient] = useState(null);

  useEffect(() => {
   checkAuth()
  }, []);

  function checkAuth() {
    Auth.currentSession().then(session => {
      const token = session.getIdToken();
      const jwtToken = token.getJwtToken();
      if (typeof jwtToken == "string") {
        const authClientConfig = {
          url: awsmobile.aws_appsync_graphqlEndpoint,
          region: awsmobile.aws_appsync_region,
          disableOffline: true,
          auth: {
            type: AUTH_TYPE.AMAZON_COGNITO_USER_POOLS,
            jwtToken: jwtToken
          }
        }
        const link = ApolloLink.from([createAuthLink(authClientConfig), createSubscriptionHandshakeLink(authClientConfig)]);
        const authClient = new ApolloClient({ link, cache: new InMemoryCache({ addTypename: false }) });
        setClient(authClient);
      } else {
        throw "error";
      }
    }).catch(e => {
      console.log(e);
      const config = {
        url: awsmobile.aws_appsync_graphqlEndpoint,
        region: awsmobile.aws_appsync_region,
        disableOffline: true,
        auth: {
          type: AUTH_TYPE.API_KEY,
          apiKey: awsmobile.aws_appsync_apiKey
        }
      }
      const link = ApolloLink.from([createAuthLink(config), createSubscriptionHandshakeLink(config)]);
      const authClient = new ApolloClient({ link, cache: new InMemoryCache({ addTypename: false }) });
        setClient(authClient);
    })
  }

    if (!client) {
      return "Loading..."
    }

    return (
      <ApolloProvider client={client}>
          ...
      </ApolloProvider>
    );
}`

答案 1 :(得分:1)

事情可能已经发生了变化,因为AppSync现在支持每个API多种身份验证类型;但是提供了有关如何在同一端点上进行身份验证/取消身份验证以实现繁荣的答案。没有回答“如何实现多个端点”的问题,这就是导致我出现在这里的原因,但是在OP场景中不再需要。

注意:此答案适用于打字稿-我不太熟悉react,但我认为它的工作原理完全相同...

  • 未经身份验证的访问使用AWS_IAM /即CognitoIdentityPool (配置为允许未经身份验证的访问)
  • 经过身份验证的访问用户AMAZON_COGNITO_USER_POOLS身份验证。

在未认证和已认证的API.graphql()调用之间切换。您需要测试当前的身份验证状态,并使用它覆盖API.graphql()调用参数中的authMode。

先决条件:

  • 必须设置graphql中的类型以允许通过@aws_iam和@aws_cognito_user_pools进行访问(请参见下面的示例)
  • 必须将AppSync API配置为允许两种身份验证类型(以下代码假定该API默认配置为AWS_IAM,但允许CognitoUserPools作为其他身份验证类型)。可以在控制台中或通过cloudFormation进行配置。

API调用的示例代码

      let authMode;
      try {
        authMode = (await Auth.currentUserPoolUser()) ? GRAPHQL_AUTH_MODE.AMAZON_COGNITO_USER_POOLS : undefined;
      } catch (err) { }

      const result = await API.graphql({
        ...graphqlOperation(statement, gqlAPIServiceArguments),
        authMode
      });

grqphql类型的示例

type Profile @aws_iam @aws_cognito_user_pools {
  username: ID!
  stuff: String!
}

我的放大配置

{
  aws_project_region: 'VALUE_HERE',
  aws_appsync_graphqlEndpoint: 'https://VALUE_HERE/graphql',
  aws_appsync_region: 'VALUE_HERE',
  aws_appsync_authenticationType: 'AWS_IAM',
  aws_appsync_apiKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXX', // This field seems to be required, but the value is ignored.
  Auth: {
    identityPoolId: 'VALUE_HERE',
    region: 'VALUE_HERE',
    userPoolId: 'VALUE_HERE',
    userPoolWebClientId: 'VALUE_HERE',
    oauth: {
      domain: 'VALUE_HERE',
      redirectSignIn: 'VALUE_HERE',
      redirectSignOut: 'VALUE_HERE',
      scope: ['email', 'openid', 'profile', 'aws.cognito.signin.user.admin'],
      responseType: 'code'
    }
  }
};

相关问题