For each request to the backend, I send an access token. If the token has not passed verification, then I save the config of the original request and make a request to update the tokens. If everything is fine, then I re-send the original request. The problem is that the original request is sent with the old token. Tell me how I can update the value in headers.Authorization?
import axios from 'axios'
import { setAccessToken } from '../store/authSlice'
export const axiosConfig = (accessToken: any, dispatch: any) => {
const API_URL = 'http://localhost:3001/api'
const $api = axios.create({
withCredentials: false,
baseURL: API_URL
})
$api.interceptors.request.use((config) => {
config.headers!.Authorization = `Bearer ${accessToken}`
return config
})
$api.interceptors.response.use(
(config) => {
return config
},
async (error) => {
const originalRequest = error.config
if (error.response.status === 403 && error.config && !error.config._isRetry) {
originalRequest._isRetry = true
try {
const response = await axios.get(`${API_URL}/auth/refresh-tokens`, {
withCredentials: false,
headers: {
Authorization: `Bearer ${localStorage.refreshToken}`
}
})
localStorage.setItem('refreshToken', response.data.refreshToken)
dispatch(setAccessToken(response.data.accessToken)) // new token
return $api.request(originalRequest) // <=== original request with old token
} catch (e) {
console.log('error')
}
}
throw error
}
)
return $api
}
You are using $api.interceptors.response.use() which is on the response not the request. You will not be able to change the Authorization header on a request that has already been sent.
I would use some type of error handler or axios response intercepter to direct user to the login page if they are expired/not logged in. Then I would have an error handler function that can try to attempt a re-authorization then have the error handler function resend the original request that would then have the updated Authorization token. But remember you still cant change the request that has already been sent.
myAxoisInstance.interceptors.request.use(
function (config) {
// This is run on each request so if you have or then update
the token for local storage your next request will get that updated token
const token = localStorage.getItem("token");
if (token) {
//Assign the token to the config
//If you need to send a request here to see if token is valid I don't recommend that. If you are using a JWT token you can check if it is expired here and do something else like a redirect to login.
config.headers!.Authorization = `Bearer ${token}`;
} else {
//Can retrieve and assign token here I typically like to do a redirect here as they are likely not logged or sesson expired. in or something like that. Then allow the sign-in process to add the token to the local storage.
}
return config;
},
function (error) {
return Promise.reject(error);
}
);
Related
I have a get refresh token api like this http://token.net/api/auth/refresh-token . I want to use it in my login function but to be honest I don't know anything about refresh tokens. how can I implement the refresh token into this.
LoginAuth.js
export const useLogin = () => {
const LoginAuth = async (data: AuthenticationProps) => {
await axios.post(`client.com/auth/login`,
{
email: data.email,
password: data.password,
},
{
headers: {
"Content-Type": "application/json",
Accept: "application/json",
}
}
)
.then((res) => {
if(res.status === 200) {
console.log("works");
}
}, (err) => {
console.log(err);
})
}
return {
LoginAuth,
}
}
Refresh token is used to generate new access token for an application. If the access token has an expiration date, once it expires, the user would have to authenticate again to obtain an access token.
Steps:
After successful login response, store token in localStorage.
Add axios response interceptor method axios.interceptors.response to call refresh_token API and update localStorage with new access_token.
whenever token will get expired, API call will returnINVALID_TOKEN code in response and refresh_token API will be called.
Now, further any API will be called with new refreshed token.
I'm playing around with the Spotify Web API, and I'm trying to fetch my most played songs. I'm using the client credentials OAuth flow (you can read more about it at https://developer.spotify.com/documentation/general/guides/authorization/client-credentials/) to get an access token so that I can create requests. I'm getting the access token just fine, but when I try to fetch the data with the token, I'm getting a 403, indicating that my request is not being authorized.
Error code:
GET https://api.spotify.com/v1/me/top/tracks 403
I'm using React, so I'm fetching the data on page load with useEffect.
API File (spotify.ts)
import { Buffer } from 'buffer';
const clientId = "" // omitted for privacy
const clientSecret = "" // omitted for privacy
const getToken = async (): Promise<string> => {
const res = await fetch('https://accounts.spotify.com/api/token', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from(clientId + ':' + clientSecret).toString('base64'),
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'client_credentials',
scope: 'user-top-read',
}),
});
const data = await res.json();
return data.access_token;
};
const getMostRecentSong = async (token: string) => {
const res = await fetch('https://api.spotify.com/v1/me/top/tracks', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
const data = await res.json();
return data;
}
App.tsx
import React, { useEffect } from 'react'
import { getToken, getMostRecentSong } from './services/spotify'
const App = () => {
useEffect(() => {
const getData = async () => {
const accessToken = await getToken();
const data = await getMostRecentSong(accessToken);
console.log(data);
}
getData();
}, [])
return (
...
)
}
I've included my App.tsx file as well for convenience, but the only error I'm getting is with the request itself. Any help is greatly appreciated :)
The /me/top/{type} route requires the user-top-read scope, so using the Client Credentials flow will always result in an error. Here's a summary of the Client Credentials flow:
The Client Credentials flow is used in server-to-server authentication. Since this flow does not include authorization, only endpoints that do not access user information can be accessed.
Instead, you will need to use the Authorization Code flow and proxy the Spotify requests using a request mechanism that isn't restricted by CORS (e.g. a server or serverless function), or use the Implicit Grant flow which can be implemented without an additional cooperating process (you can do it all in your client React app).
I am using axios in my react project to fetch data from an API which is authenticated using a token. Now, I m able to get the data but the when I inspect, the token is clearly visible in the Request Headers which is risky.
Please suggest If there is a way to abstract or hide the token in the request headers to make it more secure.
Below the snippet.
const makeRequest = async () => {
const response = await axios.get(BACKEND_API_URL, { headers: { 'Authorization': 'Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' } });
if (response.status === 200) {
// do something...
}
}
makeRequest()
I'm new to code and react. I am trying to make an API call to get the data. The problem is that the bearer token given to me expires every 24hrs and I don't know how to insert the Token code as a variable to my header authorization in my request in react to make it renew when it needs and deliver to me the JSON information.
something like this might work
import React from 'react';
const App = () => {
const token = "yourtokenhere";
const [result, setResult] = React.useState();
React.useEffect(()=>{
fetch('https://example.test/', {
method: "POST",
headers: {"Authorization": `Bearer ${token}`}
}).then(res => res.json()).then(json => setResult(json));
},[]);
return (
<>
{JSON.stringify(result)}
</>
);
};
For the authorization header, I would suggest interceptor.
Interceptors can perform tasks such as URL manipulation, logging, adding tokens to the header, etc before and after making an API request and response.
for fetch() API use, npm install fetch-intercept --save
import fetchIntercept from 'fetch-intercept';
const registerIntercept = fetchIntercept.register({
request: function (url, config) {
// Modify the url or config here
const authHeader = new Headers(config.headers);
authHeader.append('Authorization', 'Bearer 232Qefsg4fg4g'); // your token
config.headers = authHeader;
return [url, config];
},
requestError: function (error) {
// Called when an error occured during another 'request' interceptor call
return Promise.reject(error);
},
response: function (response) {
// Modify or log the reponse object
console.log(response);
return response;
},
responseError: function (error) {
// Handle a fetch error
return Promise.reject(error);
}
});
for Axios use, npm install axios
axios.interceptors.request.use(req => {
// `req` is the Axios request config, so you can modify
// the `headers`.
req.headers.authorization = 'my secret token';
return req;
});
Hello guys i have a JWT authentication in my react project i want to make a function to check if the user logged . My login function is like this :
export function login(data) {
const endpoint = '/api/auth/jwt/'
const csrfToken = cookie.load('csrftoken')
let thisComp = this
if (csrfToken !== undefined) {
let lookupOptions = {
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
credentials: 'include'
}
fetch(endpoint, lookupOptions)
.then(function(response){
return response.json()
}).then(function(responseData){
console.log(responseData)
localStorage.token = responseData.token
localStorage.expires = responseData.expires // Store the token
console.log("Token Stored", localStorage.token)
console.log("Token Expires", responseData.expires)
refreshToken(data) // Put in to the refresh function
}).catch(function(error){
console.log("error", error)
})
}
}
and my function isLoggedIn is like this :
export function isLoggedIn() {
// Check if we have a token stored
if (localStorage.token !== undefined) {
// I also want to check if the token is still work and don't expire
// i have acces to the expiration date like this :
// localStorage.token == > Token Expires 2018-06-19T14:51:59.451703Z in
the console
// How can check if the token still work ?
return true
}
return false
}
Can't you just check the expires property you stored in your local storage and compare it to current Date ?
Other ways to handle it: store the expiration date in the token itself, then use a jwt decoding library to decode the token and extract it from there. If you are using refresh tokens you can simply wait for the server to return a 401 Unauthorized response and send the refresh token to request a new one.