Fix auth page's init process to account for token expiry

This commit is contained in:
Nat 2022-04-21 16:56:38 -07:00
parent de94602cd2
commit 3920ddf20e
2 changed files with 79 additions and 11 deletions

View File

@ -20,9 +20,72 @@ const AuthenticateJsx = ({navigation}) => {
const REDIRECT_URI = Linking.makeUrl("authenticate");
const [state, setState] = useState({
instance: "",
authChecked: false,
renderLogin: false,
});
const init = async () => {
const [instancePair, tokenJSONPair, profileJSONPair, appJSONPair] =
await AsyncStorage.multiGet([
"@user_instance",
"@user_token",
"@user_profile",
]);
const instance = instancePair[1];
const tokenJSON = tokenJSONPair[1];
const profileJSON = profileJSONPair[1];
if (profileJSON == null) {
// The user hasn't logged in yet.
setState({ ...state, renderLogin: true, });
return;
}
const accessToken = JSON.parse(tokenJSON).access_token;
// Check to see if the credentials are still valid
const verifiedUser = await requests.verifyCredentials(
instance,
accessToken
).catch(e => {
/* The Pixelfed API returns an HTML page when your access token gets
* revoked instead of the JSON error object. Since this causes a lot
* of problems, we're going to assume that if the response is HTML,
* then the user needs to log in again. See issue #27.
*/
if (e instanceof SyntaxError) {
// Generate faux error API response
return { "error": true };
}
});
if(verifiedUser.error) {
// `error` will be undefined if the token is valid
// Purge the user's data
await AsyncStorage.multiRemove([
"@user_instance",
"@user_token",
"@user_profile",
]);
setState({...state,
renderLogin: true,
});
return;
}
// requests.verifyCredentials returns the latest version of the
// profile on success, so take this opportunity to update it
const newProfile = verifiedUser;
await AsyncStorage.setItem(
"@user_profile",
JSON.stringify(newProfile)
);
// Since nothing went wrong, navigate to the feed.
navigation.navigate("Feed");
};
const _handleUrl = async ({ url }) => {
// When the app is foregrounded after authorizing the app from their
// instance's website...
@ -77,16 +140,13 @@ const AuthenticateJsx = ({navigation}) => {
};
useEffect(() => {
// Register the listener for the app getting foregrounded
// This is for when the user has navigated back from their web browser
// having approved the app
Linking.addEventListener("url", _handleUrl);
AsyncStorage
.getItem("@user_profile")
.then(profile => {
if (profile) {
navigation.navigate("Feed");
} else {
setState({...state, authChecked: true});
}
});
// Start initialization sequence
init();
}, []);
const _login = async () => {
@ -132,7 +192,7 @@ const AuthenticateJsx = ({navigation}) => {
return (
<SafeAreaView style = { styles.container }>
{
state.authChecked
state.renderLogin
? <View style = { styles.innerContainer }>
<View style = { styles.logo.container }>
<Image

View File

@ -96,6 +96,14 @@ export async function _delete(url, token = false) {
return resp;
}
export async function verifyCredentials(domain, token) {
const resp = await get(
`https://${domain}/api/v1/accounts/verify_credentials`,
token
);
return resp.json();
}
export async function fetchProfile(domain, id) {
const resp = await get(`https://${domain}/api/v1/accounts/${id}`);
return resp.json();