From 6cde1dba4e7beaa9cd9e5df5e65a0627e9a60130 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 12 Jan 2026 14:33:43 +0000 Subject: [PATCH 01/14] fix(auth): replace deprecated library --- composer.json | 2 +- packages/auth/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 7d7494f77..42fe934cf 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "azure-oss/storage-blob-flysystem": "^1.2", "brianium/paratest": "^7.14", "carthage-software/mago": "1.0.0-beta.28", - "depotwarehouse/oauth2-twitch": "^1.3", + "vertisan/oauth2-twitch-helix": "^2.0", "guzzlehttp/psr7": "^2.6.1", "league/flysystem-aws-s3-v3": "^3.25.1", "league/flysystem-ftp": "^3.25.1", diff --git a/packages/auth/composer.json b/packages/auth/composer.json index 687412af4..4a83377c2 100644 --- a/packages/auth/composer.json +++ b/packages/auth/composer.json @@ -22,7 +22,7 @@ "adam-paterson/oauth2-slack": "^1.1", "wohali/oauth2-discord-new": "^1.2", "smolblog/oauth2-twitter": "^1.0", - "depotwarehouse/oauth2-twitch": "^1.3" + "vertisan/oauth2-twitch-helix": "^2.0" }, "autoload": { "psr-4": { From 4e4e8637e1df1f4d8173e61a11afa3a3fdd53a34 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 12 Jan 2026 14:35:51 +0000 Subject: [PATCH 02/14] docs(auth): adding Twitch oauth provider --- docs/2-features/17-oauth.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/2-features/17-oauth.md b/docs/2-features/17-oauth.md index 75ac6dc59..902869ce9 100644 --- a/docs/2-features/17-oauth.md +++ b/docs/2-features/17-oauth.md @@ -220,6 +220,7 @@ Tempest provides a different configuration object for each OAuth provider. Below - **Microsoft** authentication using {b`Tempest\Auth\OAuth\Config\MicrosoftOAuthConfig`}, - **Slack** authentication using {b`Tempest\Auth\OAuth\Config\SlackOAuthConfig`}, - **Apple** authentication using {b`Tempest\Auth\OAuth\Config\AppleOAuthConfig`}, +- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchOAuthConfig`}, - Any other OAuth platform using {b`Tempest\Auth\OAuth\Config\GenericOAuthConfig`}. ## Testing From 176049b21ade398e7bcc808834f8fccc227db4e0 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 15:29:38 +0000 Subject: [PATCH 03/14] feat(auth): TwitchHelix implemented, and changed from Twitch to TwitchHelix naming --- docs/2-features/17-oauth.md | 2 +- .../oauth/twitchhelix.config.stub.php | 15 ++++ .../OAuth/Config/TwitchHelixOAuthConfig.php | 73 +++++++++++++++++++ .../auth/src/OAuth/SupportedOAuthProvider.php | 3 + 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 packages/auth/src/Installer/oauth/twitchhelix.config.stub.php create mode 100644 packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php diff --git a/docs/2-features/17-oauth.md b/docs/2-features/17-oauth.md index 902869ce9..f2ca38203 100644 --- a/docs/2-features/17-oauth.md +++ b/docs/2-features/17-oauth.md @@ -220,7 +220,7 @@ Tempest provides a different configuration object for each OAuth provider. Below - **Microsoft** authentication using {b`Tempest\Auth\OAuth\Config\MicrosoftOAuthConfig`}, - **Slack** authentication using {b`Tempest\Auth\OAuth\Config\SlackOAuthConfig`}, - **Apple** authentication using {b`Tempest\Auth\OAuth\Config\AppleOAuthConfig`}, -- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchOAuthConfig`}, +- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchHelixOAuthConfig`}, - Any other OAuth platform using {b`Tempest\Auth\OAuth\Config\GenericOAuthConfig`}. ## Testing diff --git a/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php b/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php new file mode 100644 index 000000000..1e97cc72a --- /dev/null +++ b/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php @@ -0,0 +1,15 @@ + $this->clientId, + 'clientSecret' => $this->clientSecret, + 'redirectUri' => $this->redirectTo, + ]); + } + + /** + * @param TwitchHelixResourceOwner $resourceOwner + */ + public function mapUser(ObjectFactory $factory, ResourceOwnerInterface $resourceOwner): OAuthUser + { + return $factory->withData([ + 'id' => (string) $resourceOwner->getId(), + 'email' => $resourceOwner->getEmail(), + 'name' => $resourceOwner->getDisplayName(), + 'nickname' => $resourceOwner->getDisplayName(), + 'avatar' => $resourceOwner->getProfileImageUrl(), + 'provider' => $this->provider, + 'raw' => $resourceOwner->toArray(), + ])->to(OAuthUser::class); + } +} diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 1346a942d..94d260a95 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -11,6 +11,7 @@ use League\OAuth2\Client\Provider\Instagram; use League\OAuth2\Client\Provider\LinkedIn; use Stevenmaguire\OAuth2\Client\Provider\Microsoft; +use Vertisan\OAuth2\Client\Provider\TwitchHelix; use Wohali\OAuth2\Client\Provider\Discord; enum SupportedOAuthProvider: string @@ -25,6 +26,7 @@ enum SupportedOAuthProvider: string case LINKEDIN = LinkedIn::class; case MICROSOFT = Microsoft::class; case SLACK = Slack::class; + case TWITCHHELIX = TwitchHelix::class; public function composerPackage(): ?string { @@ -39,6 +41,7 @@ public function composerPackage(): ?string self::LINKEDIN => 'league/oauth2-linkedin', self::MICROSOFT => 'stevenmaguire/oauth2-microsoft', self::SLACK => 'adam-paterson/oauth2-slack', + self::TWITCHHELIX => 'vertisan/oauth2-twitch-helix', }; } } From 0ae92504a9d1723e263c275de1afd3dcf4adc9cd Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 15:37:55 +0000 Subject: [PATCH 04/14] feat(auth): Updated test --- composer.json | 2 +- tests/Integration/Auth/Installer/OAuthInstallerTest.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 42fe934cf..612a405f8 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,6 @@ "azure-oss/storage-blob-flysystem": "^1.2", "brianium/paratest": "^7.14", "carthage-software/mago": "1.0.0-beta.28", - "vertisan/oauth2-twitch-helix": "^2.0", "guzzlehttp/psr7": "^2.6.1", "league/flysystem-aws-s3-v3": "^3.25.1", "league/flysystem-ftp": "^3.25.1", @@ -88,6 +87,7 @@ "tempest/blade": "dev-main", "thenetworg/oauth2-azure": "^2.2", "twig/twig": "^3.16", + "vertisan/oauth2-twitch-helix": "^2.0", "wohali/oauth2-discord-new": "^1.2" }, "replace": { diff --git a/tests/Integration/Auth/Installer/OAuthInstallerTest.php b/tests/Integration/Auth/Installer/OAuthInstallerTest.php index 22e754b60..7fd0a9b6a 100644 --- a/tests/Integration/Auth/Installer/OAuthInstallerTest.php +++ b/tests/Integration/Auth/Installer/OAuthInstallerTest.php @@ -121,6 +121,11 @@ public static function oauthProvider(): array 'expectedConfigPath' => 'App/Authentication/OAuth/slack.config.php', 'expectedControllerPath' => 'App/Authentication/OAuth/SlackController.php', ], + 'twitchhelix' => [ + 'provider' => SupportedOAuthProvider::TWITCHHELIX, + 'expectedConfigPath' => 'App/Authentication/OAuth/twitchhelix.config.php', + 'expectedControllerPath' => 'App/Authentication/OAuth/TwitchHelixController.php', + ], ]; } } From c395f03649e677fa4719db98f8da6b126dc5dccb Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 19:48:06 +0000 Subject: [PATCH 05/14] feat(auth): Align naming to Twitch, adjust installer stub filename generation to use the enum name instead of class --- docs/2-features/17-oauth.md | 2 +- packages/auth/src/Installer/OAuthInstaller.php | 4 ++-- ...witchhelix.config.stub.php => twitch.config.stub.php} | 4 ++-- ...{TwitchHelixOAuthConfig.php => TwitchOAuthConfig.php} | 8 ++++---- packages/auth/src/OAuth/SupportedOAuthProvider.php | 9 +++++++-- tests/Integration/Auth/Installer/OAuthInstallerTest.php | 8 ++++---- 6 files changed, 20 insertions(+), 15 deletions(-) rename packages/auth/src/Installer/oauth/{twitchhelix.config.stub.php => twitch.config.stub.php} (79%) rename packages/auth/src/OAuth/Config/{TwitchHelixOAuthConfig.php => TwitchOAuthConfig.php} (88%) diff --git a/docs/2-features/17-oauth.md b/docs/2-features/17-oauth.md index f2ca38203..902869ce9 100644 --- a/docs/2-features/17-oauth.md +++ b/docs/2-features/17-oauth.md @@ -220,7 +220,7 @@ Tempest provides a different configuration object for each OAuth provider. Below - **Microsoft** authentication using {b`Tempest\Auth\OAuth\Config\MicrosoftOAuthConfig`}, - **Slack** authentication using {b`Tempest\Auth\OAuth\Config\SlackOAuthConfig`}, - **Apple** authentication using {b`Tempest\Auth\OAuth\Config\AppleOAuthConfig`}, -- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchHelixOAuthConfig`}, +- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchOAuthConfig`}, - Any other OAuth platform using {b`Tempest\Auth\OAuth\Config\GenericOAuthConfig`}. ## Testing diff --git a/packages/auth/src/Installer/OAuthInstaller.php b/packages/auth/src/Installer/OAuthInstaller.php index 0ee15ec40..4cd0b0ed8 100644 --- a/packages/auth/src/Installer/OAuthInstaller.php +++ b/packages/auth/src/Installer/OAuthInstaller.php @@ -93,8 +93,8 @@ private function publishConfig(SupportedOAuthProvider $provider): void private function publishController(SupportedOAuthProvider $provider): void { - $fileName = str($provider->value) - ->classBasename() + $fileName = str($provider->name) + ->sentence() ->replace('Provider', '') ->append('Controller.php') ->toString(); diff --git a/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php b/packages/auth/src/Installer/oauth/twitch.config.stub.php similarity index 79% rename from packages/auth/src/Installer/oauth/twitchhelix.config.stub.php rename to packages/auth/src/Installer/oauth/twitch.config.stub.php index 1e97cc72a..11968506f 100644 --- a/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php +++ b/packages/auth/src/Installer/oauth/twitch.config.stub.php @@ -2,12 +2,12 @@ declare(strict_types=1); -use Tempest\Auth\OAuth\Config\TwitchHelixOAuthConfig; +use Tempest\Auth\OAuth\Config\TwitchOAuthConfig; use Tempest\Auth\OAuth\SupportedOAuthProvider; use function Tempest\env; -return new TwitchHelixOAuthConfig( +return new TwitchOAuthConfig( clientId: env('OAUTH_TWITCH_CLIENT_ID') ?? '', clientSecret: env('OAUTH_TWITCH_CLIENT_SECRET') ?? '', redirectTo: [\Tempest\Auth\Installer\oauth\OAuthControllerStub::class, 'callback'], diff --git a/packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php b/packages/auth/src/OAuth/Config/TwitchOAuthConfig.php similarity index 88% rename from packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php rename to packages/auth/src/OAuth/Config/TwitchOAuthConfig.php index 0800bc5b3..e48e268f9 100644 --- a/packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php +++ b/packages/auth/src/OAuth/Config/TwitchOAuthConfig.php @@ -13,18 +13,18 @@ use Vertisan\OAuth2\Client\Provider\TwitchHelix; use Vertisan\OAuth2\Client\Provider\TwitchHelixResourceOwner; -final class TwitchHelixOAuthConfig implements OAuthConfig +final class TwitchOAuthConfig implements OAuthConfig { public string $provider = TwitchHelix::class; public function __construct( /** - * The client ID for the TwitchHelix OAuth application. + * The client ID for the Twitch OAuth application. */ public string $clientId, /** - * The client secret for the TwitchHelix OAuth application. + * The client secret for the Twitch OAuth application. */ public string $clientSecret, @@ -34,7 +34,7 @@ public function __construct( public string|array $redirectTo, /** - * The scopes to request from TwitchHelix. + * The scopes to request from Twitch. * * @var string[] */ diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 94d260a95..056db641b 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -26,8 +26,13 @@ enum SupportedOAuthProvider: string case LINKEDIN = LinkedIn::class; case MICROSOFT = Microsoft::class; case SLACK = Slack::class; - case TWITCHHELIX = TwitchHelix::class; + case TWITCH = TwitchHelix::class; + /** + * Returns the Composer package name for the given OAuth provider. + * + * @return string|null The Composer package name, or null if the provider is generic. + */ public function composerPackage(): ?string { return match ($this) { @@ -41,7 +46,7 @@ public function composerPackage(): ?string self::LINKEDIN => 'league/oauth2-linkedin', self::MICROSOFT => 'stevenmaguire/oauth2-microsoft', self::SLACK => 'adam-paterson/oauth2-slack', - self::TWITCHHELIX => 'vertisan/oauth2-twitch-helix', + self::TWITCH => 'vertisan/oauth2-twitch-helix', }; } } diff --git a/tests/Integration/Auth/Installer/OAuthInstallerTest.php b/tests/Integration/Auth/Installer/OAuthInstallerTest.php index 7fd0a9b6a..40a7eb5f1 100644 --- a/tests/Integration/Auth/Installer/OAuthInstallerTest.php +++ b/tests/Integration/Auth/Installer/OAuthInstallerTest.php @@ -121,10 +121,10 @@ public static function oauthProvider(): array 'expectedConfigPath' => 'App/Authentication/OAuth/slack.config.php', 'expectedControllerPath' => 'App/Authentication/OAuth/SlackController.php', ], - 'twitchhelix' => [ - 'provider' => SupportedOAuthProvider::TWITCHHELIX, - 'expectedConfigPath' => 'App/Authentication/OAuth/twitchhelix.config.php', - 'expectedControllerPath' => 'App/Authentication/OAuth/TwitchHelixController.php', + 'twitch' => [ + 'provider' => SupportedOAuthProvider::TWITCH, + 'expectedConfigPath' => 'App/Authentication/OAuth/twitch.config.php', + 'expectedControllerPath' => 'App/Authentication/OAuth/TwitchController.php', ], ]; } From 4683d47f90aa6207618db09ba16529af91fb77f2 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 20:28:42 +0000 Subject: [PATCH 06/14] feat(auth): Create Enum method to deliver canononical name --- .../auth/src/Installer/OAuthInstaller.php | 5 ++--- .../auth/src/OAuth/SupportedOAuthProvider.php | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/auth/src/Installer/OAuthInstaller.php b/packages/auth/src/Installer/OAuthInstaller.php index 4cd0b0ed8..8915b44d3 100644 --- a/packages/auth/src/Installer/OAuthInstaller.php +++ b/packages/auth/src/Installer/OAuthInstaller.php @@ -93,8 +93,7 @@ private function publishConfig(SupportedOAuthProvider $provider): void private function publishController(SupportedOAuthProvider $provider): void { - $fileName = str($provider->name) - ->sentence() + $fileName = str($provider->getName()) ->replace('Provider', '') ->append('Controller.php') ->toString(); @@ -104,7 +103,7 @@ private function publishController(SupportedOAuthProvider $provider): void destination: src_path("Authentication/OAuth/{$fileName}"), callback: function (string $source, string $destination) use ($provider) { $providerFqcn = $provider::class; - $name = strtolower($provider->name); + $name = strtolower($provider->getName()); $userModelFqcn = to_fqcn(src_path('Authentication/User.php'), root: root_path()); $this->update( diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 056db641b..5500f6ce5 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -28,6 +28,28 @@ enum SupportedOAuthProvider: string case SLACK = Slack::class; case TWITCH = TwitchHelix::class; + /** + * Returns the canonical name for the given OAuth provider. Required because some of the providers have mixed-case names. + * + * @return string|null The canonical name, or null if the provider is generic. + */ + public function getName(): ?string + { + return match ($this) { + self::APPLE => 'Apple', + self::DISCORD => 'Discord', + self::FACEBOOK => 'Facebook', + self::GENERIC => null, + self::GITHUB => 'GitHub', + self::GOOGLE => 'Google', + self::INSTAGRAM => 'Instagram', + self::LINKEDIN => 'LinkedIn', + self::MICROSOFT => 'Microsoft', + self::SLACK => 'Slack', + self::TWITCH => 'Twitch', + }; + } + /** * Returns the Composer package name for the given OAuth provider. * From c60ede274ce7217437128aecb8f4fec188ba69c1 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 20:35:05 +0000 Subject: [PATCH 07/14] feat(auth): Github is non-canonical, corrected --- packages/auth/src/OAuth/SupportedOAuthProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 5500f6ce5..023a2ecc0 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -40,7 +40,7 @@ public function getName(): ?string self::DISCORD => 'Discord', self::FACEBOOK => 'Facebook', self::GENERIC => null, - self::GITHUB => 'GitHub', + self::GITHUB => 'Github', self::GOOGLE => 'Google', self::INSTAGRAM => 'Instagram', self::LINKEDIN => 'LinkedIn', From b485852b6222f4bd3ff559914d88db31e50174dc Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 12 Jan 2026 14:33:43 +0000 Subject: [PATCH 08/14] fix(auth): replace deprecated library --- composer.json | 2 +- packages/auth/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 70449dbeb..4d1bba882 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "azure-oss/storage-blob-flysystem": "^1.2", "brianium/paratest": "^7.14", "carthage-software/mago": "1.0.0-beta.28", - "depotwarehouse/oauth2-twitch": "^1.3", + "vertisan/oauth2-twitch-helix": "^2.0", "guzzlehttp/psr7": "^2.6.1", "league/flysystem-aws-s3-v3": "^3.25.1", "league/flysystem-ftp": "^3.25.1", diff --git a/packages/auth/composer.json b/packages/auth/composer.json index 687412af4..4a83377c2 100644 --- a/packages/auth/composer.json +++ b/packages/auth/composer.json @@ -22,7 +22,7 @@ "adam-paterson/oauth2-slack": "^1.1", "wohali/oauth2-discord-new": "^1.2", "smolblog/oauth2-twitter": "^1.0", - "depotwarehouse/oauth2-twitch": "^1.3" + "vertisan/oauth2-twitch-helix": "^2.0" }, "autoload": { "psr-4": { From 347aeb957e30df5cdb9ed1ae4f838d776a29902a Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 12 Jan 2026 14:35:51 +0000 Subject: [PATCH 09/14] docs(auth): adding Twitch oauth provider --- docs/2-features/17-oauth.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/2-features/17-oauth.md b/docs/2-features/17-oauth.md index 75ac6dc59..902869ce9 100644 --- a/docs/2-features/17-oauth.md +++ b/docs/2-features/17-oauth.md @@ -220,6 +220,7 @@ Tempest provides a different configuration object for each OAuth provider. Below - **Microsoft** authentication using {b`Tempest\Auth\OAuth\Config\MicrosoftOAuthConfig`}, - **Slack** authentication using {b`Tempest\Auth\OAuth\Config\SlackOAuthConfig`}, - **Apple** authentication using {b`Tempest\Auth\OAuth\Config\AppleOAuthConfig`}, +- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchOAuthConfig`}, - Any other OAuth platform using {b`Tempest\Auth\OAuth\Config\GenericOAuthConfig`}. ## Testing From 16a7bc136fa9d82905bfa2a980f510b37ff46222 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 15:29:38 +0000 Subject: [PATCH 10/14] feat(auth): TwitchHelix implemented, and changed from Twitch to TwitchHelix naming --- docs/2-features/17-oauth.md | 2 +- .../oauth/twitchhelix.config.stub.php | 15 ++++ .../OAuth/Config/TwitchHelixOAuthConfig.php | 73 +++++++++++++++++++ .../auth/src/OAuth/SupportedOAuthProvider.php | 3 + 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 packages/auth/src/Installer/oauth/twitchhelix.config.stub.php create mode 100644 packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php diff --git a/docs/2-features/17-oauth.md b/docs/2-features/17-oauth.md index 902869ce9..f2ca38203 100644 --- a/docs/2-features/17-oauth.md +++ b/docs/2-features/17-oauth.md @@ -220,7 +220,7 @@ Tempest provides a different configuration object for each OAuth provider. Below - **Microsoft** authentication using {b`Tempest\Auth\OAuth\Config\MicrosoftOAuthConfig`}, - **Slack** authentication using {b`Tempest\Auth\OAuth\Config\SlackOAuthConfig`}, - **Apple** authentication using {b`Tempest\Auth\OAuth\Config\AppleOAuthConfig`}, -- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchOAuthConfig`}, +- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchHelixOAuthConfig`}, - Any other OAuth platform using {b`Tempest\Auth\OAuth\Config\GenericOAuthConfig`}. ## Testing diff --git a/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php b/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php new file mode 100644 index 000000000..1e97cc72a --- /dev/null +++ b/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php @@ -0,0 +1,15 @@ + $this->clientId, + 'clientSecret' => $this->clientSecret, + 'redirectUri' => $this->redirectTo, + ]); + } + + /** + * @param TwitchHelixResourceOwner $resourceOwner + */ + public function mapUser(ObjectFactory $factory, ResourceOwnerInterface $resourceOwner): OAuthUser + { + return $factory->withData([ + 'id' => (string) $resourceOwner->getId(), + 'email' => $resourceOwner->getEmail(), + 'name' => $resourceOwner->getDisplayName(), + 'nickname' => $resourceOwner->getDisplayName(), + 'avatar' => $resourceOwner->getProfileImageUrl(), + 'provider' => $this->provider, + 'raw' => $resourceOwner->toArray(), + ])->to(OAuthUser::class); + } +} diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 1346a942d..94d260a95 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -11,6 +11,7 @@ use League\OAuth2\Client\Provider\Instagram; use League\OAuth2\Client\Provider\LinkedIn; use Stevenmaguire\OAuth2\Client\Provider\Microsoft; +use Vertisan\OAuth2\Client\Provider\TwitchHelix; use Wohali\OAuth2\Client\Provider\Discord; enum SupportedOAuthProvider: string @@ -25,6 +26,7 @@ enum SupportedOAuthProvider: string case LINKEDIN = LinkedIn::class; case MICROSOFT = Microsoft::class; case SLACK = Slack::class; + case TWITCHHELIX = TwitchHelix::class; public function composerPackage(): ?string { @@ -39,6 +41,7 @@ public function composerPackage(): ?string self::LINKEDIN => 'league/oauth2-linkedin', self::MICROSOFT => 'stevenmaguire/oauth2-microsoft', self::SLACK => 'adam-paterson/oauth2-slack', + self::TWITCHHELIX => 'vertisan/oauth2-twitch-helix', }; } } From f8f0e2e57159c48b58c9a2426ec46630f01f6555 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 15:37:55 +0000 Subject: [PATCH 11/14] feat(auth): Updated test --- composer.json | 2 +- tests/Integration/Auth/Installer/OAuthInstallerTest.php | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4d1bba882..5146e035b 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,6 @@ "azure-oss/storage-blob-flysystem": "^1.2", "brianium/paratest": "^7.14", "carthage-software/mago": "1.0.0-beta.28", - "vertisan/oauth2-twitch-helix": "^2.0", "guzzlehttp/psr7": "^2.6.1", "league/flysystem-aws-s3-v3": "^3.25.1", "league/flysystem-ftp": "^3.25.1", @@ -88,6 +87,7 @@ "tempest/blade": "dev-main", "thenetworg/oauth2-azure": "^2.2", "twig/twig": "^3.16", + "vertisan/oauth2-twitch-helix": "^2.0", "wohali/oauth2-discord-new": "^1.2" }, "replace": { diff --git a/tests/Integration/Auth/Installer/OAuthInstallerTest.php b/tests/Integration/Auth/Installer/OAuthInstallerTest.php index 22e754b60..7fd0a9b6a 100644 --- a/tests/Integration/Auth/Installer/OAuthInstallerTest.php +++ b/tests/Integration/Auth/Installer/OAuthInstallerTest.php @@ -121,6 +121,11 @@ public static function oauthProvider(): array 'expectedConfigPath' => 'App/Authentication/OAuth/slack.config.php', 'expectedControllerPath' => 'App/Authentication/OAuth/SlackController.php', ], + 'twitchhelix' => [ + 'provider' => SupportedOAuthProvider::TWITCHHELIX, + 'expectedConfigPath' => 'App/Authentication/OAuth/twitchhelix.config.php', + 'expectedControllerPath' => 'App/Authentication/OAuth/TwitchHelixController.php', + ], ]; } } From 359376ea064c8bf07e463b17373aa2ea654f3041 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 19:48:06 +0000 Subject: [PATCH 12/14] feat(auth): Align naming to Twitch, adjust installer stub filename generation to use the enum name instead of class --- docs/2-features/17-oauth.md | 2 +- packages/auth/src/Installer/OAuthInstaller.php | 4 ++-- ...witchhelix.config.stub.php => twitch.config.stub.php} | 4 ++-- ...{TwitchHelixOAuthConfig.php => TwitchOAuthConfig.php} | 8 ++++---- packages/auth/src/OAuth/SupportedOAuthProvider.php | 9 +++++++-- tests/Integration/Auth/Installer/OAuthInstallerTest.php | 8 ++++---- 6 files changed, 20 insertions(+), 15 deletions(-) rename packages/auth/src/Installer/oauth/{twitchhelix.config.stub.php => twitch.config.stub.php} (79%) rename packages/auth/src/OAuth/Config/{TwitchHelixOAuthConfig.php => TwitchOAuthConfig.php} (88%) diff --git a/docs/2-features/17-oauth.md b/docs/2-features/17-oauth.md index f2ca38203..902869ce9 100644 --- a/docs/2-features/17-oauth.md +++ b/docs/2-features/17-oauth.md @@ -220,7 +220,7 @@ Tempest provides a different configuration object for each OAuth provider. Below - **Microsoft** authentication using {b`Tempest\Auth\OAuth\Config\MicrosoftOAuthConfig`}, - **Slack** authentication using {b`Tempest\Auth\OAuth\Config\SlackOAuthConfig`}, - **Apple** authentication using {b`Tempest\Auth\OAuth\Config\AppleOAuthConfig`}, -- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchHelixOAuthConfig`}, +- **Twitch** authentication using {b`Tempest\Auth\OAuth\Config\TwitchOAuthConfig`}, - Any other OAuth platform using {b`Tempest\Auth\OAuth\Config\GenericOAuthConfig`}. ## Testing diff --git a/packages/auth/src/Installer/OAuthInstaller.php b/packages/auth/src/Installer/OAuthInstaller.php index 0ee15ec40..4cd0b0ed8 100644 --- a/packages/auth/src/Installer/OAuthInstaller.php +++ b/packages/auth/src/Installer/OAuthInstaller.php @@ -93,8 +93,8 @@ private function publishConfig(SupportedOAuthProvider $provider): void private function publishController(SupportedOAuthProvider $provider): void { - $fileName = str($provider->value) - ->classBasename() + $fileName = str($provider->name) + ->sentence() ->replace('Provider', '') ->append('Controller.php') ->toString(); diff --git a/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php b/packages/auth/src/Installer/oauth/twitch.config.stub.php similarity index 79% rename from packages/auth/src/Installer/oauth/twitchhelix.config.stub.php rename to packages/auth/src/Installer/oauth/twitch.config.stub.php index 1e97cc72a..11968506f 100644 --- a/packages/auth/src/Installer/oauth/twitchhelix.config.stub.php +++ b/packages/auth/src/Installer/oauth/twitch.config.stub.php @@ -2,12 +2,12 @@ declare(strict_types=1); -use Tempest\Auth\OAuth\Config\TwitchHelixOAuthConfig; +use Tempest\Auth\OAuth\Config\TwitchOAuthConfig; use Tempest\Auth\OAuth\SupportedOAuthProvider; use function Tempest\env; -return new TwitchHelixOAuthConfig( +return new TwitchOAuthConfig( clientId: env('OAUTH_TWITCH_CLIENT_ID') ?? '', clientSecret: env('OAUTH_TWITCH_CLIENT_SECRET') ?? '', redirectTo: [\Tempest\Auth\Installer\oauth\OAuthControllerStub::class, 'callback'], diff --git a/packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php b/packages/auth/src/OAuth/Config/TwitchOAuthConfig.php similarity index 88% rename from packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php rename to packages/auth/src/OAuth/Config/TwitchOAuthConfig.php index 0800bc5b3..e48e268f9 100644 --- a/packages/auth/src/OAuth/Config/TwitchHelixOAuthConfig.php +++ b/packages/auth/src/OAuth/Config/TwitchOAuthConfig.php @@ -13,18 +13,18 @@ use Vertisan\OAuth2\Client\Provider\TwitchHelix; use Vertisan\OAuth2\Client\Provider\TwitchHelixResourceOwner; -final class TwitchHelixOAuthConfig implements OAuthConfig +final class TwitchOAuthConfig implements OAuthConfig { public string $provider = TwitchHelix::class; public function __construct( /** - * The client ID for the TwitchHelix OAuth application. + * The client ID for the Twitch OAuth application. */ public string $clientId, /** - * The client secret for the TwitchHelix OAuth application. + * The client secret for the Twitch OAuth application. */ public string $clientSecret, @@ -34,7 +34,7 @@ public function __construct( public string|array $redirectTo, /** - * The scopes to request from TwitchHelix. + * The scopes to request from Twitch. * * @var string[] */ diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 94d260a95..056db641b 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -26,8 +26,13 @@ enum SupportedOAuthProvider: string case LINKEDIN = LinkedIn::class; case MICROSOFT = Microsoft::class; case SLACK = Slack::class; - case TWITCHHELIX = TwitchHelix::class; + case TWITCH = TwitchHelix::class; + /** + * Returns the Composer package name for the given OAuth provider. + * + * @return string|null The Composer package name, or null if the provider is generic. + */ public function composerPackage(): ?string { return match ($this) { @@ -41,7 +46,7 @@ public function composerPackage(): ?string self::LINKEDIN => 'league/oauth2-linkedin', self::MICROSOFT => 'stevenmaguire/oauth2-microsoft', self::SLACK => 'adam-paterson/oauth2-slack', - self::TWITCHHELIX => 'vertisan/oauth2-twitch-helix', + self::TWITCH => 'vertisan/oauth2-twitch-helix', }; } } diff --git a/tests/Integration/Auth/Installer/OAuthInstallerTest.php b/tests/Integration/Auth/Installer/OAuthInstallerTest.php index 7fd0a9b6a..40a7eb5f1 100644 --- a/tests/Integration/Auth/Installer/OAuthInstallerTest.php +++ b/tests/Integration/Auth/Installer/OAuthInstallerTest.php @@ -121,10 +121,10 @@ public static function oauthProvider(): array 'expectedConfigPath' => 'App/Authentication/OAuth/slack.config.php', 'expectedControllerPath' => 'App/Authentication/OAuth/SlackController.php', ], - 'twitchhelix' => [ - 'provider' => SupportedOAuthProvider::TWITCHHELIX, - 'expectedConfigPath' => 'App/Authentication/OAuth/twitchhelix.config.php', - 'expectedControllerPath' => 'App/Authentication/OAuth/TwitchHelixController.php', + 'twitch' => [ + 'provider' => SupportedOAuthProvider::TWITCH, + 'expectedConfigPath' => 'App/Authentication/OAuth/twitch.config.php', + 'expectedControllerPath' => 'App/Authentication/OAuth/TwitchController.php', ], ]; } From 5f9889b95b4d5cf43a274f0fbba5fb1060771337 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 20:28:42 +0000 Subject: [PATCH 13/14] feat(auth): Create Enum method to deliver canononical name --- .../auth/src/Installer/OAuthInstaller.php | 5 ++--- .../auth/src/OAuth/SupportedOAuthProvider.php | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/auth/src/Installer/OAuthInstaller.php b/packages/auth/src/Installer/OAuthInstaller.php index 4cd0b0ed8..8915b44d3 100644 --- a/packages/auth/src/Installer/OAuthInstaller.php +++ b/packages/auth/src/Installer/OAuthInstaller.php @@ -93,8 +93,7 @@ private function publishConfig(SupportedOAuthProvider $provider): void private function publishController(SupportedOAuthProvider $provider): void { - $fileName = str($provider->name) - ->sentence() + $fileName = str($provider->getName()) ->replace('Provider', '') ->append('Controller.php') ->toString(); @@ -104,7 +103,7 @@ private function publishController(SupportedOAuthProvider $provider): void destination: src_path("Authentication/OAuth/{$fileName}"), callback: function (string $source, string $destination) use ($provider) { $providerFqcn = $provider::class; - $name = strtolower($provider->name); + $name = strtolower($provider->getName()); $userModelFqcn = to_fqcn(src_path('Authentication/User.php'), root: root_path()); $this->update( diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 056db641b..5500f6ce5 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -28,6 +28,28 @@ enum SupportedOAuthProvider: string case SLACK = Slack::class; case TWITCH = TwitchHelix::class; + /** + * Returns the canonical name for the given OAuth provider. Required because some of the providers have mixed-case names. + * + * @return string|null The canonical name, or null if the provider is generic. + */ + public function getName(): ?string + { + return match ($this) { + self::APPLE => 'Apple', + self::DISCORD => 'Discord', + self::FACEBOOK => 'Facebook', + self::GENERIC => null, + self::GITHUB => 'GitHub', + self::GOOGLE => 'Google', + self::INSTAGRAM => 'Instagram', + self::LINKEDIN => 'LinkedIn', + self::MICROSOFT => 'Microsoft', + self::SLACK => 'Slack', + self::TWITCH => 'Twitch', + }; + } + /** * Returns the Composer package name for the given OAuth provider. * From f301d351690dcddec791886be8f3bc1c4cb361e8 Mon Sep 17 00:00:00 2001 From: iamdadmin Date: Mon, 19 Jan 2026 20:35:05 +0000 Subject: [PATCH 14/14] feat(auth): Github is non-canonical, corrected --- packages/auth/src/OAuth/SupportedOAuthProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth/src/OAuth/SupportedOAuthProvider.php b/packages/auth/src/OAuth/SupportedOAuthProvider.php index 5500f6ce5..023a2ecc0 100644 --- a/packages/auth/src/OAuth/SupportedOAuthProvider.php +++ b/packages/auth/src/OAuth/SupportedOAuthProvider.php @@ -40,7 +40,7 @@ public function getName(): ?string self::DISCORD => 'Discord', self::FACEBOOK => 'Facebook', self::GENERIC => null, - self::GITHUB => 'GitHub', + self::GITHUB => 'Github', self::GOOGLE => 'Google', self::INSTAGRAM => 'Instagram', self::LINKEDIN => 'LinkedIn',