React SPA: Pass Authorization Header to fetch api call - reactjs

I have a React single page application running on a nginx-webserver. The Nginx is configured that accessing my application the first time after the browser was started the user gets the browser basic auth login window (auth_basic setting in the location-part of the nginx config file). The user enters name and password and another request to the server gets send including the authorization header. So far so good.
Now in my react application i want to call different REST-Apis via fetch api:
fetch("URL", {
method: "POST",
credentials: 'include',
headers: new Headers({
// 'Authorization': "THIS SHOULD BE SET SOMEHOW",
}),
body: "SOME_DATA"
}).then((response: any) => {
...
})
How can I access the existing authorization header from the initial page call after the user has logged in to use it in my REST-Api call?

When the user logs in(The user enters name and password and another request to the server gets send including the authorization header) the first time you should store the Authorization token in either LocalStorage, SessionStorage and get the token from there and set it to Heders.
Clean approach: You can create a Helper Class/Function(interceptor). that will take care of adding a header and common things.
// Something like this Not 100% perfect
class HttpService {
_getHeaders(){
// Logic to get header from Storage
return {'Authorization': "THIS SHOULD BE SET SOMEHOW"};
}
_apiHandler(url, options){
return fetch(url, {
headers: new Headers({
...this._getHeaders(),
}),
...options,
});
}
post(){
return this._apiHandler("URL", {
method: "POST",
credentials: 'include',
body: "SOME_DATA"
});
}
}
OR
Recommended:
Ask the backend team to send tokens in the cookies, You don't have to do anything browser will take care of that. Only same domain request
NOTE: you could share a cookie between foo.example.com and bar.example.com but never between example.com and example2.com and that's for security reasons.

Related

Client does not receive cookies from server, postman does

There is a server, which serves my client react app at root path. So when I make any request to server from POSTMAN, to login for example, cookies are attached perfect. But when I make request from my client using AXIOS and withCredentials field as well, cookies ain't attached, nevertheless the request is sent good, but no cookies received. I don't think there is any reason to search issues in server code, because postman works with it perfect. In case, there is no CORS errors: server provides client app. I get nice response from the server, with no cookies. Postman gets them.
axios request in react app:
export const login = createAsyncThunk(
'auth/login',
async (credentials: ILogin) => {
// todo: making a request to server
const response = await axios({
url: '/api' + '/auth' + '/login',
method: 'POST',
data: credentials,
withCredentials: true,
headers: {
'Content-Type': 'application/json'
},
});
console.log(response)
}
)
Client doesn't receive cookies, neither on localhost nor deployed app.
As you see, only place where cookies are shown it's network section in devtools, but everything else, including server acts like my second request hadn't any cookie, because in this case, server would answer like: agh, already logged in
P.S: i'm using http

Understanding Next.JS with-iron-sessions requirements for use in own environment

I am trying to get some of the examples located in the with-ireon-sessions github account to work with my own back-end: https://github.com/vercel/next.js/tree/canary/examples/with-iron-session
I can sign in using const { user, mutateUser } = useUser(); with useUser() being from the example: https://github.com/vercel/next.js/blob/canary/examples/with-iron-session/lib/useUser.js
My sign-in method looks like this;
const signIn = async ({ email, password, remember_me }) => {
try {
await mutateUser(
fetchJson(`${API.baseURL}/${API.signIn}`, {
method: "POST",
headers: {
"Accept": 'application/json',
"Content-Type": "application/json"
},
body: JSON.stringify({
email,
password
})
})
);
} catch (error) {
console.error("An unexpected error happened:", error);
setErrorMessage((<p className="error">{error.data.message}</p>));
}
};
I can see my user change, but I still have the following issues:
I don't see any cookies get created. Does with-iron-sessions require the site to be deployed to the vercel cloud in order for cookies to get added, or am I right in thinking I can use my own server and API endpoints?
What's the pattern for using the /api/user endpoint in useUser.js; does the endpoint look for the cookies (that are not getting created for me) and do it's own validation, or is there validation I need to do in my version of that endpoint? Is there an example of what that endpoint looks like server-side you might be able to point me to?
Is there a way to refresh the cookie (once I get them to appear) so they are X days since last using the site instead of X days from first login so it's a sliding cookie lifespan, or does that happen automatically?
When I sign out my sign_out endpoint returns a 204 status code but the UI doesn't change like it does when I sign in. Any tips for me there?
Thank you!

How to store JWT token in cookie React fetch

I am getting token from fetch method in React while I am sending appropriate credentials, but I don't know how to store JWT token in cookie, and later reused it. Below is code block:
fetch('http://localhost:5000/api/authenticate/login', {
method: 'POST',
headers: {'Content-type': 'application/json'},
body: JSON.stringify(loginInfo),
}).then(function (response) {
return response.json();
}).then(function (json) {
alert(json.token);
}).catch(function (ex) {
console.log("parsing failed", ex);
});
Rather than storing token in your browser, you should think about how to secure your connection properly.
If that's not the issue, you can store it in cookies or localStorage for what you will find plenty of tutorials on google. (I like this "hooks approach" in react)
But to use JWT token properly you should store send it in response as the HttpOnly cookie. See those implementations or nodeJS implementation
And the browser should attach the token on every new request on it's own. See here
To store a cookie in the browser use
document.cookie=`${cookieName}=${cookieValue};${cookieOptions}`
See specs here.
If you want to set the cookie from the server, use the set-cookie header, see here

React - fetching from API, how to skip the cors response

I want to make a simple POST request from my React app to my Spring back-end to authenticate the user. What i am doing :
fetch('http://localhost:8080/login', {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
username: this.state.username,
password: this.state.password,
}),
})
.then(response => response.json()).then(resposne => console.log(resposne))
Trying to make this call will get me a SyntaxError: Unexpected end of JSON input. If i log the response i can see that it is a response with a type:cors. I assume i am getting the response from the OPTIONS request that goes out. How can i skip that response? If i check the headers on the response, the header that i want to get, which is the Authorization header, is non-existant. If i go to chrome devtools - network section, and look at the response i am getting, i can see the resposne is as it should be, and i can even see the token returned in the Authorization header. How can i access that header in my React app? Server is properly configured since it returns the token, i just cant get it in the React app.
Thanks!
You should add the Access Control Expose Headers with the Authorization header like so:
Access-Control-Expose-Headers: Authorization
It doesn't seems an error on the token generation. Did you take a look on Response body?
Seems like the response body is not a valid json.

Is Excel clearing our http request authorization header attribute?

We are trying to get our Office Excel add-in to contact one of our own Web API services so it can send and receive data from it. For the request to be authorised we must fill out the Authorization header attribute. This is how we are doing the request, which works perfectly well in all of our normal web applications.
this.LoginAuth = function (authString) {
$http.defaults.headers.common.Authorization = 'Basic ' + authString;
return $http({
url: MainFactory.GetWebAPILocation() + '/API/User/AddInLoginAuth',
dataType: 'json',
method: 'POST',
data: {},
headers: {
"Content-Type": "application/json"
}
});
}
However, when the request is made through the add-in the Authorization attribute has been cleared down causing our request to fail. Is this clearing of the attribute being done by Excel? And if so, is there a way in which we can stop it?
Turns out this was a CORS issue in our Web API service.

Resources