J'écris une petite passerelle de sms pour être consommée par deux projets,
J'ai implémenté l'authentification par passeport laravel ( jeton d'octroi des identifiants client )
Ensuite, j'ai ajouté CheckClientCredentials
au groupe de middleware api:
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
'throttle:60,1',
'bindings',
\Laravel\Passport\Http\Middleware\CheckClientCredentials::class
],
];
La logique fonctionne bien, maintenant, dans mon contrôleur, je dois associer le client à un jeton valide.
routes.php
Route::post('/sms', function(Request $request) {
// save the sms along with the client id and send it
$client_id = ''; // get the client id somehow
sendSms($request->text, $request->to, $client_id);
});
Pour des raisons évidentes de sécurité, je ne peux jamais envoyer l'ID client avec la demande du consommateur, par exemple. $client_id = $request->client_id;
.
Donc, pas de réponse ...
J'ai pu résoudre le problème en consommant ma propre API. Finalement, je suis arrivé avec un flux d'authentification plus simple, le client doit envoyer son identifiant et son secret à chaque demande, puis j'ai utilisé mon propre itinéraire /oauth/token
avec les informations d'identification envoyées, inspiré par Esben Petersenarticle de blog .
Une fois le jeton d'accès généré, je l'ajoute aux en-têtes de l'instance Symfony\Request
en cours de traitement.
Mon dernier résultat comme ceci:
<?php
namespace App\Http\Middleware;
use Request;
use Closure;
class AddAccessTokenHeader
{
/**
* Octipus\ApiConsumer
* @var ApiConsumer
*/
private $apiConsumer;
function __construct() {
$this->apiConsumer = app()->make('apiconsumer');
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$response = $this->apiConsumer->post('/oauth/token', $request->input(), [
'content-type' => 'application/json'
]);
if (!$response->isSuccessful()) {
return response($response->getContent(), 401)
->header('content-type', 'application/json');
}
$response = json_decode($response->getContent(), true);
$request->headers->add([
'Authorization' => 'Bearer ' . $response['access_token'],
'X-Requested-With' => 'XMLHttpRequest'
]);
return $next($request);
}
}
J'ai utilisé le middleware ci-dessus en conjonction avec CheckClientCredentials
de Passport.
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
'throttle:60,1',
'bindings',
\App\Http\Middleware\AddAccessTokenHeader::class,
\Laravel\Passport\Http\Middleware\CheckClientCredentials::class
],
];
De cette façon, j'ai pu m'assurer que $request->input('client_id')
est fiable et ne peut être falsifié.
Il y a une méthode délicate. Vous pouvez modifier la méthode de traitement dans le middleware CheckClientCredentials, ajoutez simplement cette ligne.
$request["oauth_client_id"] = $psr->getAttribute('oauth_client_id');
Ensuite, vous pouvez obtenir client_id dans la fonction du contrôleur:
public function info(\Illuminate\Http\Request $request)
{
var_dump($request->oauth_client_id);
}
Le jeton OAuth et les informations client sont stockés sous la forme d'une variable protected dans le trait Laravel\Passport\HasApiTokens (que vous ajoutez à votre modèle User).
Ajoutez donc simplement une méthode getter à votre modèle User pour exposer les informations OAuth:
public function get_oauth_client(){
return $this->accessToken->client;
}
Cela retournera un modèle Eloquent pour la table oauth_clients
J'ai creusé dans la classe CheckClientCredentials et extrait ce dont j'avais besoin pour obtenir le client_id
à partir du jeton. La réclamation aud
correspond au lieu où le client_id
est stocké.
<?php
Route::middleware('client')->group(function() {
Route::get('/client-id', function (Request $request) {
$jwt = trim(preg_replace('/^(?:\s+)?Bearer\s/', '', $request->header('authorization')));
$token = (new \Lcobucci\JWT\Parser())->parse($jwt);
return ['client_id' => $token->getClaim('aud')];
});
});
Peu de lieux pour le refactoriser afin de pouvoir y accéder facilement, mais cela dépendra de votre application.
public function handle($request, Closure $next, $scope)
{
if (!empty($scope)) {
$psr = (new DiactorosFactory)->createRequest($request);
$psr = $this->server->validateAuthenticatedRequest($psr);
$clientId = $psr->getAttribute('oauth_client_id');
$request['oauth_client_id'] = intval($clientId);
}
return $next($request);
}
mettez ci-dessus dans votre fichier middleware, vous pourrez alors accéder à client_id par request()->oauth_client_id
J'utilise ceci pour accéder à l'application client authentifiée ...
$bearerToken = $request->bearerToken();
$tokenId = (new \Lcobucci\JWT\Parser())->parse($bearerToken)->getHeader('jti');
$client = \Laravel\Passport\Token::find($tokenId)->client;
$client_id = $client->id;
$client_secret = $client->secret;