When issuing access and refresh tokens I send them to the frontend with httpOnly = true. I made a middleware class which checks if the access token has expired and if the refresh token hasn't expired. If both are the case I call the oauth/token route with refresh_token as grant_type.
All of this works, however I'm not sure how to use the authenticated user inside the controllers. Right now I've set the middleware up that when there's a response it sends the new access and refresh token.
class RefreshAccessToken
{
/* #var AuthController $authController */
private $authController;
/**
* RefreshAccessToken constructor.
*
* #param AuthController $authController
*/
public function __construct(AuthController $authController)
{
$this->authController = $authController;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
// User already has an access token
if ($request->hasCookie('access_token')) {
return $next($request);
}
// User doesn't have an access token and doesn't have a refresh token.
if (!$request->hasCookie('refresh_token')) {
return $next($request);
}
$response = $next($request);
$cookies = $this->authController->refreshToken($request);
return $response
->cookie($cookies['access_token'])
->cookie($cookies['refresh_token']);
}
}
Now inside a controller if I want to access the logged in user I always get null as a response:
public function logout()
{
dd(auth()->user());
}
}
Inside the controller's construct method:
$this->middleware('auth:api')->only('logout');
Does anyone know how to handle this use case?
Related
I'm working on Laravel API Authentication. I have done login, register part. when I want to get-details of any user using postman every time i need add Bearer access_token in request header.
But I want to send it from my Backend Controller or Middleware .
How can i do this.
Here is my Code Sample. I try this way But not working.
public function details(Request $request)
{
$user = Auth::user();
$token='Bearer '.$request->bearerToken();
$request->header('Authorization',$token);
return response()->json(['success' => $user], $this-> successStatus);
}
I do this in middleware, for example:
<?php
namespace App\Http\Middleware;
use Closure;
class AccessTokenMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$request->headers->add(['Authorization' => "Bearer {$request->access_token}"]);
return $next($request);
}
}
I'm newbie for Laravel passport. What I want to achieve is able to verify whether there is access token pass in by user.
I want to call #index route when there are access token found,
call #indexTest route when no access token is found.
Do I have to create custom middleware for this case?
Thanks.
In api.php
/**
* Category
*/
Route::resource('categoriesbranches', 'Category\CategoryBranchController#index', ['only' => ['index']])->middleware('client.credentials');
Route::resource('categoriesbranches', 'Category\CategoryBranchController#indexTest');
In CategoryBranchController.php
// public function __construct()
// {
// $this->middleware('client.credentials')->only(['index']);
// }
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
//different action
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function indexTest()
{
//different action
}
Yes, you need to create a middleware and check for access token and then redirect the call where you want, if it has the access token you just $next($request)
You can crate a middleware and add a before middleware method to check if the request has token even before any routing.
https://lumen.laravel.com/docs/5.6/middleware
I've set up a laravel app with client authentification. I send it my client id and client secret and it gives me a token. I'm able to log in to my laravel app, but I can't figure out how to get the id of the client that's been authorized.
I've seen hints to use auth()->user()->Token()->getAttribute('client_id') to get the client id, but since I'm only using clients there is no user and I get an error about trying to call Token() on a null object. Auth::id() also returned nothing. I grabbed the token from the header with Request::header('Authorization'), but it didn't match anything in the database.
I'm assuming you're using client credentials grant tokens, and the CheckClientCredentials middleware.
You can get this information from the bearer token, but it's not that straightforward. You would need to create a new PSR7 request with the token, and send it off to the oauth server to have it converted to readable data.
This is already done inside the CheckClientCredentials middleware provided by Passport. So, one way to do this would be to extend the CheckClientCredentials middleware and just manually set the needed fields on the request object from inside the middleware.
First, create app/Http/Middleware/MyCheckClientCredentials.php:
namespace App\Http\Middleware;
use Closure;
use Illuminate\Auth\AuthenticationException;
use League\OAuth2\Server\Exception\OAuthServerException;
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
use Laravel\Passport\Http\Middleware\CheckClientCredentials;
class MyCheckClientCredentials extends CheckClientCredentials
{
/**
* The Resource Server instance.
*
* #var \League\OAuth2\Server\ResourceServer
*/
private $server;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param mixed ...$scopes
* #return mixed
* #throws \Illuminate\Auth\AuthenticationException
*/
public function handle($request, Closure $next, ...$scopes)
{
$psr = (new DiactorosFactory)->createRequest($request);
try {
$psr = $this->server->validateAuthenticatedRequest($psr);
// This is the custom line. Set an "oauth_client_id" field on the
// request with the client id determined by the bearer token.
$request['oauth_client_id'] = $psr->getAttribute('oauth_client_id');
} catch (OAuthServerException $e) {
throw new AuthenticationException;
}
$this->validateScopes($psr, $scopes);
return $next($request);
}
}
Next, update your app/Http/Kernel.php to use your custom middleware instead of the build in Passport middleware:
protected $routeMiddleware = [
'client' => \App\Http\Middleware\MyCheckClientCredentials::class,
];
Apply the middleware to your route as normal:
Route::get('/user', function(Request $request) {
// Should show "oauth_client_id" field.
dd($request->all());
})->middleware('client');
If you don't want to do this inside a middleware, you can study how the Passport middleware works and reuse this code in some type of service if you'd like.
NB: all untested.
I had to do something similar in a logger middleware of mine:
.......................
$user = $request->user();
if($user) {
// assume the authorization header exists, since the user is authenticated
$header = $request->headers->get('authorization');
if($header) { // authorization header is not set when testing via Passport::actingAs()
/**
* Stolen from League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator#63
*/
// Get the actual jwt string from the header
$jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $header));
// Parse the token from the string
$token = (new Lcobucci\JWT\Parser())->parse($jwt);
// Get the ID from the token
$oauthClientId = $token->getClaim('aud');
}
}
.......................
I have a Laravel API (actually a Lumen API) serving a VueJS front-end. The Vue app allows users to login to Google. The Google token is then sent back to the Lumen API, which verifies the token with Google, then verifies that the email address is a valid user. Then it generates a token, stores that in the DB with the user and returns the user object.
I'm not using Passport or jwt-auth or anything like that. So now, how do I go about using the default Auth middleware to verify the token header that the (now logged in) user will be returning with every request? (i.e. is the token in the DB and is it expired?). And is there a way to do this more efficiently, so Laravel caches the valid tokens and doesn't have to hit the DB for every request?
You can use the Authentication Middleware. Pass with your request an api_token. A more detailed answer can be found here.
Add a api_token column to your User table.
$table->string('api_token', 60)->unique();
Have an authentication middleware as such:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('auth/login');
}
}
return $next($request);
}
}
And use Route Group
Route::group(['middleware' => 'auth:api'], function () {
Route::resource('api/v1/foo/bar', 'API\FooBarController');
}
Im using the Auth controller in Laravel along with the auth middleware.
If the user is not logged in it redirects to:
auth/login
But I wish to redirect to a different url.
I have this in my auth controller:
protected $loginPath = '/cms/login';
protected $redirectTo = '/cms';
But it still redirects to:
auth/login
How can I redirect the auth controller?
The path for the redirect when you're not logged in is handled in the authenticates middleware, which is found at app/Http/Middleware/Authenticate.php.
Redirection will be handled by middleware. Hence change the redirect under handle() method in auth middleware as follows:
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest())
{
if ($request->ajax())
{
//return response('Unauthorized.', 401);
}
else
{
//return redirect()->guest('auth/login');
return redirect()->guest('cms/login');
}
}
return $next($request);
}