我需要在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
配置?
答案 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,但我认为它的工作原理完全相同...
在未认证和已认证的API.graphql()调用之间切换。您需要测试当前的身份验证状态,并使用它覆盖API.graphql()调用参数中的authMode。
先决条件:
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'
}
}
};