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)); | |
}; |
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; | |
} | |
}; |
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; | |
} | |
}; |
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(); |
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; | |
} | |
}; | |
} |
Top comments (0)