Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Octane + OpenSwoole: Auth::user() only works on first request #222

Open
leonvd6 opened this issue Jul 24, 2023 · 7 comments
Open

Octane + OpenSwoole: Auth::user() only works on first request #222

leonvd6 opened this issue Jul 24, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@leonvd6
Copy link

leonvd6 commented Jul 24, 2023

Subject of the issue

I've migrated my environment to Octane+Swoole and when making a request with jwt.auth middleware in api.php, the user is found using Auth::user() or $request->user(), but the subsequent request return null.

Your environment:

Q A
Bug? yes
New Feature? no
Framework Laravel
Framework version 9.52.9
Package version 2.1.0
PHP version 8.1.20

Steps to reproduce

dd(Auth::user()) in a controller API request twice in a row. Running php artisan octane:reload fixes the issue for the next request only.

Expected behaviour

Auth::user() should return the user object on every request, not just the first one.

Actual behaviour

Auth::user() returns a user on the first request, then null on any requests after that.

@leonvd6 leonvd6 added the bug Something isn't working label Jul 24, 2023
@leonvd6 leonvd6 changed the title Octane + Swoole: Auth::user() only works on first request Octane + OpenSwoole: Auth::user() only works on first request Jul 24, 2023
@leonvd6
Copy link
Author

leonvd6 commented Jul 24, 2023

After doing some diggin, I realised If I create my own middleware, it works. I'm not convinced its the best way forward though:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use PHPOpenSourceSaver\JWTAuth\Manager;
use PHPOpenSourceSaver\JWTAuth\Token;

class VerifyUserJWT
{
    /**
     * Constructor
     *
     * @param \PHPOpenSourceSaver\JWTAuth\Manager $tokenManager
     */
    public function __construct(
        private Manager $tokenManager
    ) {}

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        $tokenString = str_replace('Bearer ', '', $request->header('Authorization'));

        if (empty($tokenString)) {
            return response()->json(['message' => 'token_not_provided'], 400);
        }

        // Get user ID from from sub claim in token
        $userId = null;

        try {

            $userId = $this->tokenManager->decode(new Token($tokenString))->get('sub');
            
        } catch (\PHPOpenSourceSaver\JWTAuth\Exceptions\TokenExpiredException $e) {
            return response()->json(['message' => 'token_expired'], 401);
        } catch (\PHPOpenSourceSaver\JWTAuth\Exceptions\TokenInvalidException $e) {
            return response()->json(['message' => 'token_invalid'], 401);
        } catch (\PHPOpenSourceSaver\JWTAuth\Exceptions\InvalidClaimException $e) {
            return response()->json(['message' => 'invalid_claim'], 401);
        } catch (\PHPOpenSourceSaver\JWTAuth\Exceptions\JWTException $e) {
            return response()->json(['message' => 'unknown_token_error'], 401);
        }

        if (!$userId || !Auth::onceUsingId($userId)) {
            return response()->json(['message' => 'token_invalid'], 401);
        }

        return $next($request);
    }
}


@Ctrl-Mota
Copy link

same to me

@rajathans
Copy link

did you figure out a solution? @Ctrl-Mota @leonvd6

@leonvd6
Copy link
Author

leonvd6 commented Aug 29, 2024

@rajathans No still using my code above to get around it.

@leoralph
Copy link
Contributor

@leonvd6 do you have any global scopes within your auth model?

@leoralph
Copy link
Contributor

I recently encountered an infinite loop in my multi-tenant Laravel application.

I have a multi-tenant system, with a company_id column in my tables.

A global scope ensures users only see records associated with their company by filtering based on the company_id column.:
image

When I log in, there's no token being sent, so it doesn't try to auth()->check(), because there's no token, but the second request, when I'm already logged in, it tries to get my user using eloquent user provider, and it applies my global scope to the query, and the global scope has an auth()->check(), so it tries to get the user again, and again, resulting on an inifinite loop.

The solution for me was to replace eloquent provider with this:
image

Now removing the global scope when eloquent provider tries to locate the auth user in the database.

@leonvd6
Copy link
Author

leonvd6 commented Oct 1, 2024

Hi @leoralph ,

No global scopes on my model but thanks for the detailed feedback.

I must say my solution above has been rock solid so far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants