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