When doing local development of Laravel apps using Auth0, we are surprised how often the application gets into a state where the callback route throws “Invalid state” exceptions or “Can’t initialize a new session while there is one active session already” exceptions occur. During local development this a little bit annoying, but when it happens on production sites it is problematic (since users are left with a nondescript “500 Server Error”).
-
The “Can’t initialize a new session while there is one active session already” exceptions occur if a user tries to log in when they’re already logged-in. Throwing an exception is not really helpful - in most cases it can simply be ignored.
-
The “Invalid state” exceptions can be caused by a few things, but most often seem to be when cookies/sessions get out of whack. We’ve found this can often be resolved by visiting the http://myapp/logout URL, although sometimes the only solution is to clear browser cookies.
We’re currently implementing some exception handling to handle these exceptions more gracefully. Our code below is now resolving most situations… except those cases that can only be rectified by clearing browser cookies.
(Note: We considered 3x possible places to implement the exception-handling logic:
- In app/Exceptions/Handler.php
- Creating our own app/Http/Controllers/Auth/Auth0Controller.php controller based based on a modified version of vendor/auth0/login/src/controllers/Auth0Controller.php.
- Creating our own app/Http/Controllers/Auth/MyAuth0Controller.php as a descendent of the vendor/auth0/login/src/controllers/Auth0Controller.php class.
Option 3 gave the most readable code.
Here’s our current “app/Http/Controllers/Auth/MyAuth0Controller.php” code (which is called from web.php instead of the default Auth0Controller.php file:
<?php
namespace App\Http\Controllers\Auth;
use Auth0\SDK\Exception\CoreException;
use Auth0\Login\Auth0Controller;
class MyAuth0Controller extends Auth0Controller
{
/**
* Wrap auth0 callback controller and handle exceptions if required
*/
public function callback()
{
try {
// try calling auth0 parent method
return parent::callback();
} catch (CoreException $exception) {
$message = $exception->getMessage();
// if active session exists, then user is already logged-in - no need to throw an error
if ($message == "Can't initialize a new session while there is one active session already")
return \Redirect::intended('/');
// invalid state is often a temporary cookie or a timing problem, and is often resolved by simply logging out
if ($message == "Invalid state")
return \Redirect::route('logout');
}
}
}
Our current code leaves two unresolved questions that I’m hoping one of the Auth0 devs or other community members may be able to answer:
-
Can anyone suggest a way to reset the necessary browser cookies for the (surprisingly-frequent) situations that they get out-of-whack? I’ve been contemplating a brute-force approach, but there may already be an Auth0 or Laravel method to do this cleanly. (Our current code is not ideal, because if the logout redirection doesn’t fix the problem, the user will repeatedly try to login (with no errors) only to find that they’re not logged-in again. This is not ideal.)
-
Shouldn’t the default Auth0Controller.php be doing some of this exception-handling?
Context:
- Which SDK does this apply to? (laravel-auth0)
- Which verison of the SDK you are using? (6.0.1)
- Which version of the platform are you facing this error on? (Laravel 7)
- Was this code working before? (n/a)
- Please capture and attach the stacktrace, it helps a lot! (n/a - various scenarios)
- Please share the code that is causing the error. (see below)
- Can you share a minimum reproducible? (not readily, but these exceptions are seen across quite a few of our projects and looking at the laravel-auth0 controller implementation I imagine we’re not alone)
- Please capture and attach a HAR from the browser if this is an Authentication Bug / Issue. (n/a)
- If this is a Management API Client bug, some libraries allow you to capture a HAR. (n/a)
CODE CAUSING THE ERROR:
These exceptions are raised during the call in Auth0Controller.php line 34 (which implements no exception-handling):
...
// Try to get the user information
$profile = $service->getUser();
...
The actual exceptions are raised by Auth0.php:
...
if (! $state || ! $this->transientHandler->verify(self::TRANSIENT_STATE_KEY, $state)) {
throw new CoreException('Invalid state');
}
if ($this->user) {
throw new CoreException('Can\'t initialize a new session while there is one active session already');
}
...
Note: This forum post helped to point us to the appropriate area of code: Invalid state (error 500) after PHP/SDK redirect - #4 by josh.cunningham