Authentication & Session Management (Development Notes)
Please read the authentication usage instructions first as that provides some key information for understanding the below brief notes. See also Barry O'Donovan's PHP write up of the 2fa and user session management changes introduced in v5.3.0.
IXP Manager uses Laravel's standard authentication framework with Laravel's Eloquent ORM.
Multiple Sessions / Remember Me Cookies
The default Laravel functionality around remember me is a single shared token across multiple devices. In practice this never worked well for us (but this is most likely a consequence of using LaravelDoctrine). Regardless, we also wanted to expand the functionality to uniquely identify each session and allow other sessions to be logged out by the user.
SessionGuard and UserProvider
Most of the functionality exists in the session guard and user provider classes. We have overridden these here:
app/Services/Auth/SessionGuard.php
app/Services/Auth/EloquentUserProvider.php
Again, the idea is to minimise the changes required to the core Laravel framework (and Laravel Eloquent).
How It Works
When you log in and check remember me, IXP Manager will create a new UserRememberToken
database entry with a unique token and an expiry set to config( 'auth.guards.web.expire')
(note this is minutes).
Your browser will be sent a cookie named remember_web_xxxx
(where xxxx
is random). This cookie contains the encrypted token that was created (UserRememberToken
). IXP Manager uses this cookie to create a new authenticated session if your previous session has timed out, etc.
Note that this remember_web_xxxx
cookie has an indefinite expiry date - the actual expiring of the remember me session is handled by the expiry
field in the UserRememberToken
database entry.
When you subsequently make a request to IXP Manager:
- the SessionGuard (see the
user()
method) first tries to retrieve your session via the standard browser session cookie (laravel_session
). - If that does not exist or has expired, it then looks for
remember_web_xxxx
cookie and, if it exists, validates it and looks you in with a newlaravel_session
.
Two-Factor Authentication
Two-factor authentication (2fa) is implemented using the pragmarx/google2fa package via its Laravel bridge antonioribeiro/google2fa-laravel.
The database table for storing a user's secret key is user_2fa
. 2FA for a user is enabled if:
- there exists a
$user->user2FA
entity (one to one); and Auth::getUser()->user2FA->enabled
istrue
.
Once 2fa is enabled, the mechanism for enforcing it is the 2fa
middleware. This is applied to all authenticated http web requests via app/Providers/RouteServiceProvider.php
.
Avoiding 2fa on Remember Me Sessions
We use the antonioribeiro/google2fa-laravel bridge's PragmaRX\Google2FALaravel\Events\LoginSucceeded
event to update a user's remember me token via the listener IXP\Listeners\Auth\Google2FALoginSucceeded
. The update is to set user_remember_tokens.is_2fa_complete
to true
so that the SessionGuard knows to skip 2fa on these sessions.