mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-28 17:44:36 +08:00
fix(auth): let OAuth-only users enable 2FA without a password confirmation
Users with a linked OAuth identity or no password cannot confirm a password they do not know. The password.confirm middleware now follows User::requiresPasswordConfirmation(), like destructive actions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
3dabda5c56
commit
f75ffd329f
3 files changed
+56
-1
No files matched your search
+1
-1
@@ -17,6 +17,7 @@ use App\Http\Middleware\EnsureTeamMcpEnabled;
|
||||
use App\Http\Middleware\EnsureTokenBelongsToCurrentTeamMember;
|
||||
use App\Http\Middleware\PreventRequestsDuringMaintenance;
|
||||
use App\Http\Middleware\RedirectIfAuthenticated;
|
||||
use App\Http\Middleware\RequirePassword;
|
||||
use App\Http\Middleware\TrimStrings;
|
||||
use App\Http\Middleware\TrustProxies;
|
||||
use App\Http\Middleware\ValidateSignature;
|
||||
@@ -24,7 +25,6 @@ use App\Http\Middleware\VerifyCsrfToken;
|
||||
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
|
||||
use Illuminate\Auth\Middleware\Authorize;
|
||||
use Illuminate\Auth\Middleware\EnsureEmailIsVerified;
|
||||
use Illuminate\Auth\Middleware\RequirePassword;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Auth\Middleware\RequirePassword as Middleware;
|
||||
|
||||
class RequirePassword extends Middleware
|
||||
{
|
||||
/**
|
||||
* Users with a linked OAuth identity, or without a password, cannot confirm
|
||||
* a password they do not know. They follow the same rule as destructive
|
||||
* actions (see User::requiresPasswordConfirmation()).
|
||||
*/
|
||||
protected function shouldConfirmPassword($request, $passwordTimeoutSeconds = null)
|
||||
{
|
||||
if ($request->user()?->requiresPasswordConfirmation() === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::shouldConfirmPassword($request, $passwordTimeoutSeconds);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\OauthIdentity;
|
||||
use App\Models\OauthSetting;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
@@ -173,3 +174,35 @@ describe('confirmation modal', function () {
|
||||
->and($html)->not->toContain('Confirm with Google');
|
||||
});
|
||||
});
|
||||
|
||||
describe('two-factor setup', function () {
|
||||
beforeEach(function () {
|
||||
$this->team = Team::factory()->create(['show_boarding' => false]);
|
||||
});
|
||||
|
||||
it('lets a user with a linked identity and no password enable 2fa without a password confirmation', function () {
|
||||
$user = User::factory()->create();
|
||||
$user->forceFill(['password' => null])->save();
|
||||
$this->team->members()->attach($user, ['role' => 'owner']);
|
||||
linkGoogleIdentity($user, 'google-id');
|
||||
|
||||
$this->actingAs($user)
|
||||
->withSession(['currentTeam' => $this->team])
|
||||
->post(route('two-factor.enable'))
|
||||
->assertSessionHas('status', 'two-factor-authentication-enabled');
|
||||
|
||||
expect($user->fresh()->two_factor_secret)->not->toBeNull();
|
||||
});
|
||||
|
||||
it('still asks a password user without a linked identity to confirm the password', function () {
|
||||
$user = User::factory()->create(['password' => Hash::make('secret-password')]);
|
||||
$this->team->members()->attach($user, ['role' => 'owner']);
|
||||
|
||||
$this->actingAs($user)
|
||||
->withSession(['currentTeam' => $this->team])
|
||||
->post(route('two-factor.enable'))
|
||||
->assertRedirect(route('password.confirm'));
|
||||
|
||||
expect($user->fresh()->two_factor_secret)->toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user