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

Citti's avatar
Level 3

Use a Token API auth along with OAuth

So I have been using Passport to handle any OAuth requests which works perfectly. However there are some scenarios where I do not need a user instance to request an API endpoint. Static lists etc. I have created a middleware for that and it works fine. However there is another scenario when pulling things like lists where i want to give developers the freedom to either use the Token or OAuth to post to those endpoints. And struggling on how to do that...

Anyone have any insights?

I am thinking I could always call the Token middleware and then from the token middleware call the normal passport OAuth? Not really sure how i would go about doing that though.

Chaining would not work in this scenario because if one fails it would boot them out, where I want it to check for a token IF it does not exist THEN check OAuth token and follow normal behavior after that.

Route::group(['middleware' => 'token:auth:api',

Not seeing anywhere in the docs on how to do this. But maybe I am missing something.

Cheers

Citti

0 likes
8 replies
Citti's avatar
Level 3

unfortunately no. Great series though ;)

Indemnity83's avatar

by Token do you mean the personal access token that can be generated as part of Passport?

If so, this is already supported by Passport out of the box, just apply the auth:api middleware and developers can either pass a token received through the OAuth process, or a static Personal Access Token.

If instead you're trying to allow non authenticated access to an endpoint (and presumably adjust the response according to authentication state) then leave the middleware empty for the particular route, tell the controller you want to use the api authentication mechanism (instead of the default session based one). This will authenticate users if the Token is present, but doesn't immediately throw an error if the token is missing.

You can then check if the user is authenticated in your controller method:

class FooController extends Controller {

    /**
     * Create a new controller instance.
    */
    public function __construct()
    {
        \Auth::shouldUse('api');
    }

    // Route::get('foo/{bar}', 'FooController@show');
    public function show($bar) {
        if (\Auth::check()) {
            // user is authenticated
        } else {
            // user is not authenticated
        }
    }   

}
Citti's avatar
Level 3

no, not the personal access token. The PAT is just a short cut to creating an OAuth token... The "Token" i have created is a separate token that I check in the headers that is a non bearer token. I just check for Token

Uber docs describes this pretty well here: https://developer.uber.com/docs/riders/guides/authentication/introduction

there is OAuth 2.0 (which in laravel terms is Passport which would include the personal access token) Then there is the Token auth - which is what i have built on my end.

Now trying to leverage both on a single API endpoint.

Indemnity83's avatar

Hmm, ok so you have two different guards ...

I still think you're going to have to do the check in the controller, or make a third custom guard that does both checks for you. assuming your guards (in config/auth.php) look like this right now:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],

    'token' => [
        'driver' => 'token',
        'provider' => 'users',
    ],
],

I think you can just check both like this

if (\Auth::guard('api')->check()) {
    $user = \Auth::guard('api')->user();
}

if (\Auth::guard('token')->check()) {
    $user = \Auth::guard('token')->user();
}

if(! isset($user)) {
    abort(401, 'Not Authenticated');
}
Citti's avatar
Level 3

True. hmmm let me dig into that and give it a shot. Was hoping i could extract it out of the controller since this will be in multiple locations. but might just need to live with that. Ill give this a shot and report back. thanks for the idea though!

Indemnity83's avatar

I would make it work in one controller method; then you can extract that into the handle method of a custom middleware knowing you have something working at a simpler level.

If all you're after is the $user to be loaded, or an error thrown it might be as easy as:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Auth\AuthenticationException;

class MultiGuardAuthentication
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (\Auth::guard('api')->check()) {
            $user = \Auth::guard('api')->user();
        }

        if (\Auth::guard('token')->check()) {
            $user = \Auth::guard('token')->user();
        }

        if(! isset($user)) {
            throw new AuthenticationException;
        }

        \Auth::login($user);

        return $next($request);
    }

}

Please or to participate in this conversation.