Laravel Passport password grant returns Invalid Cr

2019-09-07 02:19发布

问题:

I am trying to setup a SPA that consumes a Laravel API protected with Passport.

I started by creating a new Laravel app specifically for this and I then followed the instructions for setting up passport and set up a password grant client.

I can successfully create a new user, save the user to the database, and log the user in. After that, I try to use the newly created user's information along with the password grant clients id and secret to create an access token. At this point I receive the exception.

I read through the log and I saw where the exception was being thrown. Inside League\OAuth2\Server\Grant\PasswordGrant the validateUser method has the following:

if ($user instanceof UserEntityInterface === false) {
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::USER_AUTHENTICATION_FAILED, $request));

            throw OAuthServerException::invalidCredentials();
        }

Seeing this I implemented the UserEntityInterface on my user model and implemented the getIdentifier method but I still receive the Exception. I'm really not too sure where to go from here, any help would be greatly appreciated. Below is some of my code.

Here is my Registration controller:

class RegisterController extends Controller
{

    private $tokenService;


    public function __construct(AccessTokenService $tokenService)
    {
        //$this->middleware('guest');
        $this->tokenService = $tokenService;
    }

    public function register(Request $request)
    {
        $this->validateWith($this->validator($request->all()));
        Log::debug('Validated');

        $user = $this->create($request->all());
        $this->guard()->login($user);
        $this->tokenService->boot(Auth::user());

        return response()->json($this->tokenService->getNewAccessToken(), 200);
    }

    protected function guard()
    {
        return Auth::guard();
    }

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => 'required|max:255',
            'email' => 'required|email|max:255|unique:users',
            'password' => 'required|min:6|confirmed',
            'password_confirmation' => 'required'
        ]);
    }

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }
}

And these are the relevant portions of AccessTokenService:

public function getNewAccessToken() {
        $http = new Client();
        $client = \Laravel\Passport\Client::where('id', 6)->first();

        Log::debug($client->getAttribute('secret'));
        Log::debug($this->user->getAttribute('email'));
        Log::debug($this->user->getAuthPassword());

        $response = $http->post('homestead.app/oauth/token', [
            'form_params' => [
                'grant_type' => 'password',
                'client_id' => 6,
                'client_secret' => $client->getAttribute('secret'),
                'username' => $this->user->getAttribute('email'),
                'password' => $this->user->getAuthPassword(),
                'scope' => '*'
            ]]);
        unset($client);
        $status = $response->getStatusCode();
        $body = $response->getBody();

        Log::debug($body->getContents());
        Log::debug($status);

        switch($status)
        {
            case 200:case 201:
            case 202:
                $tokens = array(
                    "user_id" => $this->user->getAttribute('id'),
                    "access_token" => $body['access_token'],
                    "refresh_token" => $body['refresh_token']
                );
                $output = ["access_token" => $this->storeTokens($tokens), 'status_code' => $status];
                break;
            default:
                $output = ["access_token" => '', 'status_code' => $status];
                break;

        }
        return $output;
    }

    private function storeTokens(array $tokens) {
        UserToken::create([
            "user_id" => $tokens['user_id'],
            "access_token" => bcrypt($tokens['access_token']),
            "refresh_token" => bcrypt($tokens['refresh_token'])
        ]);
        return $tokens['access_token'];
    }

回答1:

So I figured out the issue. When I was requesting the access token I was passing in the user's email and password but I was passing the hashed password when I needed to pass in the unhashed password.

My request for an access token looked like this:

$response = $http->post('homestead.app/oauth/token', [
            'form_params' => [
                'grant_type' => 'password',
                'client_id' => 6,
                'client_secret' => $client->getAttribute('secret'),
                'username' => $this->user->getAttribute('email'),
                'password' => $this->user->getAuthPassword(), //Here is the problem
                'scope' => '*'
            ]]);

By passing the Request to the function using the unhashed password like this solved the problem:

$response = $http->post('homestead.app/oauth/token', [
            'form_params' => [
                'grant_type' => 'password',
                'client_id' => 6,
                'client_secret' => $client->getAttribute('secret'),
                'username' => $request['email'],
                'password' => $request['password'],
                'scope' => '*'
            ]]);


标签: php laravel-5