Asynchronously authenticate before request










2















So I have an API and I am trying to authenticate by hitting an endpoint with credentials (this part I've gotten working) and then save the received token and use it in all subsequent requests.



My problem is that the authenticate() method is asynchronous, but all other request methods like get() need the token from the authenticate() method. So I can't just export my get() method because the export is synchronous (as I've read) and it will be exported before authentication happens. I could authenticate for every request but that seems wasteful and inefficient.



I am not sure what to do here, I'm using axios, what's the proper way of doing this?



Edit



I'll be a bit more specific here. I have created an axios instance:



var instance = axios.create(
baseURL: `http://$config.server:$config.port`,
timeout: 1000,
headers:
'Content-Type': 'application/json',
'Accept': 'application/json'

)


I want to get the authentication token, and include it in the instance header:



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance['X-Token'] = result.data.token



Now I want to export that instance to be used in other files










share|improve this question
























  • you can await it if you have ES6. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – ruby_newbie
    Nov 14 '18 at 22:13











  • Can you show me an example? Pseudocode is fine

    – Dan M
    Nov 14 '18 at 22:14











  • Sure. const token = await authenticate() const res = get(endpoint, token);

    – ruby_newbie
    Nov 14 '18 at 22:16







  • 1





    @ruby_newbie await was introduced in ECMAScript 2017, not in ECMAScript 2015 (aka ES6)

    – Patrick Roberts
    Nov 14 '18 at 22:24















2















So I have an API and I am trying to authenticate by hitting an endpoint with credentials (this part I've gotten working) and then save the received token and use it in all subsequent requests.



My problem is that the authenticate() method is asynchronous, but all other request methods like get() need the token from the authenticate() method. So I can't just export my get() method because the export is synchronous (as I've read) and it will be exported before authentication happens. I could authenticate for every request but that seems wasteful and inefficient.



I am not sure what to do here, I'm using axios, what's the proper way of doing this?



Edit



I'll be a bit more specific here. I have created an axios instance:



var instance = axios.create(
baseURL: `http://$config.server:$config.port`,
timeout: 1000,
headers:
'Content-Type': 'application/json',
'Accept': 'application/json'

)


I want to get the authentication token, and include it in the instance header:



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance['X-Token'] = result.data.token



Now I want to export that instance to be used in other files










share|improve this question
























  • you can await it if you have ES6. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – ruby_newbie
    Nov 14 '18 at 22:13











  • Can you show me an example? Pseudocode is fine

    – Dan M
    Nov 14 '18 at 22:14











  • Sure. const token = await authenticate() const res = get(endpoint, token);

    – ruby_newbie
    Nov 14 '18 at 22:16







  • 1





    @ruby_newbie await was introduced in ECMAScript 2017, not in ECMAScript 2015 (aka ES6)

    – Patrick Roberts
    Nov 14 '18 at 22:24













2












2








2








So I have an API and I am trying to authenticate by hitting an endpoint with credentials (this part I've gotten working) and then save the received token and use it in all subsequent requests.



My problem is that the authenticate() method is asynchronous, but all other request methods like get() need the token from the authenticate() method. So I can't just export my get() method because the export is synchronous (as I've read) and it will be exported before authentication happens. I could authenticate for every request but that seems wasteful and inefficient.



I am not sure what to do here, I'm using axios, what's the proper way of doing this?



Edit



I'll be a bit more specific here. I have created an axios instance:



var instance = axios.create(
baseURL: `http://$config.server:$config.port`,
timeout: 1000,
headers:
'Content-Type': 'application/json',
'Accept': 'application/json'

)


I want to get the authentication token, and include it in the instance header:



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance['X-Token'] = result.data.token



Now I want to export that instance to be used in other files










share|improve this question
















So I have an API and I am trying to authenticate by hitting an endpoint with credentials (this part I've gotten working) and then save the received token and use it in all subsequent requests.



My problem is that the authenticate() method is asynchronous, but all other request methods like get() need the token from the authenticate() method. So I can't just export my get() method because the export is synchronous (as I've read) and it will be exported before authentication happens. I could authenticate for every request but that seems wasteful and inefficient.



I am not sure what to do here, I'm using axios, what's the proper way of doing this?



Edit



I'll be a bit more specific here. I have created an axios instance:



