使用 Laravel 验证第三方 JWT
Verify third party JWT with Laravel
我正在使用外部身份提供程序对用户进行身份验证,创建了一个 SPA 客户端(得到 client_id
& client_secret
),配置 API 和 audience
& scope
,因此一旦用户通过身份验证,他们将获得 access_token
(将被授权)访问多个自定义微服务(APIs)。
当我的自定义 API 收到带有不记名访问令牌 (JWT) 的请求时,要做的第一件事就是验证令牌。为了验证 JWT,我需要执行以下步骤:
- 检查 JWT 是否格式正确(解析 JWT)
- 检查签名。我的外部身份提供者仅通过 JWKS(JSON Web 密钥集)URL (https://{domain}/.well-known/jwks.json) 支持 RS256,所以我可以在 URL.
之后得到我的 public 密钥
- 验证标准声明
- 检查应用程序权限(范围)
有很多 packages/libraries(即 https://github.com/tymondesigns/jwt-auth)来创建 JWT 令牌,但我找不到任何可以使用上述步骤验证它的方法。谁能帮我找到合适的 Laravel/PHP package/library 或让我朝着正确的方向前进以实现我的目标(尤其是第 2 点)。
我过去做过类似的事情,我不知道这是否有帮助,但我会试一试。要使用 public 密钥,您应该下载它,将它放在磁盘上的某个位置(例如 storage/jwt/public.pem
)然后 link 它在 jwt 配置 config/jwt.php
中与 ALGO (可以看到支持的算法here
'keys' => [
// ...
'public' => 'file://'.storage_path('jwt/public.pem'),
// ...
],
'algo' => 'RS256',
那么,你应该有一个自定义的守卫,我们称之为 JWTGuard:
<?php
namespace App\Guard;use App\Models\User;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWT;class JWTGuard implements Guard
{
use GuardHelpers;
/**
* @var JWT $jwt
*/
protected JWT $jwt;
/**
* @var Request $request
*/
protected Request $request;
/**
* JWTGuard constructor.
* @param JWT $jwt
* @param Request $request
*/
public function __construct(JWT $jwt, Request $request) {
$this->jwt = $jwt;
$this->request = $request;
}
public function user() {
if (! is_null($this->user)) {
return $this->user;
}
if ($this->jwt->setRequest($this->request)->getToken() && $this->jwt->check()) {
$id = $this->jwt->payload()->get('sub');
$this->user = new User();
$this->user->id = $id;
// Set data from custom claims
return $this->user;
}
return null;
}
public function validate(array $credentials = []) { }
}
这应该完成所有验证逻辑,我使用了自定义用户实现,class 签名如下:
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements AuthenticatableContract {
// custom implementation
}
最后,您应该在 AuthServiceProvider 和身份验证配置中注册守卫
public function boot()
{
$this->registerPolicies();
$this->app['auth']->extend(
'jwt-auth',
function ($app, $name, array $config) {
$guard = new JWTGuard(
$app['tymon.jwt'],
$app['request']
);
$app->refresh('request', $guard, 'setRequest');
return $guard;
}
);
}
然后在配置中允许它
<?php
return [
'defaults' => [
'guard' => 'jwt',
'passwords' => 'users',
],
'guards' => [
// ...
'jwt' => [
'driver' => 'jwt-auth',
'provider' => 'users'
],
],
// ...
];
然后您可以像这样将它用作中间件:
Route::middleware('auth:jwt')->get('/user', function() {
return Auth::user();
}
这听起来不错吗?
最后,我在 Laravel - https://auth0.com/docs/quickstart/backend/laravel/01-authorization 中使用了 Auth0 SDK。干净整洁的解决方案。
我正在使用外部身份提供程序对用户进行身份验证,创建了一个 SPA 客户端(得到 client_id
& client_secret
),配置 API 和 audience
& scope
,因此一旦用户通过身份验证,他们将获得 access_token
(将被授权)访问多个自定义微服务(APIs)。
当我的自定义 API 收到带有不记名访问令牌 (JWT) 的请求时,要做的第一件事就是验证令牌。为了验证 JWT,我需要执行以下步骤:
- 检查 JWT 是否格式正确(解析 JWT)
- 检查签名。我的外部身份提供者仅通过 JWKS(JSON Web 密钥集)URL (https://{domain}/.well-known/jwks.json) 支持 RS256,所以我可以在 URL. 之后得到我的 public 密钥
- 验证标准声明
- 检查应用程序权限(范围)
有很多 packages/libraries(即 https://github.com/tymondesigns/jwt-auth)来创建 JWT 令牌,但我找不到任何可以使用上述步骤验证它的方法。谁能帮我找到合适的 Laravel/PHP package/library 或让我朝着正确的方向前进以实现我的目标(尤其是第 2 点)。
我过去做过类似的事情,我不知道这是否有帮助,但我会试一试。要使用 public 密钥,您应该下载它,将它放在磁盘上的某个位置(例如 storage/jwt/public.pem
)然后 link 它在 jwt 配置 config/jwt.php
中与 ALGO (可以看到支持的算法here
'keys' => [
// ...
'public' => 'file://'.storage_path('jwt/public.pem'),
// ...
],
'algo' => 'RS256',
那么,你应该有一个自定义的守卫,我们称之为 JWTGuard:
<?php
namespace App\Guard;use App\Models\User;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Tymon\JWTAuth\JWT;class JWTGuard implements Guard
{
use GuardHelpers;
/**
* @var JWT $jwt
*/
protected JWT $jwt;
/**
* @var Request $request
*/
protected Request $request;
/**
* JWTGuard constructor.
* @param JWT $jwt
* @param Request $request
*/
public function __construct(JWT $jwt, Request $request) {
$this->jwt = $jwt;
$this->request = $request;
}
public function user() {
if (! is_null($this->user)) {
return $this->user;
}
if ($this->jwt->setRequest($this->request)->getToken() && $this->jwt->check()) {
$id = $this->jwt->payload()->get('sub');
$this->user = new User();
$this->user->id = $id;
// Set data from custom claims
return $this->user;
}
return null;
}
public function validate(array $credentials = []) { }
}
这应该完成所有验证逻辑,我使用了自定义用户实现,class 签名如下:
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Model;
class User extends Model implements AuthenticatableContract {
// custom implementation
}
最后,您应该在 AuthServiceProvider 和身份验证配置中注册守卫
public function boot()
{
$this->registerPolicies();
$this->app['auth']->extend(
'jwt-auth',
function ($app, $name, array $config) {
$guard = new JWTGuard(
$app['tymon.jwt'],
$app['request']
);
$app->refresh('request', $guard, 'setRequest');
return $guard;
}
);
}
然后在配置中允许它
<?php
return [
'defaults' => [
'guard' => 'jwt',
'passwords' => 'users',
],
'guards' => [
// ...
'jwt' => [
'driver' => 'jwt-auth',
'provider' => 'users'
],
],
// ...
];
然后您可以像这样将它用作中间件:
Route::middleware('auth:jwt')->get('/user', function() {
return Auth::user();
}
这听起来不错吗?
最后,我在 Laravel - https://auth0.com/docs/quickstart/backend/laravel/01-authorization 中使用了 Auth0 SDK。干净整洁的解决方案。