variable-lime
variable-lime11mo ago

Passing Authorization Bearer Tokens on API Calls

Hello, I recently implemented the use of an authorization bearer API-side. The token is passed into the app correctly on login, but I'm wondering how I can let API calls use it. I couldn't seem to find anything in the documentation about it. Any insights appreciated!
16 Replies
kapa.ai
kapa.ai11mo ago
Hi @avangeous. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Sure, you can use axios.interceptors.request.use to add the token acquired from the login method to the Authorization header of API calls. This is a flexible approach that can handle complex use cases such as refreshing tokens when they expire. Here's an example of how you can do this:
import { AuthBindings } from "@refinedev/core";
import axios, { AxiosRequestConfig } from "axios";

const axiosInstance = axios.create();

axiosInstance.interceptors.request.use((request: AxiosRequestConfig) => {
// Retrieve the token from local storage
const token = JSON.parse(localStorage.getItem("auth"));
// Check if the header property exists
if (request.headers) {
// Set the Authorization header if it exists
request.headers["Authorization"] = `Bearer ${token}`;
} else {
// Create the headers property if it does not exist
request.headers = {
Authorization: `Bearer ${token}`,
};
}

return request;
});
import { AuthBindings } from "@refinedev/core";
import axios, { AxiosRequestConfig } from "axios";

const axiosInstance = axios.create();

