I am currently using Django (2.1) to build an API, and I have added djangorestframework-jwt to manage JWT.
Here is the configuration:
JWT_AUTH = {
'JWT_SECRET_KEY': SECRET_KEY,
'JWT_VERIFY': True,
'JWT_VERIFY_EXPIRATION': True,
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=14),
'JWT_ALLOW_REFRESH': True,
'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
'JWT_AUTH_HEADER_PREFIX': 'Bearer',
}
and the endpoints:
urlpatterns = [
path('auth/get-token/', obtain_jwt_token),
path('auth/refresh-token/', refresh_jwt_token),
]
The client is built with ReactJS. I use an axios instance as a client to communicate with the API. This instance is created that way :
import axios from 'axios'
import jwt_decode from 'jwt-decode' // eslint-disable-line
import { signOut } from '../actions/authActions'
const signOutOn401 = (statusCode) => {
if (statusCode === 401) {
signOut()
window.location = '/signin'
}
}
const client = axios.create({
baseURL: process.env.API_URL,
headers: {'Authorization': ''}
})
/*
* This interceptor is used for:
* - adding Authorization header if JWT available
* - refreshing JWT to keep user authenticated
*/
client.interceptors.request.use((config) => {
if (window.localStorage.getItem('token')) {
let token = window.localStorage.getItem('token')
// Calculate time difference in days
// between now and token expiration date
const t = ((jwt_decode(token).exp * 1000) - Date.now()) / 1000 / 60 / 60 / 24
// Refresh the token if the time difference is
// smaller than 13 days (original token is valid 14 days)
if (t < 13) {
axios.post(`${process.env.API_URL}/auth/refresh-token/`, {
token: token
})
.then(({data}) => {
token = data.token
})
.catch((error) => {
signOutOn401(error.response.status)
return error
})
}
config.headers['Authorization'] = `Bearer ${token}`
}
return config
})
/*
* This interceptor is used for:
* - disconnect user if JWT is expired or revoked
*/
client.interceptors.response.use(
(response) => {
return response
},
(error) => {
signOutOn401(error.response.status)
return error
}
)
export default client
The signout action only clear the session and clean the store :
export const signOut = () => {
window.localStorage.clear()
return ({
type: SIGN_OUT,
payload: {
authenticated: false,
user: {},
errorMessage: ''
}
})
}
Everything looks working fine, I would just like to know if that implementation is correct, and if there is no security flaw :)