var instance = axios.create(
baseURL: `http://$config.server:$config.port`,
timeout: 1000,
headers:
'Content-Type': 'application/json',
'Accept': 'application/json'

)


I want to get the authentication token, and include it in the instance header:



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance['X-Token'] = result.data.token



Now I want to export that instance to be used in other files







javascript asynchronous axios






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 22:22







Dan M

















asked Nov 14 '18 at 22:12









Dan MDan M

112




112












  • you can await it if you have ES6. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – ruby_newbie
    Nov 14 '18 at 22:13











  • Can you show me an example? Pseudocode is fine

    – Dan M
    Nov 14 '18 at 22:14











  • Sure. const token = await authenticate() const res = get(endpoint, token);

    – ruby_newbie
    Nov 14 '18 at 22:16







  • 1





    @ruby_newbie await was introduced in ECMAScript 2017, not in ECMAScript 2015 (aka ES6)

    – Patrick Roberts
    Nov 14 '18 at 22:24

















  • you can await it if you have ES6. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

    – ruby_newbie
    Nov 14 '18 at 22:13











  • Can you show me an example? Pseudocode is fine

    – Dan M
    Nov 14 '18 at 22:14











  • Sure. const token = await authenticate() const res = get(endpoint, token);

    – ruby_newbie
    Nov 14 '18 at 22:16







  • 1





    @ruby_newbie await was introduced in ECMAScript 2017, not in ECMAScript 2015 (aka ES6)

    – Patrick Roberts
    Nov 14 '18 at 22:24
















you can await it if you have ES6. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

– ruby_newbie
Nov 14 '18 at 22:13





you can await it if you have ES6. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

– ruby_newbie
Nov 14 '18 at 22:13













Can you show me an example? Pseudocode is fine

– Dan M
Nov 14 '18 at 22:14





Can you show me an example? Pseudocode is fine

– Dan M
Nov 14 '18 at 22:14













Sure. const token = await authenticate() const res = get(endpoint, token);

– ruby_newbie
Nov 14 '18 at 22:16






Sure. const token = await authenticate() const res = get(endpoint, token);

– ruby_newbie
Nov 14 '18 at 22:16





1




1





@ruby_newbie await was introduced in ECMAScript 2017, not in ECMAScript 2015 (aka ES6)

– Patrick Roberts
Nov 14 '18 at 22:24





@ruby_newbie await was introduced in ECMAScript 2017, not in ECMAScript 2015 (aka ES6)

– Patrick Roberts
Nov 14 '18 at 22:24












2 Answers
2






active

oldest

votes


















2














You can use async/await. This is semi-pseudocode:



async function doStuff() 
const result = await axios.authenticate();
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);



Alternatively, you can just use then:



function doStuff(token) 
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);


axios.authenticate().then(result =>
const token = // extract token from whatever format of result is
doStuff(token);






share|improve this answer























  • Ok, but this model is on a per request basis. I want to save the token, include it in the axios instance header, and then be able to make requests using that instance and not having to manually include the header every time

    – Dan M
    Nov 14 '18 at 22:19






  • 1





    One way to do this is to to use authenticate().then() chain on first request (or if token is not present), and skip it if token is present for subsequent requests.

    – ODYN-Kon
    Nov 14 '18 at 22:22











  • So for every API call I would need to have a built in conditional to check if the token is set before I make the request? Is there not a way to set the token once, assign it to an axios instance, and then import that instance into whatever files require it to make API calls?

    – Dan M
    Nov 15 '18 at 16:11











  • You can but you need to make sure that happens before your first call to get().

    – ODYN-Kon
    Nov 15 '18 at 16:16











  • Haha, yes! That is exactly what I want to do, I just don't know how!

    – Dan M
    Nov 15 '18 at 16:21


















2














With Axios you have the ability to set default values for all requests.



So for just a single axios instance you can do...



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance.defaults.headers.common['X-Token'] = result.data.token;



Alternatively, (which it sounds like you want to do) you can add it for the default Axios export. Then all requests will automatically have the header.



async function authenticate(endpoint, username, password) 
const res = await axios.post(`$endpoint/session`, username, password );
axios.defaults.headers.common['X-Token'] = result.data.token;



Then you don't have to worry about passing around an instance between all parts of your app and can just use import * as axios from 'axios' and have the header set.




Axios also provides and extremely helpful function called interceptors which you can use to inspect a request prior to making it. You can use to check to make sure that the request has the auth header and if it doesn't you can perform that logic. I came up with this and it seems to work well!



axios.interceptors.request.use(async (config) => 
// request intercepted, check (1) the header is missing and (2) that the intercepted request isn't authorizing
if (!config.headers.common['X-Token'] && config.authorizing !== true)
const endpoint, username, password = appConfig;

// make a request to get your token AND pass our custom config
const result = await axios.post(`$endpoint/session`, username, password , authorizing: true );

// update axios to include the header for future requests
axios.defaults.headers.common['X-Token'] = result.data.token;

return config;
);


Two things that you'll want to note -- not only do I check for the existence of your X-token header I also check for a new authorization value in the config. You want to check for that config value, because we are going to use it as a flag to let the interceptor know if it should skip a request. If you don't do this, the authorization request will trigger another authorization request and infinite loop.






share|improve this answer

























  • Apologies for the somewhat late reply, and thank you for your response. I see how this is valuable, but I still don't see how I can run this authentication step synchronously so that I have the token set in the header before I make any other api calls. Maybe I am just being an idiot, but it would really help me out if you had some kind of example perhaps?

    – Dan M
    Nov 15 '18 at 16:04











  • Okay I get what you want to do, I updated my answer to provide that logic!

    – kyle
    Nov 15 '18 at 23:32










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53309514%2fasynchronously-authenticate-before-request%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














You can use async/await. This is semi-pseudocode:



async function doStuff() 
const result = await axios.authenticate();
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);



