Hello Everyone,
I’m currently developing a React Native-based mobile application, utilizing Auth0 as our authentication service and apollo-client library. However, I’m encountering a significant issue with replacing expired access tokens with new ones. Despite extensive research through Auth0’s documentation and various articles, I haven’t been able to implement this in a production-ready manner.
I wanted to know what is the ideal way to exchange the expired access_token with the new one without failure of any API calls.
Currently I’m using the oauth/token
to get a new access_token but the problem I’m facing involves the oauth/token
endpoint returning a 403 status code. I’m unsure if I’m calling this endpoint correctly for obtaining a new access token and replacing the existing one. If this is the correct approach, I need guidance on how to fix the issue.
Here’s a summary of my current implementation:
Current Implementation
I’m using a custom hook to check if the token has expired and, if so, to update it with a new one.
import Config from 'config';
import 'core-js/stable/atob'; // Polyfill since RN doesn't support atob 👉🏾 https://github.com/auth0/jwt-decode/issues/241
import { jwtDecode, JwtPayload } from 'jwt-decode';
import { captureSentryException } from 'sentry_telemetry/sentryLogger';
import { getAccessToken, getRefreshToken, setAccessToken, setRefreshToken } from '../storage/token';
export const useRefreshToken = () => {
const accessToken = getAccessToken();
const refreshToken = getRefreshToken();
function isTokenExpired() {
try {
if (!accessToken) {
return false;
}
const decoded = jwtDecode<JwtPayload>(accessToken);
const currentTime = Date.now() / 1000; // current time in seconds
return decoded.exp ? decoded.exp < currentTime : false;
} catch (err) {
console.error(err);
return false;
}
}
const getNewAccessToken = async () => {
try {
if (!refreshToken) {
return;
}
if (!isTokenExpired()) {
return;
}
const response = await fetch(`https://${Config.Auth0Domain}/oauth/token`, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
body: `grant_type=refresh_token&client_id=${Config.Auth0ClientId}&client_secret=${Config.Auth0SecretKey}&refresh_token=${refreshToken}`,
});
if (response.ok || response.status === 200) {
const data = await response.json();
setAccessToken(data.access_token);
setRefreshToken(data.refresh_token);
return { token: data?.access_token || '' };
}
} catch (err) {
console.error(err);
captureSentryException('Error in fetching new access token', err?.message);
}
};
return { getNewAccessToken, isTokenExpired };
};
Error Log:
"_bodyBlob": {"_data": {"__collector": [Object], "blobId": "D2AAB3BC-0237-4F3F-879E-8EA27E2DC6E5", "name": "token.json", "offset": 0, "size": 81, "type": "application/json"}}, "_bodyInit": {"_data": {"__collector": [Object], "blobId": "D2AAB3BC-0237-4F3F-879E-8EA27E2DC6E5", "name": "token.json", "offset": 0, "size": 81, "type": "application/json"}}, "bodyUsed": false, "headers": {"map": {"alt-svc": "h3=\":443\"; ma=86400", "cache-control": "private, no-store, no-cache, must-revalidate, post-check=0, pre-check=0, no-transform", "cf-cache-status": "DYNAMIC", "cf-ray": "8a94aa190d903a1a-BOM", "content-length": "81", "content-type": "application/json", "date": "Fri, 26 Jul 2024 13:16:29 GMT", "server": "cloudflare", "strict-transport-security": "max-age=31536000; includeSubDomains", "vary": "Origin, Accept-Encoding", "x-auth0-requestid": "b6c8b21f6bb08b584a25", "x-content-type-options": "nosniff", "x-ratelimit-limit": "300", "x-ratelimit-remaining": "299", "x-ratelimit-reset": "1721999790"}}, "ok": false, "status": 403, "statusText": "", "type": "default", "url": "https://wishup-app.us.auth0.com/oauth/token"}
Any assistance from the community would be highly appreciated.
Thank you!