I'm trying to implement markitosgv/JWTRefreshTokenBundle
in my symfony project in order to get a way to refresh my JWT token.
For this, I want to generate an HttpOnly cookie, which is something supported by the bundle.
When I log in from my frontend (angular 13), I get my JWT token (from lexik/LexikJWTAuthenticationBundle
) , as well as set-cookie
header like this:
Request URL: https://api.mysite.com/api/login_check
Request Method: POST
Status Code: 200 OK
Remote Address: 192.168.1.43:443
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://front.mysite.com:4200
Access-Control-Expose-Headers: link
Cache-Control: no-cache, private
Connection: Keep-Alive
Content-Type: application/json
Date: Mon, 25 Apr 2022 15:54:30 GMT
Keep-Alive: timeout=5, max=99
Server: Apache/2.4.41 (Ubuntu)
Set-Cookie: refresh_token=a2615d6dd2986680fd79807c61d050424b4e290090a4beaf1f1063c0c8f1807681d86c1c07216630a629667e711897dbae7a6083884d3f19b028aa72f9bbca84; expires=Tue, 26-Apr-2022 09:07:50 GMT; Max-Age=62000; path=/; domain=mysite.com; secure; httponly; samesite=lax
Transfer-Encoding: chunked
X-Debug-Token: e31102
X-Debug-Token-Link: https://api.mysite.com/_profiler/e31102
X-Robots-Tag: noindex
Of course, I cannot check if the cookie has been created or not, since it's HttpOnly
then in my angular, I have a test button with the following simple code:
onCallRefreshToken() {
this.http.post('https://api.mysite.com/api/token/refresh', {site:2}, {withCredentials: true}).subscribe((datas) =>{
console.log('datas', datas);
});
}
and when I run it, I get the following error: [401] Missing JWT Refresh Token
If dump the request inside sympfony, I see that $request->cookies->parameters
is empty. And when I look at the sent request from Chrome inspector, I see the following:
Request URL: https://api.mysite.com/api/token/refresh
Request Method: POST
Status Code: 401 Unauthorized
Remote Address: 192.168.1.43:443
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://front.mysite.com:4200
Access-Control-Expose-Headers: link
Cache-Control: no-cache, private
Connection: Keep-Alive
Content-Type: application/json
Date: Mon, 25 Apr 2022 16:00:44 GMT
Keep-Alive: timeout=5, max=100
Server: Apache/2.4.41 (Ubuntu)
Transfer-Encoding: chunked
Vary: Authorization
X-Debug-Token: 54c0bb
X-Debug-Token-Link: https://api.mysite.com/_profiler/54c0bb
X-Robots-Tag: noindex
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
Authorization: Bearer AVeryLongAndValidTokenHere
Connection: keep-alive
Content-Length: 10
Content-Type: application/json
Host: api.mysite.com
Origin: https://front.mysite.com:4200
Referer: https://front.mysite.com:4200/
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36
(JWT token removed on purprose) So as you can see, th cookie doesn't seem to be passed in the request, which would obviously explain why I don't get it in my symfony API.
So from what I read, the way to "configure" the angular http call in order to pass the HttpOnly cookie was by setting options to "withCredentials" to true. But it doesn't seem to work.
Note that I don't seem to have any CORS issue (same domain, secure, allow-credential to true
) and HTTPS is working fine
Is there something I am doing wrong? DO you have any idea? Am I not calling the API the right way?
EDIT: Here's my bundle config concerning the cookie:
gesdinet_jwt_refresh_token:
# ...
ttl: 62000
return_expiration: true
cookie:
enabled: true
same_site: lax
path: /
domain: mysite.com
http_only: true
secure: true
remove_token_from_body: true
CodePudding user response:
Ok so the reason why my refresh token wasn't passed when requesting /api/token/refresh
was because you need to use withCredentials: true
in the "refresh" request itself, but also when calling the initial "login" route!
Using this option only on the "refresh" route is not enough to make it works