I'm new to Laravel and am using Laravel 6. I am working on an app that uses the default authentication for Laravel. I registered myself three times with three different email addresses for testing purposes. I'm finding that after a few hours, I'm logged off and have to log back in again even though I did not click on the logoff option.
Am I correct in assuming there is some kind of default timeout for IDs in Laravel? If so, how to change the interval or disable it altogether?
If that isn't the issue, what could account for me being logged out?
Laravel authentication uses session driver for web guard as default. You can check your default web guard's driver on config/auth.php.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
//...
],
The Laravel session's lifetime is 120 minutes by default, You can also check this default value on config/session.php as lifetime property.
'lifetime' => env('SESSION_LIFETIME', 120),
So you'll be logged off automatically (i.e your session expires) after 2 hours by default.
If you want to stay login for a long time, you have 2 options:
Select the "remember me" option when logging into your application (Recommended).
Set a large value (e.g 10 years or so) for session's lifetime on local .env file. It's not recommended on production environment, because not only authenticated users but also all visitors (including guest, bots etc.) would have a longtime session.
SESSION_LIFETIME=5256000 // 10 years
If you check CookieSessionHandler::write and CookieSessionHandler::read:
//write
/**
* {#inheritdoc}
*/
public function write($sessionId, $data)
{
$this->cookie->queue($sessionId, json_encode([
'data' => $data,
'expires' => $this->availableAt($this->minutes * 60),
]), $this->minutes);
return true;
}
//read
/**
* {#inheritdoc}
*/
public function read($sessionId)
{
$value = $this->request->cookies->get($sessionId) ?: '';
if (! is_null($decoded = json_decode($value, true)) && is_array($decoded)) {
if (isset($decoded['expires']) && $this->currentTime() <= $decoded['expires']) {
return $decoded['data'];
}
}
return '';
}
you can see that there must be some value of time to compare with current time value. Otherwise an empty string is returned and session is being invalidated. Best way you can do is to set config value to something really large (e.g. 35791394 [~68 years in minutes]) This is fail safe for 32-bit systems because it is 2147483640 which is less than signed 32-bit MAX_INT value 2147483647, just in case. Even if sometimes in future Laravel rewrite session lifetime to use seconds instead of minutes this will last for more than a year.
Another SO answer.
Related
I'm having a problem related to 429 TOO MANY REQUESTS. I have used Laravel fortify and my web route is like
Route::get('/', function () {
return view('welcome');
});
Route::get('/dashboard','DashboardController#dashboardView')
->name('dashboard')->middleware('auth');
The problem is coming intermittently, after successful login I redirected to dashboard if immediately I hit logout and instantly try to log-in it is giving 429 TOO MANY REQUESTS and in the address bar the URL is http://127.0.0.1:8000/login. Now if I wait there for a sec and refresh the page it redirects to the dashboard page.
I have searched the web, everyone is saying about throttle and I'm not seeing this as the solution. Please help me.
Thanks.
I stumbled upon the same problem today and did some debugging. When registering the /login route, Fortify applies the Illuminate\Routing\Middleware\ThrottleRequests:login middleware to it. This means, for every request to that route, the ThrottleRequests middleware will call the RateLimiter instance for that specified key. Apparently, Fortify doesn't register a RateLimiter for the login key.
Due to the missing key in the $limiters property of the RateLimiter instance, the ThrottleRequests middleware uses its default fallback, which doesn't handle the edge case "there SHOULD be a rate limiter for that key, but there isn't." really well. The $maxAttempts variable is set to 0 and will result in flaky rate limiting behaviour.
I feel like this is a bug in Fortify, because rate limiting is also happening in the \Laravel\Fortify\Actions\EnsureLoginIsNotThrottled action, which is invoked in the \Laravel\Fortify\Http\Controllers\AuthenticatedSessionController controller. I didn't check this on a fresh Laravel installation, though, so I don't want to jump to conclusions here.
Anyway, long story short: As a workaround, you can simply register a rate limiter for the "login" key in some of your providers, e. g. AppServiceProvider or AuthServiceProvider:
public function boot()
{
RateLimiter::for("login", function () {
Limit::perMinute(5);
});
}
Edit:
I just realized that the rate limiter for the "login" key is indeed provided by Fortify within the FortifyServiceProvider class. If you happen to have a problem similar to the one discussed above, make sure that you added the FortifyServiceProvider class to your providers array in the config/app.php.
I tried everything including the Best Answer but it just didn't work.
Therefore, not even changing the RateLimiter in the FortifyServiceProvider class.
I'd try to log in and get a 429 error after just one login attempt.
Here what was the issue for me, it was the the config/fortify.php file.
I had to change:
/*
|--------------------------------------------------------------------------
| Rate Limiting
|--------------------------------------------------------------------------
|
| By default, Fortify will throttle logins to five requests per minute for
| every email and IP address combination. However, if you would like to
| specify a custom rate limiter to call then you may specify it here.
|
*/
'limiters' => [
'login' => 'login',
'two-factor' => 'two-factor',
],
to
/*
|--------------------------------------------------------------------------
| Rate Limiting
|--------------------------------------------------------------------------
|
| By default, Fortify will throttle logins to five requests per minute for
| every email and IP address combination. However, if you would like to
| specify a custom rate limiter to call then you may specify it here.
|
*/
'limiters' => [
'login' => 5,
'two-factor' => 5,
],
And funny enough the problem is inherent in the Fortify package itself when you run:
php artisan vendor:publish --provider="Laravel\Fortify\FortifyServiceProvider" as per their documentation instructions.
This fundamental reason being that code within vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php is not able to correctly parse the limit:
/**
* Resolve the number of attempts if the user is authenticated or not.
*
* #param \Illuminate\Http\Request $request
* #param int|string $maxAttempts
* #return int
*/
protected function resolveMaxAttempts($request, $maxAttempts)
{
if (Str::contains($maxAttempts, '|')) {
$maxAttempts = explode('|', $maxAttempts, 2)[$request->user() ? 1 : 0];
}
if (! is_numeric($maxAttempts) && $request->user()) {
$maxAttempts = $request->user()->{$maxAttempts};
}
return (int) $maxAttempts;
}
, which means, 'login' is just parsed as 0 and that's what it returns.
Now I don't have to run php artisan cache:clear just to test.
go to
app/http/kernel.php
and remove from routeMiddleware list the line
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
Just run
php artisan cache:clear
Hello guys I want to make the remember me checkbox and I want to save the user info into cookies so next time when try to login he find the user name and password in their fields I try to use :
$rememberMe = false;
if(isset($req->remember_me)) {
$rememberMe = true;
}
if(Sentinel::authenticate($req->all(), $rememberMe)) {
$slug = Sentinel::getUser()->roles()->first()->slug();
}
The cookies was set, I see it in the chrome settings but it does not do as I expect
I'm using laravel 5.2
You can use Cookies
cookie, is a small piece of data sent from a website and stored in a user's web browser while the user is browsing that website. Every time the user loads the website, the browser sends the cookie back to the server to notify the website of the user's previous activity
To create:
$response->withCookie(Cookie::make('name', 'value', $minutes));
To retrieve
$value = Cookie::get('name');
Your question is not to remember the user login.. The question is how to fill the inputs based on saved auth information. You can do that if you print the authentication values in the input value attribute while loading the page.
larval Cookies Docs
Also Laravel has it's own implementation of "Remember Me"
if (Auth::attempt(array('email' => $email, 'password' => $password), true))
{
// The user is being remembered...
}
if (Auth::viaRemember())
{
//
}
More information about https://laravel.com/docs/5.4/authentication#remembering-users
There is two main thing need to taken care:
1) You must pass a bool value as second parameter to the method, make sure you cast it before passing it to the method. - In your code, it's perfect
$credentials = $req->only('LOGINNAME', 'PASSNAME')
if(Sentinel::authenticate($credentials , $req->has('remember_me'))){
//Other stuff
}
2) you can verify it works by ensuring a cookie is set with the key cartalyst_sentinel?
So first change as per 1) option and then check the 2) option, may be this is your answer.
same as title, in my config:
'session' => array(
'class'=>'CHttpSession',
'timeout'=> 1200,
'autoStart'=>true,
),
in my code:
$ssKey = 'MY_SS_KEY';
if (isset(Yii::app()->session[$ssKey])) {
$this->jobWithSession();
} else {
$this->jobWithNotSession();
Yii::app()->session[$ssKey] = 'ok';
}
first time, it call function jobWithNotSession(), but after over 1200s (20 minute), it still call function jobWithNotSession, what's wrong? somebody can help me?
In order to make Yii session timeout to work, you should do the following:
In protected/config/main.php:
'components'=>array(
'session' => array(
'class' => 'CDbHttpSession', //Set class to CDbHttpSession
'timeout' => 1800, //Any time, in seconds
),
),
1800 is the time, in seconds, during which your time session will be active.
It is algo important to set the class to CDbHttpSession.
You are using the wrong functionality here. The session timeout is only applicable when the php garbage collector is getting called, which is far from every page-view. It has something to do with the gc_probability-setting. So that's not what you want to use. As long as it doesn't run, the session still exists (even though expired) and the user remains logged in.
What you do want is to "remove" the autoLogin cookie, which you can do by controlling the duration of it.
So basically what you need to change is the duration parameter of the CWebUser::login()-function.
I have implemented remember me functionality as this question
How to create "remember me checkbox" using Codeigniter session library?
first answer.
I created a cookie with a random number code as value and it stored in db(user table). On login, db code checks with cookie value.It works fine on my localhost server. But in live server which has a subdomain url has problem.Also I tested it with another server with ip address as url. There also it is not working. In both cases cookie created but cant read the cookie. Please help me.
cookie set by
$auto_login_hash_code = uniqid();
$domain = $_SERVER['SERVER_NAME'];
$cookie = array(
'name' => 'rememberMe',
'value' => $auto_login_hash_code,
'expire' => 31536000,
'domain' => $domain,
'path' => '/'
);
$this->input->set_cookie($cookie);
and reading cookie by
if (get_cookie('rememberMe')) {
$hashcode = $this->CI->input->cookie('rememberMe');
$this->CI->load->model('loginmodel', '', true);
$username = $this->CI->loginmodel->get_username_by_hashcode($hashcode);//in this function setting session variables
}
Thanks in advance
iijb
you are getting library for that on github.
search remember me on github, load it and just follow below steps.
Verify cookie if token is present in database go to home page
$this->load->library('rememberme');
$cookie_user = $this->rememberme->verifyCookie();
if ($cookie_user)
{
$this->load->view('search_view');
}
else
{
// If checkbox is checked it return true either false
$checked = (isset($_POST['Checkbox1']))?true:false;
if($checked== true)
{
//$this->load->view('tested');
$this->load->library('rememberme');
$this->rememberme->setCookie($this->input->post('loginemil'));
//$this->rememberme->setCookie('set cookie here');
}
else{
dont set anything
}
}
Also this can be done by editing/extending system Session library.
First: In user login function add remember me check-
if($remember)
{
$data['new_expiration'] = 60*60*24*30;//30 days
$this->session->sess_expiration = $data['new_expiration'];
}
$this->session->set_userdata($data);
Second: Edit system Session library [I am not sure whether extending Session will work or not]
Go to this line in sess_read() method
if (($session['last_activity'] + $this->sess_expiration) < $this->now)
Before that line add following code
if(isset($session['new_expiration'])){
$this->sess_expiration = $session['new_expiration'];
}
This works fine for me.
I am using Tank Auth, and require my users validate their email addresses. Upon validation, users are still not logged in. I would like users to be automatically logged in when activating their account.
In my previous version (home-grown auth) I wrote a login function that didn't require a password, that was only callable in that situation. However, I can't see a way of doing that in Tank Auth. One solution would be to cache passwords until activation, but I really don't want to do that...
You can just bypass your login system.
Store either thier email address OR alias in a cookie.
when they activate grab the cookie, search(verify they exist) for the user, then setup a normal login session.
A login is just a set of session rules.
inside your activation script/email process, append
$this->_set_ac_cookie({email});
-
protected function _set_ac_cookie({email})
{
return $this->input->set_cookie(array(
'name' => 'ac_cookie_'.{email},
'expire' => '7200', //You may mirror when/if your activation key expires
'domain' => 'yourdomain.com',
'path' => '/'
));
}
check cookie exists
protected function _before_activation({email})
{
return $this->input->cookie('ac_cookie_'.{email})) ? TRUE : FALSE;
//make sure {email} has a UNIQUE db constraint
}
when the user clicks the activation link
if($this->_before_activation({email}))
{
//check user exists AND activation status === false (0)
//grab the user details from db based on {email}, set activation status to true (1)
//setup login session
$this->session->set_userdata(array(
'logged_in' => (int)1,
'user_id' => {user->id},
'alias' => {user->alias}
));
redirect('dashboard');
}
else
{
//sorry!
}
If you take a look at the code inside tank auth that handles the email activation, you'll see that it explicitly logs the user out on email verification.
https://github.com/ilkon/Tank-Auth/blob/master/application/controllers/auth.php
Line 243.
You could just comment out $this->tank_auth->logout(); on line 244 and it should work as you want it to, but this would be bad practice.