axiosInstance.interceptors.request.use((request: AxiosRequestConfig) => {
// Retrieve the token from local storage
const token = JSON.parse(localStorage.getItem("auth"));
// Check if the header property exists
if (request.headers) {
// Set the Authorization header if it exists
request.headers["Authorization"] = `Bearer ${token}`;
} else {
// Create the headers property if it does not exist
request.headers = {
Authorization: `Bearer ${token}`,
};
}

return request;
});
In this example, the token is retrieved from local storage and added to the Authorization header of the API request. If the header property does not exist, it is created. You can find more information about this in the refine documentation (https://refine.dev/docs/tutorial/understanding-authprovider/create-authprovider). Remember to replace "auth" with the key you're using to store the token in local storage. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai11mo ago
<@1122927158348763206> kapa.ai is still learning and improving, please let us how it did by reacting below
variable-lime
variable-lime11mo ago
@kapa.ai I assume this goes in the dataProvider script?
kapa.ai
kapa.ai11mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you're correct. The axios instance with the interceptor should be used in your dataProvider. Here's an example of how you can use it:
import { Refine } from "@refinedev/core";
import axios, { AxiosRequestConfig } from "axios";
import dataProvider from "@refinedev/simple-rest"; // or your custom dataProvider

const axiosInstance = axios.create();

axiosInstance.interceptors.request.use((request: AxiosRequestConfig) => {
// Retrieve the token from local storage
const token = JSON.parse(localStorage.getItem("auth"));
// Check if the header property exists
if (request.headers) {
// Set the Authorization header if it exists
request.headers["Authorization"] = `Bearer ${token}`;
} else {
// Create the headers property if it does not exist
request.headers = {
Authorization: `Bearer ${token}`,
};
}

return request;
});

const App = () => {
const authProvider: AuthBindings = {
// your authProvider methods
};

return (
<Refine
authProvider={authProvider}
dataProvider={dataProvider(API_URL, axiosInstance)}
>
{/* ... */}
</Refine>
);
};
import { Refine } from "@refinedev/core";
import axios, { AxiosRequestConfig } from "axios";
import dataProvider from "@refinedev/simple-rest"; // or your custom dataProvider

const axiosInstance = axios.create();

axiosInstance.interceptors.request.use((request: AxiosRequestConfig) => {
// Retrieve the token from local storage
const token = JSON.parse(localStorage.getItem("auth"));
// Check if the header property exists
if (request.headers) {
// Set the Authorization header if it exists
request.headers["Authorization"] = `Bearer ${token}`;
} else {
// Create the headers property if it does not exist
request.headers = {
Authorization: `Bearer ${token}`,
};
}

return request;
});

const App = () => {
const authProvider: AuthBindings = {
// your authProvider methods
};

return (
<Refine
authProvider={authProvider}
dataProvider={dataProvider(API_URL, axiosInstance)}
>
{/* ... */}
</Refine>
);
};
In this example, the axios instance with the interceptor is passed as the second argument to the dataProvider function. This ensures that every API call made by the dataProvider will use this axios instance, and thus include the Authorization header. You can find more information about this in the refine documentation (https://refine.dev/docs/tutorial/understanding-authprovider/create-authprovider). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai11mo ago
<@1122927158348763206> kapa.ai is still learning and improving, please let us how it did by reacting below
variable-lime
variable-lime11mo ago
@kapa.ai Could I automatically log out the user upon token expiry?
kapa.ai
kapa.ai11mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can automatically log out the user upon token expiry by using the onError method in your authProvider. This method is called when you get an error response from the API. You can create your own business logic to handle the error such as refreshing the token, logging out the user, etc. Here's an example of how you can do this:
import { AuthBindings } from "@refinedev/core";

const authProvider: AuthBindings = {
// ---
logout: () => {
// ---
return {
success: true,
redirectTo: "/login",
};
},
onError: (error) => {
const status = error.status;
if (status === 401) { // assuming 401 is the status code for expired token
return {
logout: true,
redirectTo: "/login",
error: new Error(error),
};
}
return {};
},
// ---
};
import { AuthBindings } from "@refinedev/core";

const authProvider: AuthBindings = {
// ---
logout: () => {
// ---
return {
success: true,
redirectTo: "/login",
};
},
onError: (error) => {
const status = error.status;
if (status === 401) { // assuming 401 is the status code for expired token
return {
logout: true,
redirectTo: "/login",
error: new Error(error),
};
}
return {};
},
// ---
};
In this example, if the API returns a 401 status code (which is often used for expired tokens), the onError method will log out the user and redirect them to the login page. You can find more information about this in the refine documentation (https://refine.dev/docs/api-reference/core/providers/auth-provider/#onerror-). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai11mo ago
<@1122927158348763206> kapa.ai is still learning and improving, please let us how it did by reacting below
variable-lime
variable-lime11mo ago
@kapa.ai Theres some delay between the first 401 and onError actually being called. It seems like it attempts to fetch 7 times before calling onError. Can I change this so that it only calls once before calling onError?
kapa.ai
kapa.ai11mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The behavior you're experiencing might be due to the retry strategy of the HTTP client you're using. If you're using axios, for example, it doesn't automatically retry failed requests. However, if you're using a library or a custom setup that automatically retries failed requests, that might be the reason why it attempts to fetch 7 times before calling onError. Unfortunately, the provided extracts do not contain information on how to customize the retry strategy directly within refine. You might need to configure this in your HTTP client or the library you're using for API calls. For axios, you can use the axios-retry (https://github.com/softonic/axios-retry) library to customize the retry strategy. Here's an example:
import axios from 'axios';
import axiosRetry from 'axios-retry';

const axiosInstance = axios.create();

axiosRetry(axiosInstance, { retries: 1 }); // Only retry once before failing
import axios from 'axios';
import axiosRetry from 'axios-retry';

const axiosInstance = axios.create();

axiosRetry(axiosInstance, { retries: 1 }); // Only retry once before failing
In this example, axios will only retry once before failing. You can adjust the retries option to fit your needs. Please refer to the documentation of your HTTP client or the library you're using for API calls to find out how to customize the retry strategy. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai11mo ago
<@1122927158348763206> kapa.ai is still learning and improving, please let us how it did by reacting below
variable-lime
variable-lime11mo ago
@kapa.ai I am using axios; is there a way to configure it to retry failed requests?
kapa.ai
kapa.ai11mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can configure axios to retry failed requests by using the axios-retry library. Here's an example of how you can do this:
import axios from 'axios';
import axiosRetry from 'axios-retry';

const axiosInstance = axios.create();

axiosRetry(axiosInstance, { retries: 3 }); // Retry 3 times before failing
import axios from 'axios';
import axiosRetry from 'axios-retry';

const axiosInstance = axios.create();

axiosRetry(axiosInstance, { retries: 3 }); // Retry 3 times before failing
In this example, axios will retry 3 times before failing. You can adjust the retries option to fit your needs. Please note that this is not directly related to refine, but a feature of the axios library. You can find more information about this in the axios-retry documentation (https://github.com/softonic/axios-retry). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai11mo ago
<@1122927158348763206> kapa.ai is still learning and improving, please let us how it did by reacting below
variable-lime
variable-lime11mo ago
🤔 @kapa.ai Could I log the user out via an axios interceptor rather than authProvider's onError?
kapa.ai
kapa.ai11mo ago
Let me check the knowledge base for you. One moment! :books: @avangeous That's a great question, but unfortunately I am only capable of responding to a maximum of three questions per thread. Don't hesitate to create a new thread for any further questions you have though. I'm here to help!