Alternatively, you can just use then:



function doStuff(token) 
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);


axios.authenticate().then(result =>
const token = // extract token from whatever format of result is
doStuff(token);






share|improve this answer























  • Ok, but this model is on a per request basis. I want to save the token, include it in the axios instance header, and then be able to make requests using that instance and not having to manually include the header every time

    – Dan M
    Nov 14 '18 at 22:19






  • 1





    One way to do this is to to use authenticate().then() chain on first request (or if token is not present), and skip it if token is present for subsequent requests.

    – ODYN-Kon
    Nov 14 '18 at 22:22











  • So for every API call I would need to have a built in conditional to check if the token is set before I make the request? Is there not a way to set the token once, assign it to an axios instance, and then import that instance into whatever files require it to make API calls?

    – Dan M
    Nov 15 '18 at 16:11











  • You can but you need to make sure that happens before your first call to get().

    – ODYN-Kon
    Nov 15 '18 at 16:16











  • Haha, yes! That is exactly what I want to do, I just don't know how!

    – Dan M
    Nov 15 '18 at 16:21















2














You can use async/await. This is semi-pseudocode:



async function doStuff() 
const result = await axios.authenticate();
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);



Alternatively, you can just use then:



function doStuff(token) 
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);


axios.authenticate().then(result =>
const token = // extract token from whatever format of result is
doStuff(token);






share|improve this answer























  • Ok, but this model is on a per request basis. I want to save the token, include it in the axios instance header, and then be able to make requests using that instance and not having to manually include the header every time

    – Dan M
    Nov 14 '18 at 22:19






  • 1





    One way to do this is to to use authenticate().then() chain on first request (or if token is not present), and skip it if token is present for subsequent requests.

    – ODYN-Kon
    Nov 14 '18 at 22:22











  • So for every API call I would need to have a built in conditional to check if the token is set before I make the request? Is there not a way to set the token once, assign it to an axios instance, and then import that instance into whatever files require it to make API calls?

    – Dan M
    Nov 15 '18 at 16:11











  • You can but you need to make sure that happens before your first call to get().

    – ODYN-Kon
    Nov 15 '18 at 16:16











  • Haha, yes! That is exactly what I want to do, I just don't know how!

    – Dan M
    Nov 15 '18 at 16:21













2












2








2







You can use async/await. This is semi-pseudocode:



async function doStuff() 
const result = await axios.authenticate();
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);



Alternatively, you can just use then:



function doStuff(token) 
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);


axios.authenticate().then(result =>
const token = // extract token from whatever format of result is
doStuff(token);






share|improve this answer













You can use async/await. This is semi-pseudocode:



async function doStuff() 
const result = await axios.authenticate();
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);



Alternatively, you can just use then:



