tempest-framework icon indicating copy to clipboard operation
tempest-framework copied to clipboard

feat(auth): add OAuth installer

Open Bapawe opened this issue 2 months ago • 5 comments

Fixes #1582

OAuth can be installed optionally during ./tempest install auth or directly via ./tempest install auth --oauth.

Not sure how to best handle the UserModel for different OAuth providers, feedback is welcome!

Bapawe avatar Nov 04 '25 22:11 Bapawe

Not sure how to best handle the UserModel for different OAuth providers, feedback is welcome!

I think it's fair to keep a // todo in the generated controller, where people should fill in their own logic. Personally, I have one oauth controller action that handles all callbacks, but that's only possible because I only use it for simple logins:

    #[Get('/auth/{type}')]
    public function auth(string $type, Request $request): Response
    {
        if ($response = $this->autoLogin()) {
            return $response;
        }

        $oauth = $this->container->get(OAuthClient::class, tag: $type);

        $code = $request->get('code');

        if ($code === null) {
            $this->session->set('back', $request->get('back'));

            return $oauth->createRedirect();
        }

        $oauth->authenticate($request, function (OAuthUser $oauthUser): Authenticatable {
            $user = User::select()
                ->where('email = ?', $oauthUser->email)
                ->first();

            if (! $user) {
                $user = User::create(
                    email: $oauthUser->email,
                    name: $oauthUser->name ?? $oauthUser->nickname,
                    role: Role::USER,
                );
            } else {
                $user->name = $oauthUser->name ?? $oauthUser->nickname;
                $user->save();
            }

            return $user;
        });

        $back = $this->session->consume('back', '/');

        return new Redirect($back);
    }

Maybe having one such controller is enough? OTOH, I do see value in having one per oauth provider as well. WDYT?

brendt avatar Nov 05 '25 12:11 brendt

By the way, apart from the question about controllers, I think this is a very solid PR and I'm happy to merge it once we settled on an answer 👍

brendt avatar Nov 05 '25 12:11 brendt

I think it's fair to keep a // todo in the generated controller, where people should fill in their own logic. Personally, I have one oauth controller action that handles all callbacks, but that's only possible because I only use it for simple logins:

That works for me. I'll add a // TODO comment in the handler and comment out the current implementation in the stub file, so users have a reference to start from.

Maybe having one such controller is enough? OTOH, I do see value in having one per oauth provider as well. WDYT?

I initially considered combining multiple providers into one controller, but switched to the current approach (one controller per provider) because that's how it was described in #1582.

This approach also makes the OAuth installer easier to maintain since the stub file remains straightforward and doesn't require the installer to generate PHP code dynamically (which would be necessary for a multi-provider controller).

Bapawe avatar Nov 07 '25 14:11 Bapawe

True. Let's keep it as is then. Ping me when this is ready for review :)

brendt avatar Nov 08 '25 06:11 brendt

@brendt should be ready now.

Bapawe avatar Nov 08 '25 22:11 Bapawe

Sorry for not getting back to this earlier. I got distracted 🫣

Awesome PR and I'm so happy that you tackled this! Appreciate it!

brendt avatar Dec 03 '25 12:12 brendt