'Expo AuthSession promptAsync - no way to wait for return when getting a new access token
We have a managed Expo app using AuthSession specifically to deploy our app to a web environment. Authenticating using Auth0 and a PKCE grant.
Have run into an issue trying to get a new access token when our current access token has expired. Before making an HTTP request we check to see if our access token has expired and if it has we use AuthSession.promptAysnc() to get a new one. The problem is we have no way of waiting for promptAsync to finish before making our HTTP request.
Have we missed something?
const [request, result, promptAsync] = AuthSession.useAuthRequest(
{
redirectUri,
clientId,
scopes,
prompt: AuthSession.Prompt.Login,
extraParams: {
audience
}
},
{ authorizationEndpoint, tokenEndpoint, revocationEndpoint }
);
const refreshAuthSessionAsync = async () => {
...
promptAsync({ useProxy });
// sleep hack - wait until we have something to return
await new Promise(r => setTimeout(r, 1000));
return authState;
};
const handleFetchAsync = async (url, request) => {
...
if (Date.parse(expiresAt) < (new Date()).getTime()) {
newAuthState = await refreshAuthSessionAsync();
return newAuthState;
}
...
}
Solution 1:[1]
I'm working through a similar problem with an Expo managed app trying to access a refresh token after authenticating through Auth0 using a PKCE flow.
I came across this repo https://github.com/tiagob/create-full-stack/blob/master/packages/cfs-expo-auth0/src/index.tsx while reading through the comments of this Expo issue about refresh tokens and Auth0 https://github.com/expo/examples/issues/209.
I haven't implemented anything from this repo yet, but it seems like some of its approach may solve the issue I'm having and hopefully your problem.
Solution 2:[2]
I used a useEffect hook to "wait" for the request to finish and a useState hook to save the current state.
useEffect(() => {
if (state !== stateMode.request_running) return;
if (request === null || response === null || response.type !== "success") {
// Request not done
}
else {
// Request done
onLogin();
setState(stateMode.request_done);
}
});
The state I used
const stateMode = {
initialized: 1,
request_running: 2,
request_done: 3
};
const [state, setState] = useState(stateMode.initialized);
And before calling promptAsync I set
setState(stateMode.request_running);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | ymekuria |
| Solution 2 |
