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

schroedermatthias's avatar

Passport: Use token-based authentication also for web requests.

Dear Laravel community!

I implemented my api authentication with Laravel Passport according to this tutorial: https://youtu.be/HGh0cKEVXPI and https://youtu.be/GRhkhSzyApc

What happens here?

  • Installed Passport
  • Implemented own AuthController (see below)
  • Authentication happens via ajax request to /login (with username and password)
  • AuthController does a guzzle request to the OAuth2 endpoint of Passport
  • Access token is returned
  • JavaScript uses access_token for further requests (bearer)

This works like a charm for "regular API calls". Now I have to deliver images, that are protected (belong to a specific user). For this, I need authentication also on the web layer. As <img src="xyz" /> does a regular GET request (without the possibility to add the bearer header), I would like to deliver the protected image via a "regular web route".

Why not delivering the images also via api?

  • <img src="xyz" /> does no API-Call (no XHR / no accept: application/json)
  • base64 encoded images are bigger and more difficult to cache on the client side

My question is: How to "reuse" the existing api authentication for web requests? Is there a way to also authenticate the user for web requests (with cookie, I guess), when authenticating for the api?

My current setup:

routes/api.php:

<?php

Route::post('/login', 'AuthController@login');
Route::post('/register', 'AuthController@register');

Route::middleware('auth:api')->group(function () {
    Route::post('/logout', 'AuthController@logout');
    Route::post('/projects', 'Api\ProjectController@search');
    Route::put('/projects', 'Api\ProjectController@save');
    Route::patch('/projects', 'Api\ProjectController@update');
    Route::delete('/projects', 'Api\ProjectController@delete');
});

routes/web.php:

<?php

Route::get('/', 'FrontendController@index'); // Entry point for SPA
Route::get('/documents/thumbnails/{project}.png', 'ProjectController@thumbnail')->middleware('auth'); // Route for protected images

AuthController->login():

    /**
     * @param Request $request
     *
     * @return \Illuminate\Http\JsonResponse|\Psr\Http\Message\StreamInterface
     */
    public function login(Request $request)
    {
        $http = new \GuzzleHttp\Client(['defaults' => ['verify' => false]]);

        try {
            $response = $http->post(config('services.passport.login_endpoint'), [
                'form_params' => [
                    'grant_type'    => 'password',
                    'client_id'     => config('services.passport.client_id'),
                    'client_secret' => config('services.passport.client_secret'),
                    'username'      => $request->username,
                    'password'      => $request->password,
                ],
            ]);

            return $response->getBody();
        } catch (BadResponseException $badResponseException) {
            if ($badResponseException->getCode() === 400) {
                return response()->json(__('auth.invalid'), $badResponseException->getCode());
            } else if ($badResponseException->getCode() === 401) {
                return response()->json(__('auth.failed'), $badResponseException->getCode());
            }

            return response()->json(__('auth.error'), $badResponseException->getCode());
        }
    }

config/auth.php:

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

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

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

.env:

PASSPORT_LOGIN_ENDPOINT=http://my-project.local/oauth/token
PASSPORT_CLIENT_ID=2
PASSPORT_CLIENT_SECRET=rYtVGQsJh498hiajbfi1bnrgUc8phZ3vV

Thank you very much for your time.

Matthias

0 likes
4 replies
schroedermatthias's avatar

As nobody replied, I guess that my question was too unclear. So let me put it a bit more simple.

I am providing and API that authenticates JWT based (Passport). How to deliver images that are access protected (belong to a specific) user?

The difference to a "regular" API call is, that here the Header "Authorization Bearer xyz" is passed, but when loading an image via GET there can be no header and [url]/image.png?access_token=xyz does not seem to work.

What are your architectural suggestions?

Thanks a lot Matthias

MortenS's avatar

Have you tried using api_token as a GET param in stead of access_token?

erikleon's avatar

Where you ever able to figure out a solution. Having a similar problem and don't know what to do.

Please or to participate in this conversation.