mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(auth): allow OAuth sign-up with an unverified provider email
The provider email verification check now runs only when an account with that email already exists. A new account follows the registration settings, the same way password registration does, which also doesn't verify the email. Linking to an existing account still needs a verified email, except for password-less users created before OAuth identities. Add tests for new-user registration from Authentik, Discord and GitLab when the provider email is unverified. Also test that the "Registration is disabled" error is shown when registration is turned off.
This commit is contained in:
@@ -132,13 +132,14 @@ class OauthLoginService
|
||||
|
||||
$user = User::whereEmail($email)->first();
|
||||
|
||||
// Before OAuth identities existed, OAuth sign-in matched users by email only.
|
||||
// Users from that time keep signing in without email delivery, so their
|
||||
// first identity links without a provider verification claim. A user who
|
||||
// has a password never gets this exemption. This check runs first, so an
|
||||
// unverified email cannot reveal a linked account.
|
||||
// Linking to an existing account needs a verified email. A new account
|
||||
// follows the registration settings, like password registration, which
|
||||
// does not verify the email either. Password-less users from before OAuth
|
||||
// identities existed (OAuth matched by email only) link their first
|
||||
// identity without a verification claim. This check runs before the
|
||||
// linked-account check, so an unverified email cannot reveal one.
|
||||
$isPreUpgradeOauthUser = $user?->created_before_oauth_identities === true && ! $user->hasPassword();
|
||||
if (! $isPreUpgradeOauthUser && ! $this->hasVerifiedEmail($provider, $rawClaims, $email)) {
|
||||
if ($user && ! $isPreUpgradeOauthUser && ! $this->hasVerifiedEmail($provider, $rawClaims, $email)) {
|
||||
throw new OauthLoginException('OAuth provider did not verify the email address', 'auth.failed.oauth_email_unverified');
|
||||
}
|
||||
|
||||
|
||||
@@ -878,3 +878,47 @@ it('allows OAuth user creation through global registration or the OIDC user crea
|
||||
'oidc, registration off, oidc user creation off' => ['oidc', false, false, false],
|
||||
'oidc, registration on, oidc user creation off' => ['oidc', true, false, true],
|
||||
]);
|
||||
|
||||
it('registers a new user from an unverified provider email when registration is enabled', function (string $provider, array $rawClaims) {
|
||||
InstanceSettings::findOrFail(0)->update(['is_registration_enabled' => true]);
|
||||
$setting = OauthSetting::updateOrCreate(['provider' => $provider], [
|
||||
'client_id' => 'client-id',
|
||||
'client_secret' => 'client-secret',
|
||||
'base_url' => 'https://auth.example.com',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
$user = app(OauthLoginService::class)->login($provider, (object) [
|
||||
'email' => 'new-user@example.com',
|
||||
'name' => 'New User',
|
||||
'id' => 'new-provider-id',
|
||||
'user' => $rawClaims,
|
||||
], $setting);
|
||||
|
||||
expect($user->email)->toBe('new-user@example.com')
|
||||
->and(OauthIdentity::where(['user_id' => $user->id, 'provider' => $provider])->exists())->toBeTrue();
|
||||
$this->assertAuthenticatedAs($user);
|
||||
})->with([
|
||||
'authentik default email scope' => ['authentik', ['email_verified' => false]],
|
||||
'discord unverified' => ['discord', ['verified' => false]],
|
||||
'gitlab unconfirmed' => ['gitlab', ['confirmed_at' => null]],
|
||||
]);
|
||||
|
||||
it('tells a new user with an unverified provider email that registration is disabled', function () {
|
||||
$setting = OauthSetting::updateOrCreate(['provider' => 'authentik'], [
|
||||
'client_id' => 'client-id',
|
||||
'client_secret' => 'client-secret',
|
||||
'base_url' => 'https://auth.example.com',
|
||||
'enabled' => true,
|
||||
]);
|
||||
|
||||
expect(fn () => app(OauthLoginService::class)->login('authentik', (object) [
|
||||
'email' => 'new-user@example.com',
|
||||
'name' => 'New User',
|
||||
'id' => 'new-provider-id',
|
||||
'user' => ['email_verified' => false],
|
||||
], $setting))->toThrow(HttpException::class, 'Registration is disabled');
|
||||
|
||||
expect(User::count())->toBe(0);
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user