How to store JWT token in cookie React fetch - reactjs

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

Related

React SPA: Pass Authorization Header to fetch api call

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.

Axios post fails with 403 error code and showing CSRF token validation failed but works fine django api when passing csrftoken in header with Postman

I am tring to send csrf token by using axios post in react js but csrf token validation is failing. I am also done with credentials:true
but it's not working.I am receving csrf token in cookie but not able to send it.
class LoginService extends Component {
loginUser(formData)
{
const config = {
headers: { 'content-type': 'application/json',
'X-CSRFToken': Cookies.get("csrftoken")}
}
return axios.post(`${API_BASE_URL}api/user/v1/account/login_session/`,formData,config);
}
}
If you are using httpsOnly cookies then 'X-CSRFToken': Cookies.get("csrftoken")} will not work.
What is HttpOnly?
According to the Microsoft Developer Network,
HttpOnly is an additional flag included in a Set-Cookie HTTP response
header. Using the HttpOnly flag when generating a cookie helps
mitigate the risk of client side script accessing the protected cookie
(if the browser supports it).
Using withCredentials: true should suffice.
loginUser(formData)
{
const config = {
headers: { 'content-type': 'application/json' },
withCredentials: true
}
return axios.post(`${API_BASE_URL}api/user/v1/account/login_session/`,formData,config);
}
}
withCredentials indicates whether or not cross-site Access-Control
requests should be made using credentials
withCredentials: false,
// default
Of course you also need to ensure the cookie domain is set correctly in order for the cookie to work.
Tip: Check your chrome network inspector, and see whether the desire cookie is sent together with your request
CSRF with HttpOnly
If you are setting csrf cookie with httpOnly you can remove httpOnly.
There's an answer with regards to this here https://security.stackexchange.com/a/175540/135413
When you send the header in Axios to the server, you need to know if your server-side accepts the patterns: CSRF-TOKEN or X-CSRF-TOKEN or XSRF-TOKEN or X-XSRF-TOKEN.
You are using X-CSRFToken, that not combine with any patterns shown above.
More here: https://www.npmjs.com/package/csurf
**This is how I solve my problem :
first set these two as:-
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
**
loginUser(formData)
{
const config = {
headers: { 'content-type': 'application/json'},
"X-CSRFToken": Cookies.get('csrftoken'),
withCredentials: true
}
return axios.post(`${API_BASE_URL}api/user/v1/account/login_session/`,formData,config);
}
}

React and Axios get AWS client credentials

I'm using latest version of react with axios and want to get an authentication token from aws / cognito. Therefore I have my client and client secret. When I send a curl request, it works as expected, but when I send the request via axios, I always get a status 405 response.
My code looks as follows:
...
axios({
url: 'https://xyz.amazoncognito.com/oauth2/token?grant_type=client_credentials',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'client_id': '***************',
'client_secret': '****************'
'redirect_uri': 'http://localhost:4200'
}
})
.then((response) => {
console.log(response);
}, (error) => {
console.log(error);
});
Instead of setting client_id, client_secret and redirect_uri to the headers, I added them in the url like
...grant_type=client_credentials&client_id=************&client_secret=*************&redirect_uri=http%3A%2F%2Flocalhost%3A4200
with the same result. Any ideas, what I'm doing wrong? As a side remark: I'm using axios for all my api requests and so I would like to stay at axios also in this case.
Thanks and kind regards,
Balu
You are not passing the required parameters correctly. Have a look at the example here:
https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html
The required headers will be:
Authorization
If the client was issued a secret, the client must pass its client_id and client_secret in the authorization header through Basic HTTP authorization. The secret is Basic Base64Encode(client_id:client_secret).
Content-Type
Must always be 'application/x-www-form-urlencoded'.
The other information will be passed as request parameters.
This being said, you should not store your client and client secret on the client side (React application). If this is exposed on the client, anyone can get your client ID and Client secret and obtain a Cognito Token.

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.

Angular $http post with custom headers

I am new to angular and am from .net framework. I need to post a angular request to .net service, where it expects two custom headers from the client.
angular post command:
var request = $http(
{
url: "http://localhost:53585/api/myService/Validate",
method: "POST",
data: JSON.stringify(payload),
headers: { 'first_token': sessionService.first_token, 'second_token': sessionService.second_token }
});
But in the service side, I can see only first_token in the request header and not the second token. What I am missing here?
Issue is with my service. I figured out and restarted the IIS and then service was able to read both the headers token
I found this method in a forum, it works.
return this.http.post<any>('https://yourendpoint', { username, password }, { headers: new HttpHeaders().set('Authorizaion', 'your token')})
.pipe(map(user => {
// login successful if there's a jwt token in the response
if (user && user.token) {
// sto`enter code here`re user details and jwt token in local storage to keep user logged in between page refreshes
localStorage.setItem('currentUser', JSON.stringify(user));
}
console.log(user);
return user;

Resources