Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ferares's avatar

Laravel - Authentication through API

Hi, I'm building a frontend application using Laravel that consumes data from an API.

I need to authenticate users for access to certain views and said authentication is done through the before mentioned API like this: I send a username and password to the API and I either get an error or a session token to use for future authenticated requests.

My first idea is to store said token on Laravel's session and have the authentication guard check for its existence and validated it against and endpoint on the API.

I've tried doing this:

Http/Controllers/LoginController.php

...
public function authenticate(Request $request)
{
	$data = ['email' => $request->email, 'password' => $request->password];
	$apiUrl = env('API_URL', '');
	$response = Http::asForm()->post("$apiUrl/admin/login", $data);
	if ($response->status() === 200) {
		$apiSession = $response->cookies()->getCookieByName('session')->getValue();
		$request->session()->regenerate();
        $request->session()->put('token', $apiSession);
        return redirect(route('admin'));
	}
	// Else => Login error handling
	...
}
...

routes/web.php :

...
$router->get('/admin', [AdminController::class, 'admin'])->middleware('auth')->name('admin');
...

Http/Middleware/Authenticate.php

namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{
    protected function redirectTo($request)
    {
        if (!$request->expectsJson()) {
            return route('login');
        }
    }
}

But after login in successfully I get redirected back to the login form.

I thought that the $request->session()->regenerate(); was the call to make so Laravel's default auth logic would see the current session as an authenticated one but I guess not.

Can anyone tell me what am I missing? or if I'm going at it in a wrong way.

Thank you!

P.S.: I've also changed the SESSION_DRIVER environment variable to be cookie.

0 likes
4 replies
rodrigo.pedra's avatar

Take a look on how it is implemented in laravel/ui

https://github.com/laravel/ui/blob/197359ff31d3c22dad757acfb802e9bcb537c238/auth-backend/AuthenticatesUsers.php

If youa re going to use the auth middleware, you need to tell Laravel how to retrieve the current auth data.

By default will try to use some known auth stack, it won't just guess how you named your "token" variable in the session.

If you want to write a custom auth driver, so you can store your custom token, check the docs:

Maybe going with a custom request guard would be easier

Lastly, you can write a custom middleware for checking your authenticated user.

ferares's avatar

@rodrigo.pedra I've read these docs before but all these solutions seem to work with a User model and a user provider. I thought there might be a simpler solution in my case since all I have to do is check for the presence of a token and validate it against the API.... It's looking like there's no simple way to do that and I'll have to create a user model and provider, right?

rodrigo.pedra's avatar
Level 56

@ferares well, Laravel Auth expects an user object, not necessarily an Eloquent User model from a database.

This user object it expects is just required to implement the Illuminate\Contracts\Auth\Authenticatable. It can be a plain PHP object.

You can use the Request Guard if you don't want to create a custom user provider, and return an instance of the Illuminate\Auth\GenericUser class, which implements Illuminate\Contracts\Auth\Authenticatable.

This class requires an attribute named id to be the auth identifier, which in your case can be your session token:

use Illuminate\Auth\GenericUser;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
 
// in a ServiceProvider class
public function boot()
{
    $this->registerPolicies();
 
    Auth::viaRequest('custom-token', function (Request $request) {
        // do any necessary authentication logic
        $token = $request->input('token');

        return new GenericUser(['id' => $token]);
    });
}

There is a previous thread where I built a external API user provider along with another user. It might be helpful to your use case too:

https://laracasts.com/discuss/channels/code-review/custom-user-provider

1 like
ferares's avatar

@rodrigo.pedra That was it, thank you!

For completion here's the relevant code:

app/providers/AuthServiceProvider.php

...
public function boot()
    {
        $this->registerPolicies();
        
        Auth::viaRequest('custom-token', function (Request $request) {
            // Get the API's token from the session
            $token = $request->session()->get('token');
            if (!$token) return null;
            // Verify the token against the API
            $apiUrl = env('API_URL', '');
    		$apiDomain = parse_url($apiUrl)['host'];
   		$cookies = CookieJar::fromArray(['session' => $token], $apiDomain);
            try {
                $response = Http::withOptions(['cookies' => $cookies])->get("$apiUrl/admin/verify");
            } catch (\Throwable $th) {
                return abort(500);
            }
            if ($response->status() !== 200) {
                return null;
            }
            // Return a user instance
            return new GenericUser(['id' => $token]);
        });
    }
...

app/config/auth.php

...
'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
       // Custom guard with the custom-token driver
        'api' => [
            'driver' => 'custom-token',
        ],
    ],
...
1 like

Please or to participate in this conversation.