【问题标题】:Verify third party JWT with Laravel使用 Laravel 验证第三方 JWT
【发布时间】:2022-01-21 14:53:48
【问题描述】:

我正在使用外部身份提供者对用户进行身份验证,创建了一个 SPA 客户端(获得了client_idclient_secret),使用audiencescope 配置了API,因此一旦用户通过身份验证,他们将获得access_token (将被授权)访问多个自定义微服务 (API)。

当我的自定义 API 收到带有不记名访问令牌 (JWT) 的请求时,首先要做的是验证令牌。为了验证 JWT,我需要执行以下步骤:

  1. 检查 JWT 格式是否正确(解析 JWT)
  2. 检查签名。我的外部身份提供者仅通过 JWKS (JSON Web Key Set) URL (https://{domain}/.well-known/jwks.json) 支持 RS256,因此我可以通过此 URL 获取我的公钥。
  3. 验证标准声明
  4. 检查应用程序权限(范围)

有很多包/库(即https://github.com/tymondesigns/jwt-auth)可以创建 JWT 令牌,但我找不到使用上述步骤验证它的任何包/库。任何人都可以帮助找到合适的 Laravel/PHP 包/库或将我带向正确的方向以实现我的目标(尤其是第 2 点)。

【问题讨论】:

    标签: php laravel jwt


    【解决方案1】:

    我过去做过类似的事情,我不知道这是否会有所帮助,但我会试一试。要使用公钥,您应该下载它,将其放在磁盘上的某个位置(例如storage/jwt/public.pem),然后将其链接到 jwt 配置 config/jwt.php 与 ALGO(您可以看到支持的算法 here

        'keys' => [
            // ...    
            'public' => 'file://'.storage_path('jwt/public.pem'),
            // ...
        ],
        'algo' => 'RS256', 
    

    那么,你应该有一个自定义的 Guard,我们称之为 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 = []) {    }
    }
    

    这应该完成所有验证逻辑,我使用了自定义用户实现,类签名如下:

    use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
    use Illuminate\Database\Eloquent\Model;
    class User extends Model implements AuthenticatableContract {
        // custom implementation
    }
    

    最后,你应该在 AuthServiceProvider 和 auth 配置中注册守卫

    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();
    }
    

    这听起来不错吗?

    【讨论】:

    • 谢谢,它会起作用,我已将其标记为正确答案。
    【解决方案2】:

    最后我使用了 Laravel 的 Auth0 SDK - https://auth0.com/docs/quickstart/backend/laravel/01-authorization。干净整洁的解决方案。

    【讨论】:

      猜你喜欢
      • 2017-01-06
      • 1970-01-01
      • 2016-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-03-18
      • 2020-01-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多