web-dev-qa-db-fra.com

Laravel Passport Obtenir l'ID client par jeton d'accès

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;.

8
Walid Ammar

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é.

3
Walid Ammar

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);
}
9
Marsprobe

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

3
Adam Albright

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.

1
James Wagoner
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

0
phnix

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;

La source

0
bmatovu