function doStuff(token) 
const token = // extract token from whatever format of result is
const data = await axios.get(/* supply token to get */);


axios.authenticate().then(result =>
const token = // extract token from whatever format of result is
doStuff(token);







share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 14 '18 at 22:16









ODYN-KonODYN-Kon

2,3322825




2,3322825












  • Ok, but this model is on a per request basis. I want to save the token, include it in the axios instance header, and then be able to make requests using that instance and not having to manually include the header every time

    – Dan M
    Nov 14 '18 at 22:19






  • 1





    One way to do this is to to use authenticate().then() chain on first request (or if token is not present), and skip it if token is present for subsequent requests.

    – ODYN-Kon
    Nov 14 '18 at 22:22











  • So for every API call I would need to have a built in conditional to check if the token is set before I make the request? Is there not a way to set the token once, assign it to an axios instance, and then import that instance into whatever files require it to make API calls?

    – Dan M
    Nov 15 '18 at 16:11











  • You can but you need to make sure that happens before your first call to get().

    – ODYN-Kon
    Nov 15 '18 at 16:16











  • Haha, yes! That is exactly what I want to do, I just don't know how!

    – Dan M
    Nov 15 '18 at 16:21

















  • Ok, but this model is on a per request basis. I want to save the token, include it in the axios instance header, and then be able to make requests using that instance and not having to manually include the header every time

    – Dan M
    Nov 14 '18 at 22:19






  • 1





    One way to do this is to to use authenticate().then() chain on first request (or if token is not present), and skip it if token is present for subsequent requests.

    – ODYN-Kon
    Nov 14 '18 at 22:22











  • So for every API call I would need to have a built in conditional to check if the token is set before I make the request? Is there not a way to set the token once, assign it to an axios instance, and then import that instance into whatever files require it to make API calls?

    – Dan M
    Nov 15 '18 at 16:11











  • You can but you need to make sure that happens before your first call to get().

    – ODYN-Kon
    Nov 15 '18 at 16:16











  • Haha, yes! That is exactly what I want to do, I just don't know how!

    – Dan M
    Nov 15 '18 at 16:21
















Ok, but this model is on a per request basis. I want to save the token, include it in the axios instance header, and then be able to make requests using that instance and not having to manually include the header every time

– Dan M
Nov 14 '18 at 22:19





Ok, but this model is on a per request basis. I want to save the token, include it in the axios instance header, and then be able to make requests using that instance and not having to manually include the header every time

– Dan M
Nov 14 '18 at 22:19




1




1





One way to do this is to to use authenticate().then() chain on first request (or if token is not present), and skip it if token is present for subsequent requests.

– ODYN-Kon
Nov 14 '18 at 22:22





One way to do this is to to use authenticate().then() chain on first request (or if token is not present), and skip it if token is present for subsequent requests.

– ODYN-Kon
Nov 14 '18 at 22:22













So for every API call I would need to have a built in conditional to check if the token is set before I make the request? Is there not a way to set the token once, assign it to an axios instance, and then import that instance into whatever files require it to make API calls?

– Dan M
Nov 15 '18 at 16:11





So for every API call I would need to have a built in conditional to check if the token is set before I make the request? Is there not a way to set the token once, assign it to an axios instance, and then import that instance into whatever files require it to make API calls?

– Dan M
Nov 15 '18 at 16:11













You can but you need to make sure that happens before your first call to get().

– ODYN-Kon
Nov 15 '18 at 16:16





You can but you need to make sure that happens before your first call to get().

– ODYN-Kon
Nov 15 '18 at 16:16













Haha, yes! That is exactly what I want to do, I just don't know how!

– Dan M
Nov 15 '18 at 16:21





Haha, yes! That is exactly what I want to do, I just don't know how!

– Dan M
Nov 15 '18 at 16:21













2














With Axios you have the ability to set default values for all requests.



So for just a single axios instance you can do...



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance.defaults.headers.common['X-Token'] = result.data.token;



Alternatively, (which it sounds like you want to do) you can add it for the default Axios export. Then all requests will automatically have the header.



async function authenticate(endpoint, username, password) 
const res = await axios.post(`$endpoint/session`, username, password );
axios.defaults.headers.common['X-Token'] = result.data.token;



Then you don't have to worry about passing around an instance between all parts of your app and can just use import * as axios from 'axios' and have the header set.




Axios also provides and extremely helpful function called interceptors which you can use to inspect a request prior to making it. You can use to check to make sure that the request has the auth header and if it doesn't you can perform that logic. I came up with this and it seems to work well!



axios.interceptors.request.use(async (config) => 
// request intercepted, check (1) the header is missing and (2) that the intercepted request isn't authorizing
if (!config.headers.common['X-Token'] && config.authorizing !== true)
const endpoint, username, password = appConfig;

// make a request to get your token AND pass our custom config
const result = await axios.post(`$endpoint/session`, username, password , authorizing: true );

// update axios to include the header for future requests
axios.defaults.headers.common['X-Token'] = result.data.token;

return config;
);


Two things that you'll want to note -- not only do I check for the existence of your X-token header I also check for a new authorization value in the config. You want to check for that config value, because we are going to use it as a flag to let the interceptor know if it should skip a request. If you don't do this, the authorization request will trigger another authorization request and infinite loop.






share|improve this answer

























  • Apologies for the somewhat late reply, and thank you for your response. I see how this is valuable, but I still don't see how I can run this authentication step synchronously so that I have the token set in the header before I make any other api calls. Maybe I am just being an idiot, but it would really help me out if you had some kind of example perhaps?

    – Dan M
    Nov 15 '18 at 16:04











  • Okay I get what you want to do, I updated my answer to provide that logic!

    – kyle
    Nov 15 '18 at 23:32















2














With Axios you have the ability to set default values for all requests.



So for just a single axios instance you can do...



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance.defaults.headers.common['X-Token'] = result.data.token;



Alternatively, (which it sounds like you want to do) you can add it for the default Axios export. Then all requests will automatically have the header.



async function authenticate(endpoint, username, password) 
const res = await axios.post(`$endpoint/session`, username, password );
axios.defaults.headers.common['X-Token'] = result.data.token;



Then you don't have to worry about passing around an instance between all parts of your app and can just use import * as axios from 'axios' and have the header set.




Axios also provides and extremely helpful function called interceptors which you can use to inspect a request prior to making it. You can use to check to make sure that the request has the auth header and if it doesn't you can perform that logic. I came up with this and it seems to work well!



axios.interceptors.request.use(async (config) => 
// request intercepted, check (1) the header is missing and (2) that the intercepted request isn't authorizing
if (!config.headers.common['X-Token'] && config.authorizing !== true)
const endpoint, username, password = appConfig;

// make a request to get your token AND pass our custom config
const result = await axios.post(`$endpoint/session`, username, password , authorizing: true );

// update axios to include the header for future requests
axios.defaults.headers.common['X-Token'] = result.data.token;

return config;
);


Two things that you'll want to note -- not only do I check for the existence of your X-token header I also check for a new authorization value in the config. You want to check for that config value, because we are going to use it as a flag to let the interceptor know if it should skip a request. If you don't do this, the authorization request will trigger another authorization request and infinite loop.






share|improve this answer

























  • Apologies for the somewhat late reply, and thank you for your response. I see how this is valuable, but I still don't see how I can run this authentication step synchronously so that I have the token set in the header before I make any other api calls. Maybe I am just being an idiot, but it would really help me out if you had some kind of example perhaps?

    – Dan M
    Nov 15 '18 at 16:04











  • Okay I get what you want to do, I updated my answer to provide that logic!

    – kyle
    Nov 15 '18 at 23:32













2












2








2







With Axios you have the ability to set default values for all requests.



So for just a single axios instance you can do...



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance.defaults.headers.common['X-Token'] = result.data.token;



Alternatively, (which it sounds like you want to do) you can add it for the default Axios export. Then all requests will automatically have the header.



async function authenticate(endpoint, username, password) 
const res = await axios.post(`$endpoint/session`, username, password );
axios.defaults.headers.common['X-Token'] = result.data.token;



Then you don't have to worry about passing around an instance between all parts of your app and can just use import * as axios from 'axios' and have the header set.




Axios also provides and extremely helpful function called interceptors which you can use to inspect a request prior to making it. You can use to check to make sure that the request has the auth header and if it doesn't you can perform that logic. I came up with this and it seems to work well!



axios.interceptors.request.use(async (config) => 
// request intercepted, check (1) the header is missing and (2) that the intercepted request isn't authorizing
if (!config.headers.common['X-Token'] && config.authorizing !== true)
const endpoint, username, password = appConfig;

// make a request to get your token AND pass our custom config
const result = await axios.post(`$endpoint/session`, username, password , authorizing: true );

// update axios to include the header for future requests
axios.defaults.headers.common['X-Token'] = result.data.token;

return config;
);


Two things that you'll want to note -- not only do I check for the existence of your X-token header I also check for a new authorization value in the config. You want to check for that config value, because we are going to use it as a flag to let the interceptor know if it should skip a request. If you don't do this, the authorization request will trigger another authorization request and infinite loop.






share|improve this answer















With Axios you have the ability to set default values for all requests.



So for just a single axios instance you can do...



async function authenticate(instance) 
const result = await instance.post(
'/session',

'username': config.username,
'password': config.password

)
instance.defaults.headers.common['X-Token'] = result.data.token;



Alternatively, (which it sounds like you want to do) you can add it for the default Axios export. Then all requests will automatically have the header.



async function authenticate(endpoint, username, password) 
const res = await axios.post(`$endpoint/session`, username, password );
axios.defaults.headers.common['X-Token'] = result.data.token;



Then you don't have to worry about passing around an instance between all parts of your app and can just use import * as axios from 'axios' and have the header set.




Axios also provides and extremely helpful function called interceptors which you can use to inspect a request prior to making it. You can use to check to make sure that the request has the auth header and if it doesn't you can perform that logic. I came up with this and it seems to work well!



axios.interceptors.request.use(async (config) => 
// request intercepted, check (1) the header is missing and (2) that the intercepted request isn't authorizing
if (!config.headers.common['X-Token'] && config.authorizing !== true)
const endpoint, username, password = appConfig;

// make a request to get your token AND pass our custom config
const result = await axios.post(`$endpoint/session`, username, password , authorizing: true );

// update axios to include the header for future requests
axios.defaults.headers.common['X-Token'] = result.data.token;

return config;
);


Two things that you'll want to note -- not only do I check for the existence of your X-token header I also check for a new authorization value in the config. You want to check for that config value, because we are going to use it as a flag to let the interceptor know if it should skip a request. If you don't do this, the authorization request will trigger another authorization request and infinite loop.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 15 '18 at 23:32

























answered Nov 14 '18 at 22:28









kylekyle

1,11031127




1,11031127












  • Apologies for the somewhat late reply, and thank you for your response. I see how this is valuable, but I still don't see how I can run this authentication step synchronously so that I have the token set in the header before I make any other api calls. Maybe I am just being an idiot, but it would really help me out if you had some kind of example perhaps?

    – Dan M
    Nov 15 '18 at 16:04











  • Okay I get what you want to do, I updated my answer to provide that logic!

    – kyle
    Nov 15 '18 at 23:32

















  • Apologies for the somewhat late reply, and thank you for your response. I see how this is valuable, but I still don't see how I can run this authentication step synchronously so that I have the token set in the header before I make any other api calls. Maybe I am just being an idiot, but it would really help me out if you had some kind of example perhaps?

    – Dan M
    Nov 15 '18 at 16:04











  • Okay I get what you want to do, I updated my answer to provide that logic!

    – kyle
    Nov 15 '18 at 23:32
















Apologies for the somewhat late reply, and thank you for your response. I see how this is valuable, but I still don't see how I can run this authentication step synchronously so that I have the token set in the header before I make any other api calls. Maybe I am just being an idiot, but it would really help me out if you had some kind of example perhaps?

– Dan M
Nov 15 '18 at 16:04





Apologies for the somewhat late reply, and thank you for your response. I see how this is valuable, but I still don't see how I can run this authentication step synchronously so that I have the token set in the header before I make any other api calls. Maybe I am just being an idiot, but it would really help me out if you had some kind of example perhaps?

– Dan M
Nov 15 '18 at 16:04













Okay I get what you want to do, I updated my answer to provide that logic!

– kyle
Nov 15 '18 at 23:32





Okay I get what you want to do, I updated my answer to provide that logic!

– kyle
Nov 15 '18 at 23:32

















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53309514%2fasynchronously-authenticate-before-request%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Top Tejano songwriter Luis Silva dead of heart attack at 64

ReactJS Fetched API data displays live - need Data displayed static

政党