Ich schreibe ein kleines SMS-Gateway für ein paar Projekte,
Ich habe Laravel Passport-Authentifizierung implementiert ( Client-Berechtigungsnachweise gewähren Token )
Dann habe ich CheckClientCredentials
zur api-Middleware-Gruppe hinzugefügt:
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
'throttle:60,1',
'bindings',
\Laravel\Passport\Http\Middleware\CheckClientCredentials::class
],
];
Die Logik funktioniert gut. Jetzt muss ich in meinem Controller einen Client mit einem gültigen Token verknüpfen.
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);
});
Aus offensichtlichen Sicherheitsgründen kann ich niemals die Client-ID mit der Consumer-Anfrage senden, z. $client_id = $request->client_id;
.
Also keine Antworten ...
Ich konnte das Problem durch Verwendung meiner eigenen API beheben. Schließlich fand ich einen einfacheren Authentifizierungsfluss vor. Der Client muss bei jeder Anforderung seine ID und sein Geheimnis senden. Dann verbrauchte ich meine eigene /oauth/token
-Route mit den gesendeten Anmeldeinformationen.Esben PetersenBlogbeitrag .
Sobald das Zugriffstoken generiert wurde, füge ich es den Kopfzeilen der Symfony\Request
-Instanz hinzu, die gerade verarbeitet wird.
Meine letzte Ausgabe wie folgt:
<?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);
}
}
Ich habe die oben genannte Middleware in Verbindung mit der CheckClientCredentials
von Passport verwendet.
protected $middlewareGroups = [
'web' => [
...
],
'api' => [
'throttle:60,1',
'bindings',
\App\Http\Middleware\AddAccessTokenHeader::class,
\Laravel\Passport\Http\Middleware\CheckClientCredentials::class
],
];
Auf diese Weise konnte ich sicherstellen, dass $request->input('client_id')
zuverlässig ist und nicht gefälscht werden kann.
Es gibt eine knifflige Methode. Sie können die Methode des Handles in der Middleware CheckClientCredentials ändern. Fügen Sie einfach diese Zeile hinzu.
$request["oauth_client_id"] = $psr->getAttribute('oauth_client_id');
Dann können Sie client_id in der Controller-Funktion erhalten:
public function info(\Illuminate\Http\Request $request)
{
var_dump($request->oauth_client_id);
}
Das OAuth-Token und die Clientinformationen werden als protected Variable in der Eigenschaft Laravel\Passport\HasApiTokens (die Sie Ihrem Benutzermodell hinzufügen) gespeichert.
Fügen Sie einfach eine Getter-Methode zu Ihrem User-Modell hinzu, um die OAuth-Informationen anzuzeigen:
public function get_oauth_client(){
return $this->accessToken->client;
}
Dies gibt ein Eloquent-Modell für die oauth_clients-Tabelle zurück
Ich grub die CheckClientCredentials-Klasse ein und extrahierte, was ich brauchte, um den client_id
vom Token zu erhalten. aud
ist der Ort, an dem der client_id
gespeichert wird.
<?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')];
});
});
Es gibt nur wenige Stellen, an denen Sie dies ändern können, um einfach darauf zugreifen zu können. Dies ist jedoch Sache Ihrer Anwendung
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);
}
fügen Sie oben in Ihre Middleware-Datei ein. Dann können Sie mit request()->oauth_client_id
auf client_id zugreifen.
Ich benutze dies, um auf die authentifizierte Client-App zuzugreifen ...
$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;