i'm using Larave 5.4 passport to create SPA application. However, i was able to make authentication work. but access token are always short-lived tokens with 600s expiration time.
i could not increase expiration time with:
Passport::tokensExpireIn(Carbon::now()->addDays(15));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(30));
it have no effect at all.
any help? thanks in advance.
Personal access tokens are always long-lived. Their lifetime is not modified when using the tokensExpireIn or refreshTokensExpireIn methods - as explained in Laravel's official documentation (https://laravel.com/docs/5.7/passport#personal-access-tokens).
The option of editing PassportServiceProvider.php in the vendor directory is a bad idea. Every time, you make an update (e.g composer update/install) or by another developer in production, code will be reverted to status quo, and it would start failing.
A better approach is to use Password Grant Tokens. The OAuth2 password grant allows your other first-party clients, such as a mobile application, to obtain an access token using an e-mail address / username and password. This allows you to issue access tokens securely to your first-party clients without requiring your users to go through the entire OAuth2 authorization code redirect flow. Be sure that you have duly installed passport (See Guide: https://laravel.com/docs/5.7/passport#installation), then run this command
php artisan passport:client --password
Having done this, you can request an access token by issuing a POST request to /oauth/token. Remember, this route is already registered by the Passport::routes method so there is no need to define it manually. If the request is successful, you will receive an access_token and refresh_token in the JSON response from the server. See payload sample below:
{
"grant_type" : "password",
"client_id":"your-client-id",
"client_secret":"your-client-secret",
"username":"twady77#gmail.com",
"password":"123456",
"scope":""
}
Sample response:
{
"token_type":"Bearer",
"expires_in":1296000,
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IjVkMWJjN2NhOTU0ZWU2YTZmOGNkMGEyOTFjOTI5YzU4Zjk3ODk3M2YxZDJmNjQ2NjkyZjhjODQyZjYxNTBjZGRiYzMwY2RjMzRmZjJhYmU1In0.eyJhdWQiOiI4IiwianRpIjoiNWQxYmM3Y2E5NTRlZTZhNmY4Y2QwYTI5MWM5MjljNThmOTc4OTczZjFkMmY2NDY2OTJmOGM4NDJmNjE1MGNkZGJjMzBjZGMzNGZmMmFiZTUiLCJpYXQiOjE1NDkyOTI5MjcsIm5iZiI6MTU0OTI5MjkyNywiZXhwIjoxNTUwNTg4OTI3LCJzdWIiOiIxIiwic2NvcGVzIjpbXX0.cSvu30xAT-boA5zmVuxTr0TfH_5MYuVWYi6NVQRbryZSswt8EAFTi5QXHH1f0O63DWnLA6VFBS2AfDe4-ryJZACDnt4gtPJOeuu1rNMZ53MU1vjxnyC8FsYz8v9vmYJsZPKqfTJpuJFYRFh7kkV7uWAmrEkuF3POnDn-GjW50f4i26lIZW5ta5j4nZQrIJCQUEzwXaQtn9H-qef3bTWAaplWaV-k7Blic-0TXXVfWa_CdoKCAzHROVBRWY1Idhe1LJkvGKldUGzUfliiB1x7EVVInq94VYEP5d9__90Z2UMUn5dCEgWkXvcEHYy87_4OSwu4TQk_f3hD82OVOEtJGgPyJqK51WqnQCBYwNtxNjqAW2oaMgpritp3G8nccUiyhkE4Pd_kj3cb2OvSNRXdDS9z-RnJb1OXUkja-4Xe_JfIWUjlTnkss18xMg89hcU_3xtBwUXBWHgffzcbNoI1oOwUL6Whekduiy8csf665v0cnzkPXISmvyGhiMseIlBEN9m9uESaJqD_g7WzbsEs7meI0CAF3230UgrI1MdYSAJMW0mMPF9EScH31a_Qpde5O233Ty6-S4NAp323Wneqs_jpGSfw81CvoI1JeY0hZccRC-MBBsQ2Ox7AM36H5L3p-ybricmT3oCcHEqhufq-ygyfqk1RufJwwRblwYPyaJE",
"refresh_token":"def50200c6b2378110190ac28d9d55f622885bb0b470a20543a6f1eefb18ed93c57b7040dc4db9444aa8853209bde9d5443a407d43fcaf1deb2e1f3f5ea3ce7431c4ec5e111bdc0cc71ca76034cd2a884441c51e4c922dddfa3f6e3a3fa8e1fbb8efe4581ce70d76590e732b3fa8b0c41a8abff4a8759f9dd1cc3ae46134fb67a8f25cd79e3229f6ee3238701ebfe0e8b0e2f14bd13c7fde3f813708a3de9928c8e992850994ca97bf61984cdb846bd0d72916312d9985472fc4293a3b3f2c55e1ef19621ef009623a6780f800ece9c8d835871dc795fda5daa43ac3fdae467e66b46e4eb73d53b8cb821522ee60979711c28c54fb2085f6000ac7e96e019ce51b9f92ea3fa2028aa0238fc3dca9c900e8dd77907782b22482f95a5e55708e5bda8c28f3732ff55e361f08447b33fe05d5646cecfb9faed462d327efdcc2a3742f46f9f825275d296b4ced25c05f3b6add68f43a2b448e4523d5410c631dc45bba"
}
Try to use this library: https://github.com/GeneaLabs/laravel-caffeine , and you can look laravel session config options
tokenExpireIn() instead of refreshTokensExpireIn() use then solve tokenExpireIn problem.
for passport grant token
Passport::tokensExpireIn(Carbon::now()->addDays(10));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(15));
This is only adding 10 minutes of expiry time. Don't know how and why, but instead changing internal codes. I Changed
Passport::tokensExpireIn(Carbon::now()->addDays(10000));
Passport::refreshTokensExpireIn(Carbon::now()->addDays(12000));
Now it's adding 7 days of expiry time. Seems like addDays function adding 10000 minutes.
I have the same issue before for my application, I spent two days try to find what is the problem, The best solution that I came up with is to change the expire date directly in the PassportServiceProvider
Go to vendor/laravel/passport/src/PassportServiceProvider.php line 108
new PersonalAccessGrant, new DateInterval('P1Y')
for example to set the expire date to one week
new PersonalAccessGrant, new DateInterval('P1W')
I know this is a bad solution for fixing the issue, recently I have found the same issue on Laravel Git repo
https://github.com/laravel/passport/issues/47
Related
I have a laravel / angular app secured with tymon/jwt-auth.
Now I need a seperate Laravel (or Lumen) API. I want this API to accept the same tokens as the first one. I assumed that this would work if I would set the same secret and mount the middleware.
It doesn't. Using a freshly generated token I can query the first API but not the new one. Why is that? Is something else besides the secret used to verify the token?
What would be a good way to make this work? I would not mind to make a completely new authentication.
Edit: So it seems like a connection to the database is need to verify the token. Maybe it checks if the user specified in the token is actually present in the DB?
Edit2: Tore Nestenius commented about Aud-Claims. I wanted to go to the config/jwt.php file to check on that. But I had forgotten to create one. Now it works.
The aud claim in the token must match what both API's expect to see in the access token. I am glad my comment helped you to solve your issue.
I have a Spring Boot authentication server running on a EC2 on AWS us-east-2 region which generates Firebase custom authentication token for a Flutter mobile app.
Everything is working fine, except by the fact that Firebase token issuedAt variables are being generated 4 or 5 minutes ahead of Firebase default time. This makes the FirebaseAuth.signInWithCustomToken return an error with The custom token format is incorrect. Please check the documentation message.
I haven't found any option to set time in Java Firebase API and I can't change it's value after the token have been signed.
I've seen some other questions facing a similar problem, but I couldn't figure out a way to fix it.
Edit 1
On the server side, I generate the token this way:
return FirebaseAuth.getInstance().createCustomToken(authService.getEmail());
And it really is a valid token, because if await 4 or 5 minutes before using it, it works. Otherwise, if I try to use it immediately, it doesn't.
As #Frank van Puffelen suggested, I contacted Firebase Support and they told me to try to generate Firebase Token manually. So I did that, set issuedAt attribute to 10 minutes before and it worked properly.
I Just have my question why Laravel passport create a new token with each login or register process?
My database now ( just for testing)
notice with every registration process creating a new token, imagine if I have 100,000 users and every user has to assume 10 tokens, will this affect performance?
I'm new on Laravel passport
The tokens that Passport generates are meant to be long lived; Notice the expires_at column it shows about one year.
Passport is typically used by First party app like you own SPA/mobile app or by a third party Machine/API to get access to your app. This Oauth procedure (register/login) may occur only once per long time, for example a mobile app using your API: the users won't enter their credentials every time to open the app; instead the token is saved to mobile app storage and it's already long lived.
If you use your app like The Passport docs explains and suggests you won't end up with all these tokens.
Another thing you should consider running a scheduler to purge the tokens as the docs states:
# Purge revoked and expired tokens and auth codes...
php artisan passport:purge
# Only purge revoked tokens and auth codes...
php artisan passport:purge --revoked
# Only purge expired tokens and auth codes...
php artisan passport:purge --expired
Finally, Sanctum "previously Airlock" is here ✌🏻
I suggest you take a look at the docs and you will notice it's much simpler than Passport and probably what you need.
I'm creating a SPA app with Vue.js (will be stored on remote server) and I'm confused as to what I should use.
At first I considered the use of Passport, but I don't understand how to make an API with Passport for 1st party only. Also I don't understand, how to make it quite secure if I need to send to the server my client-secret and client-id.
Then I read more about JWT, but there's no scopes for my tokens and no refresh tokens. It means if somebody stole the token from localStorage, then he will get access to this user permanently.
And one more question about the token access and API. I read a lot about different token expiration when it depends on its importance. It means token for changing password must be valid for a period of 5 minutes, but token for reading some information should be valid for 6 months. Is it right and how to do this right?
About JWT or Passport - what should I use then?
If you access api directory from client(using angular/react/vue js..) I suggest you to use Passport. in the passport there is a option call Password Grant Tokens, so user have to enter user credential and it'll generate a token(you can adjust the lifetime of the token) and when it expire you can refresh it. And yes if someone stole your token they can access your data
Read this if you want to know more:
https://stackoverflow.com/a/34983109/801448
Maybe I searched with the wrong keywords but I never found anything about the following scenario:
I have both an API with JWT auth (Laravel + tymon/jwt-auth) and a PHP application that should query that API protected by a JWT token.
How can I make sure that the app always is authentificated? After reading a lot of tutorials and article about JWT auth I'm left with this ideas:
using a never expiring token which is stored permanently in the consuming application. If I understand it right this could be a security concern because someone who has access to that token has access to the api as long as he want? But I don't understand why this token shouldn't be invalidated if the token has been stolen?
refresh the token on every request and invalidate the old one. This implies that the consuming application have to update the token after each request in it's storage (database would make the most sense, I guess). In my opinion this produces a lot of overhead and it doesn't prevent for jwt-auth's refresh_ttl setting.
using an additional API request (perhabs cron based?) to a refresh route to prevent the token from expiring. Again there is the jwt-auth's refresh_ttl problem I think.
I wonder why there seems to be no discussions/articles about that scenario.
Any help on that subject I would very much welcome!
You don't want your user logging in every time but you also don't want them to be logged forever.
Here are my thoughts
I have worked with 1 year tokens for comercial applications, I was using it for low level third party developers, the api concept was already overwhelming for them so I went easy on the auth thingy. Once every year their application broke and they had to reach out to get the new token, bad design but it worked.
Refreshing your token on every request will kill your performance and let attackers have a consistent way to break/predict your key, no good.
In my opinion, this is your most elegant suggestion. You could use some PWA features to accomplish that.
I would suggest increasing the refresh_ttl to 30 days and keep the ttl on one hour.
If you're using SPA or heavy js apps:
On your javascript you could do an ajax setup (or prototype or whatever your javascript framework uses for oop) and have a call to refresh whenever you get a .
If you're using just common page refresh for your apps, store you JWT on a cookie, then your application can refresh it whenever it needs and there will be no special js to make. HTTPS will take care of security.