如何配置 Amplify 以使用多个 AppSync 端点?
How do I configure Amplify to to use multiple AppSync endpoints?
我需要在 React Native 应用程序中支持经过身份验证和未经身份验证的 AppSync 请求。由于 AppSync 每个 API 只允许一种授权类型,我设置了两个 API:一个用于经过身份验证的用户(Cognito 用户池),一个用于访客(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
returns 一个承诺,我一直在研究如何在应用程序的这个顶级实例化中解决一个承诺。我还需要在身份验证事件期间更换此配置。
我可以通过什么方式在启动和身份验证事件中动态地 select 和更改 ApolloProvider
配置?
这目前是不可能的。在正式支持顶级等待之前,您应该创建两个 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>
);
}`
随着 AppSync 现在支持每个 API 的多种身份验证类型,事情可能已经发生了变化;但是提供了关于如何 auth/unauth 在同一端点上实现繁荣的答案。没有回答 how-to 多端点问题,这是导致我来到这里的原因,但在 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'
}
}
};
我需要在 React Native 应用程序中支持经过身份验证和未经身份验证的 AppSync 请求。由于 AppSync 每个 API 只允许一种授权类型,我设置了两个 API:一个用于经过身份验证的用户(Cognito 用户池),一个用于访客(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
returns 一个承诺,我一直在研究如何在应用程序的这个顶级实例化中解决一个承诺。我还需要在身份验证事件期间更换此配置。
我可以通过什么方式在启动和身份验证事件中动态地 select 和更改 ApolloProvider
配置?
这目前是不可能的。在正式支持顶级等待之前,您应该创建两个 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>
);
}`
随着 AppSync 现在支持每个 API 的多种身份验证类型,事情可能已经发生了变化;但是提供了关于如何 auth/unauth 在同一端点上实现繁荣的答案。没有回答 how-to 多端点问题,这是导致我来到这里的原因,但在 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'
}
}
};