DEV Community

Saad
Saad

Posted on

Creating a reusable “Token Manager” class in react-native.

In any app, especially an app that has user accounts, it is a very common task to check for existing user token and redirects the user either to AuthStack or AppStack according to the token found. So for this common task, we can create our own token manager class which handles the common functionalities related to user token. In today’s code read I will try to document that.

Usually, we store tokens locally in our AsyncStorage, so we have 2 functions in our class. One is to set and the other one is to clear the token.

clearToken = async () => {
await AsyncStorage.multiRemove(['tokenObj', 'userObj']); // removing token and user
};
setToken = async data => {
await AsyncStorage.setItem('tokenObj', JSON.stringify(data.token));
await AsyncStorage.setItem('userObj', JSON.stringify(data.user));
};
view raw tokenizer.js hosted with ❤ by GitHub

Now the next one is the most important function, anywhere in our app where we want to get the valid token for the user we need to check a few things. They are the following:

  • First, we check if there is any saved token in our local storage. We check for the tokenObj, that object should have the necessary information about the token. Like token value, expires-at, etc.
  • If there is not an existing token, we return null.
  • If there is an existing token, we need to check if the token is still valid, meaning if it is still not expired. This information should be passed from API when the user logged in or signed up in the app before.

So with all these steps, our function should look like following

getValidToken = async () => {
const token = JSON.parse(await AsyncStorage.getItem('tokenObj'));
// Check if we have a valid token
if (token) {
// Grab the token expiry date from the tokenObj
const {expiresIn} = token;
const expireDate = Date.parse(expiresIn);
//We refresh the token withing the 10 days it will expire
const currentDate = moment().add(10, 'days');
if (currentDate >= expireDate) { // getting new token
// new token function hits the refresh token api to get the new token
let newToken = await this.newToken();
return newToken.accessToken;
} else {
// not expired
return token.accessToken;
}
} else { // no token in local storage, return null
return null;
}
};
view raw tokenizer.js hosted with ❤ by GitHub

Finally, we have our new token function where if the token is expired we request for refresh token from the API.

newToken = async () => {
const token = JSON.parse(await AsyncStorage.getItem('tokenObj'));
const user =
JSON.parse(await AsyncStorage.getItem('userObj')) ||
JSON.parse(await AsyncStorage.getItem('userObjk'));
const baseUrl = this.state.baseUrl; // it will be API BASE URL
// just an API example
let response = await axios.post(baseUrl + '/auth/refresh-token/', {
clientId: Config.CLIENT_ID,
clientSecret: Config.CLIENT_SECRET,
email: user.email,
refreshToken: token.refreshToken,
});
if (response.status == 200) {
let {data} = await response;
this.setToken(data); // set the new token in our async storage
return data; // returning new token data
} else {
this.clearToken();
return null;
}
};
view raw tokenizer.js hosted with ❤ by GitHub

Once we have this class set up, we just need to import this class and create an object to get a valid token from anywhere in our app like the following.

const tokenize = new Tokenizer();
const token = await tokenize.getValidToken();
view raw tokenizer.js hosted with ❤ by GitHub

The full code for the tokenizer class is given below for reference.

import Config from 'react-native-config';
import AsyncStorage from '@react-native-community/async-storage';
import axios from 'axios';
import moment from 'moment';
export default class Tokenizer {
constructor() {
this.state = {
baseUrl: Config.API_URL,
};
}
clearToken = async () => {
await AsyncStorage.multiRemove(['tokenObj', 'userObj']);
};
setToken = async data => {
await AsyncStorage.setItem('tokenObj', JSON.stringify(data.token));
await AsyncStorage.setItem('userObj', JSON.stringify(data.user));
};
getValidToken = async () => {
const token = JSON.parse(await AsyncStorage.getItem('tokenObj'));
// Check if we have a valid token
if (token) {
// Grab the token expiry date
const {expiresIn} = token;
const expireDate = Date.parse(expiresIn);
const currentDate = moment().add(10, 'days');
if (currentDate >= expireDate) {
let newToken = await this.newToken();
return newToken.accessToken;
} else {
return token.accessToken;
}
} else {
return null;
}
};
newToken = async () => {
const token = JSON.parse(await AsyncStorage.getItem('tokenObj'));
const user =
JSON.parse(await AsyncStorage.getItem('userObj')) ||
JSON.parse(await AsyncStorage.getItem('userObjk'));
const baseUrl = this.state.baseUrl;
let response = await axios.post(baseUrl + '/auth/refresh-token/', {
clientId: Config.CLIENT_ID,
clientSecret: Config.CLIENT_SECRET,
email: user.email,
refreshToken: token.refreshToken,
});
if (response.status == 200) {
let {data} = await response;
this.setToken(data);
return data;
} else {
this.clearToken();
return null;
}
};
}
view raw tokenizer.js hosted with ❤ by GitHub

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay