I'm using a django backend, and a CRAO frontend. I saved the jwt refresh token as a httponly cookie:
document.cookie = `refresh=${refresh_token}; SameSite=Strict; Path=/api/token/refresh; HttpOnly`;
Then to refresh the access token, I'm sending an axios request:
const response = await axios.post('/api/token/refresh/', { withCredentials: true });
But, in this case, the originally saved cookies don't get sent by axios. However, on removing the httponly attribute, the cookies do get sent, and everything works fine.
You did not set the cookie well in your django app. follow up this way to save it as httponly cookie:
response.set_cookie(
key=settings.SIMPLE_JWT["AUTH_COOKIE_REFRESH"],
value=token["refresh"],
expires=settings.SIMPLE_JWT["ACCESS_TOKEN_LIFETIME"],
secure=settings.SIMPLE_JWT["AUTH_COOKIE_SECURE"],
httponly=settings.SIMPLE_JWT["AUTH_COOKIE_HTTP_ONLY"],
samesite=settings.SIMPLE_JWT["AUTH_COOKIE_SAMESITE"],
)
Related
I have app on domain.com and sub.domain.com. Both apps set cookie with name X-XSRF-TOKEN but with different domain value.
I use this settings for Axios, so Axios take token from cookies and set it to headers:
axios.defaults.xsrfCookieName = "XSRF-TOKEN"
axios.defaults.xsrfHeaderName = "X-XSRF-TOKEN"
My app on subdomain send X-XSRF-TOKEN header from cookie taken from main domain (because it returned first when axios looking for XSRF-TOKEN cookie). How to deal with this ?
How to tell Axios take cookie from current domain ?
Like to ask a CORS cookie question again, I have spent quite some time on this but cannot resolve it.
Here is the situation.
I got a Backend api in nodejs(http://localhost:5000), and a React Frontend app(http://localhost:3000).
In Backend side, Cors setting is like this.
private initializeCors(){
this.app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:3000");
res.header("Access-Control-Allow-Headers", "Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", "true");
next();
});
}
I have set { credentials: "include" } in Fetch Api when login with username/password.
Set-Cookie has been set in response and I can see it saved in browser.
Cookie is with the format "Authorize=TOKEN;HttpOnly;Max-Age=3600;"
Cookie in browser
Then when route to another url and it cannot retrieve data from Backend with 401 exception.
Here is the code of the sequence call.
const credentialsInclude : "include" | "omit" | "same-origin" | undefined = "include";
function getAllPayments() {
const requestOptions = {
method: 'GET',
credentials: credentialsInclude
};
return fetch(apiUrls.GET_ALL_PAYMENTS, requestOptions).then(handleResponse);
}
I can see the cookie not added into header.
No cookie in header
I have followed the best answer of here, but cannot get it work.
Any suggestions? Thanks.
I have just figured out. The issue was not caused by the CORS settings. It caused by the Cookie itself.
For my case, I need to add Path=/; into Set-Cookie in response headers. So that the cookie from response could be added to sequenced requests after successful login.
The HTTP_X_CSRFTOKEN header does not match what is inside the csrftoken cookie.
How can I examine the cookie? Set-Cookie is not displayed in the Response header for Cross Domain requests.
I have already followed instructions found in:
CSRF with Django, React+Redux using Axios
Interestingly I found "X-CSRFTOKEN" translates to "HTTP_X_CSRFTOKEN" on the server request header.
Works fine in the development env under localhost (although I am using 2 different ports - one for django and the other my frontend).
UPDATE:
It seems the csrktoken cookie is not correctly set for cross domain rquests (although the browser displays it in the Request Header) so the X-CSRFTOKEN does not get sent.
I ended up adding an API call to return the current csrftoken using a GET request and then sending it back using the X-CSRFTOKEN header.
You haven't mentioned how you're getting the csrftoken from the server in the first place, so I'm assuming it's already present in your browser.
Along with the X-CSRFToken header, also include the cookies in the request using withCredentials: true.
I'm using the js-cookie library to get the csrftoken from the cookies.
import Cookies from 'js-cookie';
axios({
url: 'http://localhost:8000/graphql',
method: 'post',
withCredentials: true,
data: {
query: `
{
// Your query here
}
`
},
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
}
})
Also add CORS_ALLOW_CREDENTIALS = True to your settings.py, assuming you are using django-cors-headers. Otherwise, the cookies won't be accepted.
You will have to make the X-CSRFTOKEN header accessible via the CORS Access-Control-Expose-Headers directive. Example:
Access-Control-Expose-Headers: X-CSRFTOKEN
This header has to be set by your API or web server, so that the browser will see it during the CORS preflight request.
I'm attempting to retrieve an authentication cookie from a POST sign-in request. When I send this request using Postman, I see the cookie's value in the Cookies tab of the response in Postman.
Postman Response Cookies
My current Lua script is as follows:
local signInUrl = webBaseUrl.."/signin"
local signInResponse = http.request({"POST", signInUrl, headers={
["Content-Type"]="application/x-www-form-urlencoded",
["Referer"] = baseUrl}, data="UrlHash=&UserName="..username.."&Password=123&RememberMe=false", auto_decompress=true})
for i,v in pairs(signInResponse.cookies) do print(i,v) end
Printing out the value of the cookies returns a sessionId cookie and a return email cookie, but not the authentication cookie that I'm looking for.
I can see that the authentication cookie that I'm looking for is actually located in the Request Headers, in the Postman Console.
Postman Console
How would I go about getting the value of this cookie?
I used requests to send request.
import requests
def print(req):
print('{}\n{}\n{}\n\n{}'.format(
'-----------START-----------',
req.method + ' ' + req.url,
'\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
req.body,
))
print "----------END------------"
try:
req = requests.Request('GET',
'https://myip/myproject/upload/token',
headers={'Authorization': 'Token 401f7ac837a',
})
prepared = req.prepare()
print(prepared)
except Exception as e:
print "Exception:", e
Output:
-----------START-----------
GET https://myip/myproject/upload/token
Authorization: Token 401f7ac837a
None
----------END------------
But after I printed the request.META, there is
META:{u'CSRF_COOKIE': u'YGzoMaNEQJz1Kg8yXAwjJt6yNuT9L'
What set the CSRF_COOKIE?
Any comments welcomed. Thanks
UPDATE
(1)
From the doc, it said This cookie is set by CsrfViewMiddleware, which means the CSRF cookie was set in back-end and set to front-end in the response (CSRF cookie: server -> browser). Why it also said For all incoming requests that are not using HTTP GET, HEAD, OPTIONS or TRACE, a CSRF cookie must be present? And why it appears in my request.META? (CSRF cookie: browser -> server ???)
(2)
It said **A hidden form field with the name ‘csrfmiddlewaretoken’ present in all outgoing POST forms. The value of this field is the value of the CSRF cookie.
This part is done by the template tag.
**
When and How the template tag do it?
This is a standard cookie Django applications spin up for each new user to prevent Cross Site Forgery.
A CSRF cookie that is set to a random value (a session independent
nonce, as it is called), which other sites will not have access to.
This cookie is set by CsrfViewMiddleware. It is meant to be permanent,
but since there is no way to set a cookie that never expires, it is
sent with every response that has called
django.middleware.csrf.get_token() (the function used internally to
retrieve the CSRF token).
For security reasons, the value of the CSRF cookie is changed each
time a user logs in.
for more reading
https://docs.djangoproject.com/en/1.9/ref/csrf/#how-it-works