I am developing web application using Laravel 5 and angularJs with RESTFUL apis.
Using middleware to authentication purpose. My problem is after sending few request simultaneously,system automatically logged out and sending 401 exception from laravel side.
API base controller:
class ApiController extends BaseController {
use DispatchesCommands, ValidatesRequests;
function __construct() {
$this->middleware('api.auth');
}
}
Middleware:
class APIMiddleware {
/**
* Handle an incoming request.
*
* #param Request $request
* #param Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
if (!Auth::check()) {
abort(401, "Unauthorized");
}
return $next($request);
}
}
Log in controller
public function login(LoginRequest $request) {
if (Auth::check()) {
Auth::logout();
}
if (Auth::attempt(['email' => $request->input('email'), 'password' => $request->input('password')], $request->input('is_remember'))) {
return array(true);
} else {
abort(401, "Invalid email & password");
}
}
After few request gone, Server log out and sends 401 exception. I am stuck with this issue.
Now I'm not 100% sure (and depending on your set-up I can't even say I'm 90% sure) But after changing my session_driver from file to database I seem to have fixed this issue - that is if it's the same issue.
I think do the samething as you with my app - that is on a start up of a page, I'm making 6 request (this is development and I will be changing it to one so please don't cry). If I load this page, it works with about 3 or 4 request, then the other 2-3 come back with a unauthorised response. It also only happens on request that require middleware => auth.
So here's my theory to why this is happening: Because, by default, sessions are saved in a file - making multiple requests at once means that file is being opened 6 times at once - probably messing it up (depending on your machine). Therefore changing the session to a database, which is designed to have thousands of requests at once, works!
SOLUTION:
Go to your .env file and change SESSION_DRIVER=file to SESSION_DRIVER=database.
Next you will need to create a session migration: php artisan session:table.
Now composer dump-autoload for good practice.
Finally migrate (php artisan migrate).
NOTE: I'm not 100% sure though if this is the case, but for me this solution worked. I am also aware that this question is really old, but both the developers I work with and myself have had this issue and there doesn't seem to be a solution, so Just though I'd post this.
Managed to figure it out.. Since i use laravel for pretty much all my projects, I forgot to change the session name, as a result, one session was overwriting the other, causing the auto-loggout.. So if you have multiple laravel projects running, make sure they all have different session names. Hope this helps someone in future !
Here is a Laracast thread on this issue.
For me this was the process to solve the problem:
Cleared my browser's cookies for localhost.
Changed value of cookie key in app/session.php.
Ran php artisan config:clear.
It may be a problem that you are accessing the user variable illegally. Please use Auth::check() before accessing Auth::user() This seems to work for my project. Optionally you can try for changing the session driver from .env file.
Might be useful for someone: Had the very same problem. I've changed the cookie name in session settings. By default it is laravel_session, so try setting it to something else
I solved the same issue by clearing cache using php artisan cache:clear and also running composer dump-autoload. Hope this works for you.
I had a similar problem this week. I have a server with multiple Laravel applications. One application was logging the other out.
The problem had to do with session management. The session name was the same for all the applications. Changing it would be enough to avoid different applications conflict. However, I can have different instances of the same application in the server (for testing purposes, for example). So, changing only the session name would not be enough.
To solve my problem properly, I used the session path to make the configuration unique per instance. In the config/session.php, I defined something like this:
'cookie' => 'systemx_session',
'path' => parse_url(env('APP_URL', 'http://localhost'), PHP_URL_PATH),
I use the parse_url function with the environment variable APP_URL because my server has the instances deployed under something like http://example.com/systemx.
I hope this helps someone who might end up having the same kind of problem.
I think you copied an old project for a new application, so you need to change the config/session.php
'cookie' => 'new_session',
I had a similar problem that the users didn't login at all & I found Its because of my authenticatable eloquent model, specified in my auth guard in config/auth.php (User in my case).
I was applying a global scope (in my case verified) so that users were filtered by a specific column & auth guard couldn't find the user so it logged out everytime ...
I solved my problem by this post https://laracasts.com/discuss/channels/laravel/ignore-global-scopes-for-auth
Related
I deployed my Laravel app with Laravel Nova on Laravel Forge.
I installed Nova with a path repository, I have also Nova user.
I replaced NovaServiceProvider Gate method like:
Gate::define(‘viewNova’, function ($user) {
return in_array($user->email, [
‘my#license.com’,
]);
});
When I visiting page "/nova" there is login form but when I’m trying to log in with my existing user, it goes on 403 error page with the message “Sorry, you are forbidden from accessing this page”
The only article I found is "Common problems when setting up Laravel Nova" on Medium.
Problem #2: there looks like my issue, but it's not. I think my issue is about the license, otherwise, I tried everything.
I have a solo Nova license and I have not to email support to ask them.
I have: Laravel 5.7 and Nova: 1.3.1
My question is: Should I buy the pro license? and why? Or what's the issue?
This often occurs if you have deployed to a production environment and haven't set up your Gate guard yet. Or have a cached config, or are signed in as an email that isn’t whitelisted.
Ensure you add your emails like so:
protected function gate()
{
Gate::define('viewNova', function ($user) {
return in_array($user->email, [
'your#emails.com',
'login#emails.com',
]);
});
}
to app/Providers/NovaServiceProvider.php
Further to that - some housekeeping items to remember:
php artisan nova:install
php artisan optimize:clear
Clearing [config] caches can usually clear up bumps along the road.
I believe your issue (unless it's not actually the code running), is due to the ‘ and ’ characters surrounding the email address you're authorizing and what's being passed to define(). Try ' or " instead - PHP understands those, not the previous characters.
Gate::define('viewNova', function ($user) {
return in_array($user->email, [
'my#license.com',
]);
});
This is a common mistake if you're copying / pasting from text editors like Microsoft Word, or copying from online sources!
I want to make boot function for my app preview, for that I have plan to add new variable to .env file and let's name it APP_Mode so I want to say:
If APP_Mode=preview prevent all actions and redirect back with
xxxxxx text as flash session message.
The point
The point of this boot action that I try to achieve is to not let users change any of my preview site settings like store/delete/update etc.
Question
Is that possible? How?
First off, might be worth considering if Laravel's maintenance mode might work for you - you can whitelist the IP addresses that are able to access the site, and it will appear down for everyone else.
If that's not going to do the trick, you'll probably be best to create your own middleware - it will likely be similar to the CheckForMaintenanceMode middleware that Laravel ships with. In the handle method you can check for the configuration option to see if you're in preview mode or not, and then decide how to handle the request.
If you're using "RESTful" routing like Laravel recommends - that is, GET requests are idempotent and don't change anything, and only POST/PUT/DELETE requests make changes - your middleware can simply return a HTTP 403 response (forbidden) if your preview mode is enabled and the request method isn't GET.
A very simple implementation (you'll likely need to tweak) to get you started would be something like this:
public function handle($request, Closure $next) {
if (config('app.mode') === 'preview' && $request->method() !== 'GET') {
abort(403);
}
return $next($request);
}
Just in regard to using config('app.mode') instead of something env('APP_MODE') is that you shouldn't be using the env helper outside of the configuration files - otherwise you can't take advantage of Laravel's config caching. So add another config option in the config/app.php file that you can use to check the mode the app is in.
I set my SESSION_DOMAIN ="example.com" in my .env
now I can't login my account with correct email and password.
anybody who encounter this problem?.
For all experiencing this error.
When you change the SESSION_DOMAIN env variable, Laravel will issue new cookies but old ones are still in the browsers memory. When the request comes from browser to Laravel app the old cookie has priority and there for you are not able to login.
The solution to this is delete old cookies from the browser (those registered without any domain so to actual host of app).
This error typically bites those who wants to add multi subdomain persistent login. And what is even worse, when you have your application in production already, all your clients will suffer from this issue as well. Nobody will able to login (not only that, but mainly) to your application until they completely clear out their cookies.
I solved this by adding middleware, which does it for me:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Cookie;
class ForgotOldSessionCookies
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
*
* #return mixed
*/
public function handle($request, Closure $next)
{
Cookie::queue(new \Symfony\Component\HttpFoundation\Cookie('laravel_session', null, now()->subYear(1)->timestamp, '/'));
Cookie::queue(new \Symfony\Component\HttpFoundation\Cookie('XSRF-TOKEN', null, now()->subYear(1)->timestamp, '/'));
return $next($request);
}
}
Be aware, when you use only this:
Cookie::queue(Cookie::make('laravel_session', null, -6000, '/', 'yourdomain.com'))
or
Cookie::queue(Cookie::forget('laravel_session', '/', 'yourdomain.com'))
Laravel will send Cookie header with domain so browser will create the cookie with domain .yourdomain.com - that's why nothing will be deleted.
Couple of things:
Make sure you did not actually wrote example.com. if this is your local, write 127.0.0.1:8000
Make sure to re run the server after any change in the .env file with php artisan serve
I am building a REST user-microservice using Laravel 5.5 + Passport.
I am using the standard Passport::routes(), but I have had to modify the Auth::routes in order to make them return JSON responses, and to make them work with Passport.
I have added the following lines to my routes/web.php file:
Route::group(['middleware' => 'auth:api'], function () {
$this->post('logout', 'Auth\LoginController#logout')->name('logout');
});
This allows me to POST https://myapi/logout
If I make the call with the header "Authorization => Bearer TOKEN", I get a successful logout response.
If I provide no header at all, I get a "not authenticated" message (which is good)
However, if I provide the header with a revoked token, I get a recursive deadloop of the function: Illuminate\Auth\RequestGuard->user() (it keeps calling itself recursively until stack-overflow)
This is all done in the auth:api middleware, my logout code is not reached, but my LoginController constructor is called. Constructor code:
public function __construct(Application $app)
{
$this->apiConsumer = $app->make('apiconsumer');
$this->middleware('guest')
->except('logout');
}
I'm struggling to understand if it's my code causing this issue, or some combination of Laravel + passport + auth.
My first thought was that the auth:api middleware fails to authenticate the user, and as a result redirects the user to /home, where for some reason it's triggered again, recursively. But if that was the case, why would it work correctly with no header?
My current thinking is that the token in question does exist in the database, but Laravel is failing to figure out that it's revoked.
Any suggestions appreciated,
I found an answer (if not the answer) after a lot of research. It appears this is a Laravel bug (https://github.com/laravel/passport/issues/440). The solution is to add OAuthServerException to the $dontReport array in app/Exceptions/Handler.php:
class Handler extends ExceptionHandler
{
protected $dontReport = [
...
\League\OAuth2\Server\Exception\OAuthServerException::class,
];
}
This will avoid trying to log user information, thereby avoid the deadloop.
I have faced this in localhost. in my case, I have used xampp server and facing this issue
after creating a virtual host like "testlarave.test" then solve the error
I'm building a package called under-construction. When this package is activated in a config
file the site will be underconstruction only people with the right code can access the
application.
https://github.com/larsjanssen6/underconstruction
The problem that I have right now:
When the code is entered I make an ajax call that hit's this controller method (called check):
https://github.com/larsjanssen6/underconstruction/blob/master/src/Controllers/CodeController.php
If the code is correct a session variable is being set:
session(['can_visit' => true]);
Then in my vue.js code I redirect to /. And it will hit my middleware again. Here I check if a session called can_visit exists.
return session()->has('can_visit');
https://github.com/larsjanssen6/underconstruction/blob/master/src/UnderConstruction.php
But the session variable can_visit is always gone! How is that possible?
Thanks for your time.
You're not loading the session middleware, so session is not started and no values are persisted.
As was mentioned in the comments, even though your protected routes (/) are within the web middleware (read session), your service provider's routes (/under/construction, /under/check) are not (no write session).
The simple fix is to add the session, or even better, the whole web middleware.
$routeConfig = [
'namespace' => 'LarsJanssen\UnderConstruction\Controllers',
'prefix' => 'under',
'middleware' => [
'web', // add this
// DebugbarEnabled::class, // leaving this dead code behind despite vcs
],
];
However, you might quickly run into trouble with infinite redirect loops if a user adds your middleware to their web middleware group. So I would add a check of some sort to make sure you're not on one of the existing underconstruction routes.
public function handle($request, Closure $next)
{
// check this isn't one of our routes
// too bad router hasn't loaded named routes at this stage in pipeline yet :(
// let's hope it doesn't conflict with user's routes
if ($request->is('under/*')) {
return $next($request);
}
if (! $this->config['enabled']) {
return $next($request);
}
if (!$this->hasAccess($request)) {
return new RedirectResponse('/under/construction');
}
return $next($request);
}
And ultimately guessing from the context of this project, I'd expect most people would want to stick this in the global middleware. However, you're going to run into the same session-hasn't-started-yet issues because that doesn't run in the global middleware. So there's more to chew on. Happy coding!