Skip to content

Updating auth headers on every request? #1383

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nikola1970 opened this issue Feb 25, 2018 · 10 comments
Closed

Updating auth headers on every request? #1383

nikola1970 opened this issue Feb 25, 2018 · 10 comments

Comments

@nikola1970
Copy link

Hello guys,

I made a new instance of the axios which I use for the protected api resources and I attached auth header with token to it, but the problem is if I go to the console and delete tokem from localStorage, axios is still sending it as the instance was not updated.

Is there a solution so my auth headers in the instance can check for token in localStorage in every request?

Thanks!

@HappyEmu
Copy link

HappyEmu commented Feb 28, 2018

I have a similar use case where it would be great if the passed headers would be evaluated lazily for every request.

Thought:
Instead of passing the headers hash eagerly as an object (axios.create({headers: {...}}) we could pass a function that returns the headers (axios.create({headers: () => {...}}) which would be evaluated before the request is sent.

What do you think?
Edit: This is a proposal, I dont think this works at the moment.

@mattstrayer
Copy link

mattstrayer commented Mar 1, 2018

I ran into the same use case. What I ended up doing in the short term was use the transformRequest function. Definitely a hack and would love to assist implementing a proper lazy-loading approach into the codebase.

See below for the code snippet. auth() gets the logged in user's token if available.

let HTTP = axios.create({
  baseURL: baseurl,
  transformRequest: [function (data, headers) {
    headers['Authorization'] = auth()
    return JSON.stringify(data)
  }],
  headers: {
    'Content-Type': 'application/json'
  }
})

@mattridley
Copy link

mattridley commented Apr 2, 2018

I have used interceptors for this purpose. If the base URL of the request is to my API I add the auth header (to prevent sending credentials to third parties). This is run on each request so if the token changes (for example as a result of a token refresh) then the next request picks up the new token. I also ensure I check for existing values in the request to allow overriding of the header from the call site if that happened to be necessary for whatever reason.

axios.interceptors.request.use(
  config => {
    if (config.baseURL === baseApiAddress && !config.headers.Authorization) {
      const token = getToken();

      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    }

    return config;
  },
  error => Promise.reject(error)
);

@jamessawyer
Copy link

@mattstrayer can you show me the getToken() method? Do you storage your token in localStorage or AsyncStorage(React Native)? Thanks in advance!

@yujingaya
Copy link

I ended up with this.

axios.create({
  baseURL: '<your-api>',
  headers: {
    Authorization: {
      toString () {
        return `Bearer ${localStorage.getItem('token')}`
      }
    }
  }
})

I'm not sure whether it works for any case.

@danielschmitz
Copy link

My http.js file:

import axios from 'axios';
import {store} from './store';

const http = axios.create ({
  baseURL: process.env.VUE_APP_ROOT_API,
  timeout: 1000,
  headers: {'Content-Type': 'application/json'},
});

http.interceptors.request.use (
  function (config) {
    const token = store.token;
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  function (error) {
    return Promise.reject (error);
  }
);

export default http;

My store, a simple get/set "class"

export const store = {
    _username: '',
    _email: '',
    _token: '',
  
    isLogged () {
      return this.token
    },
  
    set username (str) {
      this._username = str
      localStorage.setItem('username',str)
    },
    get username () {
      return this._username || localStorage.getItem('username')
    },
  
    set email (str) {
      this._email = str
      localStorage.setItem('email',str)
    },
    get email () {
      return this._email || localStorage.getItem('email')
    },
  
    set token (str) {
      this._token = str
      localStorage.setItem('token',str)
    },
    get token () {
      return this._token || localStorage.getItem('token')
    }
  
  }

My user service "class":

import http from './http'

export const user = {
  ping: () => http.get('/users/ping'),
  save: (user) => http.post('/users', user)
}

and finnaly, my implementation:

import {user} from '@/services'

 user.ping().then( r => {
      console.log(r.data)
    })

btw, process.env.VUE_APP_ROOT_API and @/services are Vue things...

Result:
image

@jchiatt
Copy link

jchiatt commented Jul 30, 2018

@danielschmitz thanks for that example!!

@emilyemorehouse
Copy link
Member

Looks like y'all figured this out and that it isn't a bug, so I'm closing this out 🙂

@conorot
Copy link

conorot commented Feb 26, 2019

I found it useful to wrap the interceptor in async/await to ensure my token was set before the API call was triggered:

http.interceptors.request.use (
  async (config) => {
    const token = await getToken(); // slightly longer running function than example above
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  (error) => {
    return Promise.reject (error);
  }
);

@alexisraca
Copy link

I have used interceptors for this purpose. If the base URL of the request is to my API I add the auth header (to prevent sending credentials to third parties). This is run on each request so if the token changes (for example as a result of a token refresh) then the next request picks up the new token. I also ensure I check for existing values in the request to allow overriding of the header from the call site if that happened to be necessary for whatever reason.

axios.interceptors.request.use(
  config => {
    if (config.baseURL === baseApiAddress && !config.headers.Authorization) {
      const token = getToken();

      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    }

    return config;
  },
  error => Promise.reject(error)
);

Interceptor seems like the most elegant solution

@axios axios locked and limited conversation to collaborators May 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests