Laravel Sanctum: How to configure the expiration date of the token? - laravel

Context and Need
In my api routes file, I've written the following code following the documentation (https://laravel.com/docs/8.x/sanctum#introduction) :
Route::post('/tokens/create', function (Request $request) {
$token = $request->user()->createToken($request->token_name);
return ['token' => $token->plainTextToken];
});
I would want to set an expiration delay that would be used to compare the date of the creation of the token with the date of the current check of the token expiration: the token'd have a creation date of x, the current date'd be y, and the delay'd be d so the token would expire if y > x + d.
What I've done
So I've read some code in the directory vendor/laravel/sanctum, and I've found the class Guard.php.
The class Guard.php contains an object attribute named $expiration, a constructor that sets it (among other things), and the __invoke method that contains the following expiration check:
if (! $accessToken ||
($this->expiration &&
$accessToken->created_at->lte(now()->subMinutes($this->expiration))) ||
! $this->hasValidProvider($accessToken->tokenable)) {
return;
}
As you can see, it does exactly what I want. However, I can't figure out how to set my own value for the attribute $expiration.
In this same file, there are some allusion to an existing configuration file, like this one: config('sanctum.guard', 'web'). Also, the class SanctumServiceProvider instanciates Guard and passes to its constructor the following value: config('sanctum.expiration'). But I don't know how/where to define this config value. Perhaps https://laravel.com/docs/8.x/configuration config(['sanctum.expiration' => '1277126']);? Could you confirm it please? (but where to put this line?)
Question
My question is: in Laravel 8 Sanctum, how could I set my own value for the variable $expiration used for Sanctum tokens check? Should I edit a configuration file and if yes, how? Should I type a configuration command in a terminal?

You can publish the Laravel configuration:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
See https://laravel.com/docs/8.x/sanctum#installation
After this you are able to change all configuration options in config/sanctum.php. The configuration files in config will overwrite the vendor default configuration.

