I have Laravel Passport implemented in my project and it is everything working well except the cookie expiration time where the tokens are being stored (that is just 1 hour).
My project consists in a backend Laravel 5.8 api (with Laravel Passport) that serves a front SPA app (Vue).
Users from my app can login successfully using a page with a Vue component that makes a POST request with the user credentials and, if the login is successfully done, users are redirected to a new URL (app home) - this redirection is a GET request that creates the "laravel_token" cookie - created by the CreateFreshApiToken middleware.
From now on, users can go everywhere inside the app and all data needed from the app components' is obtained through ajax calls (Laravel will note the presence of the cookie "laravel_token" in these ajax calls and will identify the logged in user using the JWT present in that cookie).
My problem is:
The "laravel_token" cookie that was created when user logged in was created with a lifetime of just 1 hour. Because this is a SPA, this cookie never gets updated (exchanged by a new one, with a new hour lifetime)... so, after 1 hour, when a new ajax request needs to be done to the backend Laravel server, it will receive an Unauthenticated response - that makes sense because "laravel_token" cookie is outdated.
How do you deal with this problem?
I know that i can refresh this cookie by perfoming a full refresh/reload of the page before this cookie expire but this is not a good solution in terms of user experience.
I can't make an ajax call to refresh this cookie because this is a SPA and i don't have the client_id and it's secret from client side... and also because not only this cookie is httponly but also it is encrypted by Laravel - so, i can't exchange it by a new one using JS.
Is the only solution increase the lifetime of this cookie (from 1 hour to.... 1 year, for example)? Do you see any problem with this? And where can i set this cookie expiration time? Does i need to extend the ApiTokenCookieFactory class?
I would like user to be logged in until he deliberately performs a logout request or the access_token expires (that, in my case that i am using Laravel Passport defaults, is a long-lived token of 1 year).
I would appreciate if someone could help me with this problem.
If you see something that i am not doing the correct way, i also would appreciate your comments with suggestions.
Thank you very much!
According to ApiTokenCookieFactory an expiration time of laravel_token cookie is getting from session lifetime value.
Well, just change value of SESSION_LIFETIME in .env
Related
I am trying to create a restricted area where logged in users would need to input a code to access it.
I'm using laravel sanctum and nuxt(ssr) with nuxt-auth module. I'm trying to understand how nuxt-auth module is checking the backend if a user is logged in or not so I can replicate this in my own restricted area access.
So far I noticed that if I invalidate the user session on the backend (FLUSHALL redis sessions) when I refresh the frontend, somehow nuxt-auth knows that the user is logged out and logs the user out on frontend too.
Same if I remove the /api/user route, nuxt thinks that the user is logged out. But when the route is active I don't see the route being accessed in the dev network tab.
I am new to nuxt and I cannot understand where in the nuxt-module source code is it doing the backend check. Is it in the middleware or storage? I'm confused.
So far in the backend I'm checking the user code and save an ID in the session similar with a user log in situation. Now I'm trying to make a nuxt middleware that would verify this.
Nuxt-auth will store a JWT token in cookies usually (it depends on which configuration you're doing of course!) and all of this is checked by reaching your backend's route.
If you refresh your SPA and flush the DB or break the route, the module wipes the client storage + set the loggedIn state to false.
Usually, you do have a JWT token for a specific amount of time (maybe 1 hour or so), if it is not expired, you will not get any network request. If you delete the JWT token, you should see a network request.
Otherwise, a global auth middleware is also available, out of the box with the module. But you could add another global one if you want to have something homemade.
I am trying to understand how an auth in a spa context with a jwt token should be implemented based on a Register / Login / Logout process. I have been searching on the web and have implemented at laravel side tymon jwt but I am confused about next step regarding register form and login form.
Do I understand well that when my user register for the first time on my website, this is at this time that the JWT token should be generated and recorded in a cookie ? If yes, is it Vue or Laravel which should record the JWT token in a cookie ? I suppose Vue ?! If yes, in which manner?
Other question: what happen if the user clear the browser cache and eliminate the cookie containing the JWT form his computer ? Does he need to register again to get a a new token ?? I am totally confused about the process.
Getting a more detailed and step by step process would help.
Thanks
The rough sketch for a JWT authentication works like this:
Registration - (optional | If the user is not registered) User fills the registration form which is posted to the register route, User account is created and the api responds with 201 ( content created)
Login - User uses his credentials to login to the app. The credentials are verified and a JWT token is issued and sent back to the user.
Vue handles the JWT Token and stores the provided token into cookies ( you can use js-cookie to handle this, usually in Vuex state )
The token is used with every request sent forth to the server, server verifies the Token and then the request proceeds.
Logging out requests the server to invalidate the token and then removes the token from the cookies.
You can use laravel passport, Laravel Sanctum or tymon/Jwt for token management.
I have been playing for a couple of days with a stateless Laravel API with JWT based authentication, where I store the token in a cookie.
All is well, except for the cookie (in)validation...
I set my cookie like so
Cookie::queue(Cookies::NAME, $token, (int) env('COOKIE_VALIDITY'), Cookies::PATH, env('COOKIE_DOMAIN'), env('COOKIE_SECURE'), Cookies::HTTPONLY, Cookies::RAW, Cookies::SAMESITE);
$redirectUrl = $request->query('redirectTo') ?? route('home');
return redirect($redirectUrl);
This works, it does set the cookie.
However, my cookie Expires/Max-Age seems to be one hour behind, always.
2019-10-12T08:51:35.737Z (when it is actually 9:51)
The cookies gets sent correctly on all subsequent requests though.
The biggest problem however, is cookie invalidation.
My logout action looks like this
return redirect('/login')->withCookies([Cookie::forget(Cookies::NAME)]);
The action gets called to, but the cookie remains unchanged.
I also tried with the cookie()->forget() helper, this has the same result.
Any clues to what I am doing wrong here?
Ps: I do see that laravel by default adds a session cookie as well, I suppose this is normal, due to the fact that I reach the site as an anonymous user and therefor receive a session for that?
Im asking because the challange for me is to have a full stateless API that only uses server side rendered login page and then redirects back to some kind of SPA.
All help is much appreciated.
To whom it may concern, I have found the problem.
Apparently, specifying the cookie name is not sufficient.
return redirect('/login')->withCookies([Cookie::forget(Cookies::NAME, Cookies::PATH, env('COOKIE_DOMAIN'))]);
Works perfectly.
I am working on Laravel 4 application and using Sentry for authentication. I need to add Keep Me Logged In functionality into my application. I have googled around and found that passing second variable to Sentry::login($user, $remember) sets up a cookie. I have done that and can verify that it is working from the browser (Chrome). But somehow whenever I try Sentry::check() after a day it returns null for cookies. Even when the cookie is present in the browser. Can anyone point out what am I doing wrong? Same happens when I attach my custom cookie to the response.
This scenario happens on my production server. Whereas it works fine on my local server.
PS: Lifetime of the cookie is set to forever (5 Years)
After working around for sometime on the issue I was finally able to resolve the issue by creating and attaching custom cookie to the response after login. And then wrote a middleware to check for that cookie. If present then login user and continue.
I know that to protect web applications from Cross Site Request Forgery, the only secure method is implementing a CSRF token. My question is, isn't it possible to use the CSRF token to track sessions also? Why should we implement a different session id to track the sessions?
A CSRF token is a value that must be generated randomly and associated to a session (a user) in EVERY GET that shows a form to prevent false POST. This false POST comes from the user browser too so, to authenticate the POST, you need a session with the token stored in server memory to compare if the token that comes with the POST is the same that is stored in user session.
Also, web app's shuold need to identify users in a GET and CSRF tokens are only in POST.
Session need to be static to identify user along time and several request due to disconnected nature of HTTP. CSRF changes in every GET, it can not be used like session.
In the other hand. What server should do with your idea? Create a new session every GET and copy all previous session data to the new session? This is crazy.
Take a look to this pdf at Montana State University. It helps me to understand CSRF.