Reputation: 528
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.
Upvotes: 5
Views: 5358
Reputation: 174
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');
}
}
.......................
Upvotes: 0
Reputation: 62338
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.
Upvotes: 8