代码之家  ›  专栏  ›  技术社区  ›  Denis Priebe

拉维尔护照-测试密码授权

  •  0
  • Denis Priebe  · 技术社区  · 6 年前

    我正在使用Laravel 5.7和Passport为第一方客户机创建一个API。我有一个登录表单,它接受用户的电子邮件和密码,并将两者发送到自定义登录控制器。然后,LoginController创建一个oAuth负载,发送一个 POST 请求 oauth/token 通过Guzzle将访问令牌、刷新令牌和其他所有内容返回给我的第一方客户端。

    这是我的对应代码:

    登录控制器

    <?php
    
    namespace App\Http\Controllers\Api;
    
    use App\Domain\Auth\PasswordGrant;
    use App\Http\Requests\LoginRequest;
    
    class LoginController extends ApiController
    {
        /**
         * LoginController constructor.
         */
        public function __construct()
        {
            $this->middleware('api')->only('login');
        }
    
        /**
         * Attempt to authenticate the user with the credentials they provided
         * and if successful, return an access token for the user.
         *
         * @param LoginRequest $request
         * @return \Illuminate\Http\Response
         */
        public function login(LoginRequest $request)
        {
            return PasswordGrant::attempt($request->email, $request->password);
        }
    }
    

    <?php
    
    namespace App\Domain\Auth;
    
    use GuzzleHttp\Client as GuzzleHttp;
    use GuzzleHttp\Exception\ClientException;
    use Laravel\Passport\Client;
    
    class PasswordGrant
    {
        /**
         * The GuzzleHttp client instance.
         *
         * @var GuzzleHttp
         */
        protected $http;
    
        /**
         * PasswordGrant constructor.
         *
         * @param GuzzleHttp $http
         */
        public function __construct(GuzzleHttp $http)
        {
            $this->http = $http;
        }
    
        /**
         * @param $username
         * @param $password
         * @return \Illuminate\Http\Response
         */
        public static function attempt($username, $password)
        {
            $passwordGrant = resolve(static::class);
    
            $payload = $passwordGrant->oAuthPayload(
                $passwordGrant->oAuthClient(), $username, $password
            );
    
            return $passwordGrant->oAuthResponse($payload);
        }
    
        /**
         * Get the oAuth Client we are using to authenticate our login and user.
         *
         * @return Client
         */
        protected function oAuthClient()
        {
            return Client::query()
                ->where('name', config('api.password_client'))
                ->where('password_client', true)
                ->where('revoked', false)
                ->firstOrFail();
        }
    
        /**
         * The payload we need to send to our oAuth server in order to receive
         * a bearer token and authenticate the user.
         *
         * @param Client $client
         * @param $username
         * @param $password
         * @return array
         */
        protected function oAuthPayload(Client $client, $username, $password)
        {
            return [
                'form_params' => [
                    'grant_type' => 'password',
                    'client_id' => $client->id,
                    'client_secret' => $client->secret,
                    'username' => $username,
                    'password' => $password,
                    'scope' => '*'
                ]
            ];
        }
    
        /**
         * Get the response from our oAuth server.
         *
         * @param array $payload
         * @return \Illuminate\Http\Response
         */
        protected function oAuthResponse(array $payload)
        {
            try {
    
                return $this->http->post(route('passport.token'), $payload)->getBody();
    
            } catch (ClientException $exception) {
    
                return response($exception->getMessage(), $exception->getCode());
    
            }
        }
    }
    

    密码格兰特

    <?php
    
    namespace Tests\Feature\Requests\Team;
    
    use App\Domain\Auth\PasswordGrant;
    use App\Models\User;
    use Illuminate\Foundation\Testing\RefreshDatabase;
    use Illuminate\Support\Facades\Artisan;
    use Tests\TestCases\TestCase;
    
    class PasswordGrantTest extends TestCase
    {
        use RefreshDatabase;
    
        /** @test */
        public function it_returns_an_access_token_for_a_user_with_valid_credentials()
        {
            Artisan::call('passport:client', [
                '--password' => true,
                '--name' => config('api.password_client')
            ]);
    
            $user = create(User::class);
    
            $result = PasswordGrant::attempt($user->email, 'secret');
    
            dd($result);
        }
    }
    

    dd 在测试结束时,总是返回401,并显示消息: {"error":"invalid_client","message":"Client authentication failed"}

    我已经三次检查了我的用户模型passport客户端的存在性和有效性,并确保有效负载的格式正确。

    可能我在测试期间对服务器的请求中缺少某些头?

    0 回复  |  直到 6 年前