The documentation https://laravel.com/docs/8.x/sanctum#spa-configuration says that, for SPA, we can set a value for the configuration option SANCTUM_STATEFUL_DOMAINS in the file vendor/laravel/sanctum/config/sanctum.php. So it should be the same for expiration. This file, indeed, contains the following text:
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. If this value is null, personal access tokens do
| not expire. This won't tweak the lifetime of first-party sessions.
|
*/
'expiration' => null,
So I think I should modify it to set the number of minutes of tokens expiration.
The sole problem is: as this file is contained in the vendor directory, if I download an update of Sanctum, would it erase this modification (i.e.: the number of minutes of expiration I've written)? If yes, then I should look for a similar solution that would be permanent (overriding this configuration file? modifying the .env file?). If no, then there isn't any problem, it would be perfect.
Maybe https://laravel.com/docs/8.x/configuration#accessing-configuration-values would be interesting to know which decision to take. However, if anyone could advise me in a comment it woud be kind.
Final Solution
Important Edit: instead of vendor/laravel/sanctum/config/sanctum.php, there is also the following config file: <my_site>/laravel/sanctum/config/sanctum.php so the latter should be editable without any problem. I think this is the best solution.

Related

Is there a one time link generation Laravel?

Is it possible to create a one time link in Laravel? Once you open the link it expires?
I have created a Temporary Signed Link, but I can open it multiple times. How do I counter it?
There is this package that can help you
https://github.com/linkeys-app/signed-url/
This will generate a link valid for 24hours and for just one click .
$link = \Linkeys\UrlSigner\Facade\UrlSigner::generate('https://www.example.com/invitation', ['foo' => 'bar'], '+24 hours', 1);
The first time the link is clicked, the route will work like normal. The second time, since the link only has a single click, an exception will be thrown. Of course, passing null instead of '+24 hours' to the expiry parameter will create links of an indefinite lifetime.
There maybe a package that provides a functionality like this... always worth looking on Packagelist before building something rather generic like this from scratch. But, it's also not a hard one to build from scratch.
First you'll need database persistence, so create a model and a migration called UniqueLink. In the migration you should include a string field called "slug", a string field called path, and a timestamp field called "used_at."
Next create a controller with a single __invoke(string $slug) method. In the method look up the $link = UniqueLink::where('slug', $slug)->first(); Update the models' used_at parameter like so $link->update(['used_at' => Carbon::now()]);
Then return a redirect()->to($link->path);
Add a route to your routes file like this Route::get('/unique-link/{slug}', UniqueLinkController::class);
Now you'll just need to create a method to add these links to the db which create a slug (you could use a UUID from Str::uuid() or come up with something more custom) and a path that the link should take someone. Over all a pretty straight forward functionality.
You could track when the URL is visited at least once and mark it as such for the user if you really want to, or you could reduce the expiry down to a few mins.
URL::temporarySignedRoute( 'foobar', now()->addMinutes(2), ['user' => 100] );

Laravel: best way to get locale time in my language in whole admin section?

I'm new to Laravel 5 (and to OOP in general) and I'm trying to switch from my old procedural code. In the whole admin section, I need to set the locale time to Italian for viewing purposes (i.e. show dates like "martedì 8 dicembre 2015" instead of "Tuesday 8 December 2015").
So far, I set 'locale' => 'it' in config/app.php and changed the routes.php file like this:
Route::group(['prefix' => 'admin'], function(){
setlocale(LC_TIME, config('app.locale'));
// here go all my routes
});
It works, but is this a correct approach (I mean, set a config in routes file)? Is there some more elegant way to keep routes separated from custom configs? Or is it better to keep simplicity like this?
More, I still don't know if this can affect the way dates are stored into database (at the moment I deal only with list of records, not with store or updates) - of course my dates should be stored as ISO
Thanks a lot
Don't forget that you canalso set this in your App/config/app.php file:
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/
'timezone' => 'Europe/Amsterdam',

Laravel session key changing the whole time?

I am using "file storage" for my session. When I run this:
Session::set('awesomekey', 'myVal123');
And refresh the page, I can see new files being created in /storage/session each time. I assumed it would update the same file each time. This basically means sessions don't work at all. In other words, if it keeps recreating a session file, this never works:
Session::get('awesomekey');
Or at least, it returns a blank. What am I missing that could possibly be causing a new session key to be created each time a page is loaded?
UPDATE
On further investigation, it seems the cookie is regenerated on each page load. What could be causing that?
I am not even looking at logging in yet, so this information is useless to me --> http://willworkforbanjos.com/2014/02/laravel-sessions-not-working-in-4-1/
My problem is happening when I simply put the above set and get code in the master.blade.php file. It should set it, store the info, and on the next reload get the right information from session. But it can't because on reload it changed the cookie to some other code.
Anyone know why this is happening?
UPDATE 2
Adding: 'lifetime' => 120 to session.php did not work. (#Sheikh Heera)
Placing the code in the controller only, does not work. (#Phill Sparks)
I tried chrome and firefox, same result (#The Shift Exchange)
Just to be clear on what I'm trying to do. I add the following code in HomeController.php:
public function index()
{
Session::put('awesomekey', 'myVal123');
return View::make('home.index');
}
Then I put this in my master.blade.php:
print Session::get('awesomekey');
I do not include any "dies" or random echos in my controller side of the code, except for this. When I open the file the first time, I can see myVal123 being printed out.
I then take out this part in the controller:
Session::put('awesomekey', 'myVal123');
And reload the page. It now prints nothing. I can see in my browser that the cookie has changed. Generating a new cookie will lose the reference to the session, so I'm stuck trying to understand why it's doing that each time, even though it saves the session on the first load.
Any more ideas?
UPDATE 3
I also tried:
Running "php artisan dump-autoload" ... still doesn't work
I went here: http://www.whatismybrowser.com/are-cookies-enabled ... and yes, cookies are enabled.
I'm really running out of ideas here...
UPDATE 4
I went to SessionManager.php and just underneath this:
$lifetime = $this->app['config']['session.lifetime'];
I printed out the value of life time:
print $lifetime; die();
And this code was never hit on page reload?! However, adding this in my controller:
$d = Config::get('session.lifetime');
print $d;
Does in fact print out my value for lifetime.... :(
The problem was this line:
'cookie' => 'xxxx.com',
in session.php. Apparently it loses the cookie if you have a "." in the cookie name. I can't believe Laravel doesn't like that. Or maybe it's browser's in general.
I believe you are using:
'lifetime' => 0 // number of minutes
in your app/config/session.php file. Make it something like this:
'lifetime' => 120 // number of minutes or whatever you want
It'll work. I tried same settings as you described and just used 0 and I get same result, each time a new file is being created but once I change it to 120 or so, it works. So, it make sense that, if it's set to 'lifetime' => 0 in the session config then every time it just creates a new file for a new session because the session doesn't live. So, go to your app/config/session.php file and you'll find something like this, change the value:
/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
|
*/
Update:
You may use following code to get the lifetime value set in the app/config/session.php file:
Config::get('session.lifetime');
Have a look at the cookie's expire time in Chrome developer tools, or Firebug. If it is set to 0 then the cookie will expire immediately.
Also, double-check if your clock is setup correctly - strange things could happen if there's a disparity between your host's and the browser's clock. Make both systems consult NTP to ensure this is not an issue.
I had a similar problem with the sessions, if you're using the model User and your users table doesn't have the primaryKey as Id, you must overwrite that variable at the model.
class User extends Eloquent {
protected $primaryKey = 'admin_id';
}
In /app/config/session.php check the "HTTPS Only Cookie" setting.
Make sure it's "secure => false" if you are not using SSL!
I've experienced issues related to this. The session file wasn't created every time but sometimes I just can't get the session variable displayed. After hours of experiments I found that the problem was related to Debugbar.
If you're using Debugbar and having session issues, disable it and try again to confirm.
Use Session::put('value') instead of set.
http://laravel.com/docs/session#session-usage

user->setParam in onUserAfterSave plugin has no effect

I have a (currently working) plugin which creates a user on a third party system when a user registers. This is working fine so far.
I'm trying now to add a param to the user to store the third party id but this doesn't seem to be working:
function onUserAfterSave($user,$isNew,$success,$msg=''){
if(!$isNew || ! $success){
return;
}
jimport('joomla.log.log');
$res = someThirdPartyCall();
//Res is valid here
JLog::add("Res ".print_r($res,true), JLog::WARNING, 'jerror');
$userOb = JUser::getInstance($user['id']);
$userOb->setParam('sugarid', $res['id']);
//User ob is valid here
JLog::add("UserOb ".print_r($userOb,true), JLog::WARNING, 'jerror');
$saveRes = $userOb->save();
//Result is true. Error array is empty.
JLog::add("Result ".print_r($saveRes,true), JLog::WARNING, 'jerror');
JLog::add("Errors ".print_r($userOb->getErrors(),true), JLog::WARNING, 'jerror');
}
Everything looks great, no errors or the like. The only thing not working is that the params aren't set in the db. Is this because I'm trying to save the user in onUserAfterSave?
You have forgot to import the user library in to your plugin to use setParam. So At the beginning of your file do not forget to include user library. Use this line of code.
jimport( 'joomla.user.user' );
Hope this will help.
If save is finished you can't go back and add to it, the save is finished and door is shut. You need to do set things up when you set up the paramters by making a form plugin to add another field to the params. Then you don't need to save at all because params will just save as part of the normal process. I'm assuming this is not something that needs to be encrypted, right? It's just the user name?
Also I should mention that there is Juser::defParam($key, $value) that lets you add parameters via code.

Is it possible to regenerate Code Igniter sessions manually?

As above: Is it possible to regenerate Code Igniter sessions manually? I'm looking for something similar to session_regenerate_id in PHP sessions, so that I could call it manually when a user went through privilege escalation.
Thanks,
Lemiant
CI automatically regenerates the session id every x seconds, which you can set in your config.
You could create a new function in Session.php the same as sess_update() but with the following removed from the top & the function renamed to regenerate_id().
// We only update the session every five minutes by default
if (($this->userdata['last_activity']+$this->sess_time_to_update) >= $this->now)
{
return;
}
This will regenerate the session id, update users_activity and keep the users data. Just call it by $this->session->regenerate_id();
I know this is an old post, but I came across it, so others might too.
You could also do the following so you don't have to hack the core files at all (making codeigniter more easily upgradable with future releases):
//Setting this to 0 forces the sess_update method to regenerate on the next call
$this->session->sess_time_to_update=0;
//Call the sess_update method to actually regenerate the session ID
$this->session->sess_update();
Credit to the original answer for leading me down this path though, thank you.

Resources