简体   繁体   中英

SOLVED - Laravel Passport - CreateFreshApiToken is not being recognized by auth:api middleware

Firstly, I've already read other similar questions both on StackOverflow and others. Please read what I have to say before redirecting me to other solved issues:)

I was using passport as detailed in the official documentation of Laravel so that my js app could use my Laravel API using the access token set in the cookie created by the CreateFreshApiToken class. I had no problem, even using it to access GraphQL queries (I had to change apollo-client to Axios to achieve this. For a reason I didn't understand, apollo didn't send the cookie).

The problem is that I ran composer install and Laravel updated from 6.x to 8, so everything broke. After many trys to solve it, I decided to rollback to Laravel 6.x and everything worked again, except CreateFreshApiToken class...

Now, Axios keeps using the cookie, but the backend isn't responding as expected, because its behavior is like it hasn't received any cookie and therefore middleware response is 'unauthenticated'.

I can sightly guess that some dependencies have something to do with this if they weren't rolled back well to their original state. Whether this assumption is right or not, I still think the solution is to adopt some code to the current state of my dependencies.

The issue has nothing to do with Passport itself because if I test a request explicitly using the access_token obtained, it works well.

EDIT: I successfully checked in server side the cookie is included in the request.

Project info

Laravel framework 6.20.27 php 7.3.4 node v14.17.0

Related code:

Kernel.php

protected $middleware = [
    \App\Http\Middleware\TrustProxies::class,
    \App\Http\Middleware\CheckForMaintenanceMode::class,
    \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
    \App\Http\Middleware\TrimStrings::class,
    \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \Laravel\Passport\Http\Middleware\CreateFreshApiToken::class
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ]
];

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
    'checkRole' => \App\Http\Middleware\CheckRole::class    //custom middleware
];

/**
 * The priority-sorted list of middleware.
 *
 * This forces non-global middleware to always be in the given order.
 *
 * @var array
 */
protected $middlewarePriority = [
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \App\Http\Middleware\Authenticate::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

User.php

use SoftDeletes, SoftCascadeTrait, Notifiable, HasApiTokens;

Auth.php

'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ]
],

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\User::class,
    ],
],

AuthServiceProvider

public function boot() {
    $this->registerPolicies();
    Passport::routes();
}

RouteServiceProvider

public function map() {
    $this->mapApiRoutes();
    $this->mapWebRoutes();
    //
}

protected function mapWebRoutes() {
    Route::middleware('web')
        ->namespace($this->namespace)
        ->group(base_path('routes/web.php'));
}

protected function mapApiRoutes() {
    Route::prefix('api')
        ->middleware('api')
        ->namespace($this->namespace)
        ->group(base_path('routes/api.php'));
}

LoginController

public function handleFacebookCallback() {
    try {
        $user = Socialite::driver('facebook')->stateless()->fields(['first_name', 'last_name'])->user();

        $attributes = [
            'names' => $user->user['first_name'],
            'lastname' => $user->user['last_name'],
            'email' => $user->email,
            'facebook_id' => $user->id,
            'photo_uri' => $user->getAvatar()
        ];

        $user = User::where('facebook_id', $user->id)->first();

        if ($user) {
            // do things
        } else {
            $user = User::create($attributes);
            $user->roles()->attach(10);
        }
        
        foreach ($user->tokens as $token)
            $token->revoke();

        $this->guard()->login($user); //web login

        $token = Auth::user()->createToken('API')->accessToken; //Passport access token creation
        //shouldn't matter if token is sent or not to the view
        return View::make('welcome')->with('token', $token); 
    }
    catch(\GuzzleHttp\Exception\ClientException $e) {
        return redirect('auth/facebook');
    }
}

composer.json

"require": {
    "php": "^7.2",
    "askedio/laravel-soft-cascade": "^6.0",
    "doctrine/dbal": "^2.10",
    "fideloper/proxy": "^4.0",
    "laravel/framework": "^6.2",
    "laravel/passport": "^8.2",
    "laravel/socialite": "^4.3",
    "laravel/tinker": "^1.0",
    "laravel/ui": "1.0",
    "league/flysystem-aws-s3-v3": "^1.0",
    "rebing/graphql-laravel": "^3.1",
    "symfony/cache": "^4.2",
    "symfony/config": "^4.2",
    "symfony/console": "^4.2"
},

Will be very grateful for your comments. Greetings.

Finally, this issue was solved updating passport to 9.x

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM