Laravel 6 passport returns 400 Bad request on wrong credential
Asked Answered
F

5

16

I use Laravel 6 passport grant password for my Vue backend.

When i send right credential to oauth/token it works and returns token, but when i send wrong (email/password) it returns 400 instead of 401 with this message.

    {
    "error": "invalid_grant",
    "error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.",
    "hint": "",
    "message": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."
}

I checked client_id and client_secret.

I tested with new installed Laravel + passport with out single line of code, Laravel 5.8 returns 401 without any problem but Laravel 6 returns 400 bad request.

Do you have any Idea?

Forage answered 7/12, 2019 at 20:38 Comment(6)
401 is unauthorized, not a ''wrong credential''Boote
I know , but in Laravel 5.8 when i provide wrong username/password it returns 401 with this message : invalid_credentials (The user credentials were incorrect) but in Laravel 6 it returns 400 with invalid_grant message @AlbertoSinigagliaForage
Did you create your client pair with the --password flag in artisan?Morph
According to Laravel website "If you have already run the passport:install command, you do not need to run this command", but yes i removed them and create new client with --password flag. @MorphForage
I am encountering the same issue, did you find a solution for this?Artema
@Artema I answered what i found.Forage
F
15

Finally i found the problem, the problem is back to league/oauth2-server which that used by Laravel passport.

They changed response from 401 to 400 in version 8.

PR link

I changed my code in login section to this.

switch ($e->getCode()) {
    case 400:
    case 401:
        return response()->json('Your credentials are incorrect. Please try again', $e->getCode());
    break;
    default:
        return response()->json('Something went wrong on the server', $e->getCode());

}

Forage answered 11/12, 2019 at 20:47 Comment(5)
i switched in my own codes, "we usually don't change vendor files...", but if you want know where was the change vendor/league/oauth2-server/src/Grant/PasswordGrant.php line 107 throw OAuthServerException::invalidGrant(); change to throw OAuthServerException::invalidCredentials(); @azurecornForage
I'm facing the same issue. Do you know if Is this a known issue or a new way to throw exceptions? Your solution actually does not represent the real response since you won't be able to show "Hey! complete login data!" or "Hey! Your data is wrong!"Boarish
seems it's new way, and it should be 400 regarding this document https://tools.ietf.org/html/rfc6749#section-5.2. If you want separate wrong credential with error, you can create token manually by validating username and password then $user->createToken('tokenName')->accessToken @BoarishForage
Tha's correct @Mojtaba Sayari, confirmed by the creators in github.com/thephpleague/oauth2-server/issues/1093 Thanks for your possible solution BTWBoarish
I sugest you use abort instead of response: abort($response->status(), 'Your credentials are incorrect. Please try again')Unwinking
O
0

You can add the error handler on App\Exceptions\Handler

use League\OAuth2\Server\Exception\OAuthServerException;
class Handler extends ExceptionHandler
{
    public function render($request, Exception $exception)
    {
        if (get_class($exception) === OAuthServerException::class) {
            response()->json(['message' => $exception->getMessage()], 401);
        }
    }
}
Osy answered 12/5, 2020 at 13:36 Comment(1)
Rectify use Laravel\Passport\Exceptions\OAuthServerExceptionOsy
J
0

I had to use the following in laravel 7.x to convert the 400 level error to 401 in app/Exceptions/Handler.php

NB: check the OAuthServerException::class type

/**
 * Render an exception into an HTTP response.
 *
 * @param \Illuminate\Http\Request $request
 * @param \Exception $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Throwable $exception)
{
    if (get_class($exception) === \Laravel\Passport\Exceptions\OAuthServerException::class) {
        return response(['message' => $exception->getMessage()], 401);
    }

    return parent::render($request, $exception);
}
Jackknife answered 18/6, 2020 at 15:25 Comment(0)
H
0

Update UserFactory password (use Hash::make() not bcrypt)

Helot answered 23/11, 2020 at 20:53 Comment(0)
G
0

try this:

php artisan passport:keys --force
php artisan passport:client --password

then edit your .env

PASSPORT_CLIENT_ID="Client ID"
PASSPORT_CLIENT_SECRET="Client secret"
Gratify answered 26/4, 2021 at 7:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.