How to test authentication via API with Laravel Passport?

前端 未结 7 1110
轮回少年
轮回少年 2020-12-24 07:55

I\'m trying to test the authentication with Laravel\'s Passport and there\'s no way... always received a 401 of that client is invalid, I\'ll leave you what I\'ve tried:

7条回答
  •  星月不相逢
    2020-12-24 08:22

    I wasn't familiar with the Passport tool that Dwight is referring to when I wrote this, so it's possible that's a simpler solution. But here's something that may help. It produces a token for you, that you can then apply to your mock-API call.

    /**
     * @param Authenticatable $model
     * @param array $scope
     * @param bool $personalAccessToken
     * @return mixed
     */
    public function makeOauthLoginToken(Authenticatable $model = null, array $scope = ['*'], $personalAccessToken = true)
    {
        $tokenName = $clientName = 'testing';
        Artisan::call('passport:client', ['--personal' => true, '--name' => $clientName]);
        if (!$personalAccessToken) {
            $clientId = app(Client::class)->where('name', $clientName)->first(['id'])->id;
            Passport::$personalAccessClient = $clientId;
        }
        $userId = $model->getKey();
        return app(PersonalAccessTokenFactory::class)->make($userId, $tokenName, $scope)->accessToken;
    }
    

    Then you an just apply it to the headers:

    $user = app(User::class)->first($testUserId);
    $token = $this->makeOauthLoginToken($user);
    $headers = ['authorization' => "Bearer $token"];
    $server = $this->transformHeadersToServerVars($headers);
    
    $body = $cookies = $files = [];
    $response = $this->call($method, $uri, $body, $cookies, $files, $server);
    
    $content = $response->getContent();
    $code = $response->getStatusCode();
    

    If you need to be able to parse the token, try this:

    /**
     * @param string $token
     * @param Authenticatable $model
     * @return Authenticatable|null
     */
    public function parsePassportToken($token, Authenticatable $model = null)
    {
        if (!$model) {
            $provider = config('auth.guards.passport.provider');
            $model = config("auth.providers.$provider.model");
            $model = app($model);
        }
        //Passport's token parsing is looking to a bearer token using a protected method.  So a dummy-request is needed.
        $request = app(Request::class);
        $request->headers->add(['authorization' => "Bearer $token"]);
        //Laravel\Passport\Guards\TokenGuard::authenticateViaBearerToken() expects the user table to leverage the
        //HasApiTokens trait.  If that's missing, a query macro can satisfy its expectation for this method.
        if (!method_exists($model, 'withAccessToken')) {
            Builder::macro('withAccessToken', function ($accessToken) use ($model) {
                $model->accessToken = $accessToken;
                return $this;
            });
            /** @var TokenGuard $guard */
            $guard = Auth::guard('passport');
            return $guard->user($request)->getModel();
        }
        /** @var TokenGuard $guard */
        $guard = Auth::guard('passport');
        return $guard->user($request);
    }
    

提交回复
热议问题