Skip to content

Instantly share code, notes, and snippets.

@Davi0k
Created May 27, 2020 15:48
Show Gist options
  • Select an option

  • Save Davi0k/e27bfa600311f4a2832d16fdd5bfd301 to your computer and use it in GitHub Desktop.

Select an option

Save Davi0k/e27bfa600311f4a2832d16fdd5bfd301 to your computer and use it in GitHub Desktop.
A small and useful authentication middleware for JWT apps which use node-fetch and a JS Storage to store Access and Refresh tokens written in Type-Script
import fetch, { Response } from "node-fetch";
export const API: string = "http://localhost:8000/api"; // The URL of your API to add to the endpoint of each request
/**
* Send a request using node-fetch and automatically inserting the user's access-token in the Authorization header.
*
* @param url - The URL to send the request to;
* @param method - The verb/method with which to make the request, by default it is set to `"GET"`;
* @param body - The body of the request if necessary, by default it is set to `null`;
*
* @returns The awaited response returned by the fetch function.
*
* @remarks The function works with Content-Type `application/json` and `multipart/form-data` but can be easily extended
*/
export async function authorization(url: string, method: string = "GET", body: any = null): Promise<Response> {
const token: string = window.localStorage.getItem("access-token"); // Or any other way you want to use to retrieve the user's access-token
const headers: HeadersInit = {
"Accept": "application/json",
"Authorization": `Bearer ${token}`
};
if(body instanceof FormData == false)
headers["Content-Type"] = "application/json";
return await fetch(url, {
method, headers,
body: (body ? body instanceof FormData ? body : JSON.stringify(body) : null) as any
});
}
/**
* Send a request using node-fetch and, if the response status code matches `401 Unauthorized`, send a request to
* refresh the` access-token` using the `refresh-token` of the authenticated user.
* If the latter is successful, it will retry the first request and return the response,
* otherwise it means that the user's session has expired.
*
* @param url - The URL to send the request to;
* @param method - The verb/method with which to make the request, by default it is set to `"GET"`;
* @param body - The body of the request if necessary, by default it is set to `null`;
*
* @returns The awaited response returned by the fetch function.
*
* @remarks The function works with Content-Type `application/json` and `multipart/form-data` but can be easily extended
*/
export async function middleware(url: string, method: string = "GET", body: any = null): Promise<Response> {
let response: Response = await authorization(url, method, body);
if(response.status == 401) {
const body: any = {
refresh: window.localStorage.getItem("refresh-token") // Or any other way you want to use to retrieve the user's refresh-token
};
const refresh: Response = await fetch(`${API}/token/refresh`, {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(body)
});
if(refresh.status == 400 || refresh.status == 401 || refresh.status == 403)
// Handle the Out-Dated Session case (Force Log-out or whatever you want)
const data: any = await refresh.json();
window.localStorage.setItem("access-token", data.access);
response = await authorization(url, method, body);
}
return response;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment