With Fortify, a user is logged in, automatically, after registration. This might not be what you want for your application. Thankfully, the package is easily extensible.
This post is a walk-through on how to override the default behaviour and disable the auto-login.
Before we start, let's take a look at the package and try to understand what is happening behind the curtain. You register a user by hitting the /register
endpoint with the expected name
, email
, password
and password_confirmation
fields' values. On a successful login, you get redirected to the home
configuration option in your fortify's configuration file. The controller responsible for handling the registration request is RegisteredUserController
. Inside the controller class, there is another method–store
that handles the actual registration:
/**
* Create a new registered user.
*
* @param \Illuminate\Http\Request $request
* @param \Laravel\Fortify\Contracts\CreatesNewUsers $creator
* @return \Laravel\Fortify\Contracts\RegisterResponse
*/
public function store(Request $request,
CreatesNewUsers $creator): RegisterResponse
{
event(new Registered($user = $creator->create($request->all())));
$this->guard->login($user);
return app(RegisterResponse::class);
}
You can see that the registered user is logged in right after firing the Registered
event.
$this->guard->login($user);
A noob mentality will have you thinking you can easily comment out that line and you're good to go. Well, you could do that and your code temporarily behaves as expected but what happens when you run composer update/install
and your change is overridden––You are back to square one. You should never make changes to any code within the confines of the vendor
folder.
Create a folder and name it Responses
inside the Http
folder of your application. Inside, create a RegisterResponse
class that extends the FortifyRegisterResponse
class.
<?php
namespace App\Http\Responses;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Laravel\Fortify\Contracts\RegisterResponse as RegisterResponseContract;
class RegisterResponse extends FortifyRegisterResponse
{
/**
* Create an HTTP response that represents the object.
*
* @param \Illuminate\Http\Request $request
* @return \Symfony\Component\HttpFoundation\Response
*/
public function toResponse($request)
{
return $request->wantsJson()
? new JsonResponse('', 201)
: redirect()->intended(config('fortify.home'));
}
}
Take out everything inside the toResponse
method and replace it with code that will first log out the just logged in user by Fortify and then defers to the base class's implementation:
<?php
namespace App\Http\Responses;
use Illuminate\Contracts\Auth\StatefulGuard;
use Laravel\Fortify\Http\Responses\RegisterResponse as FortifyRegisterResponse;
class RegisterResponse extends FortifyRegisterResponse
{
protected $guard;
public function __construct(StatefulGuard $guard)
{
$this->guard = $guard;
}
public function toResponse($request)
{
$this->guard->logout();
return parent::toResponse($request);
}
}
Fortify's RegisteredUserController
accepts a stateful guard implementation on it's constructor. So, we are using the same approach so that the response object receives the same guard instance as that of the controller. Otherwise, we could have used the Auth
facade to logout the user.
The final step is to register the implementation in Fortify's service provider's boot method as in the following:
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
...
$this->app->singleton(
\Laravel\Fortify\Contracts\RegisterResponse::class,
\App\Http\Responses\RegisterResponse::class,
);
}
And that's all, folks!
This post appeared here first.
Top comments (0)