Feature | UserController MFA Integration, Device Trust Cookie Management, Audit Wiring, and 2FA Rate Limiting#136
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
📘 OpenAPI / Swagger preview ➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-136/ This page is automatically updated on each push to this PR. |
77c0c4f to
0fb9adf
Compare
|
📘 OpenAPI / Swagger preview ➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-136/ This page is automatically updated on each push to this PR. |
0fb9adf to
84252f7
Compare
|
📘 OpenAPI / Swagger preview ➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-136/ This page is automatically updated on each push to this PR. |
… Audit Wiring, and 2FA Rate Limiting
84252f7 to
56e1468
Compare
|
📘 OpenAPI / Swagger preview ➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-136/ This page is automatically updated on each push to this PR. |
| $oauth_auth_request = OAuth2AuthorizationRequestFactory::getInstance()->build | ||
| ( | ||
| OAuth2Message::buildFromMemento($this->oauth2_memento_service->load()) | ||
| if ($flow == "password") { |
There was a problem hiding this comment.
@matiasperrone-exo please move flow to constants on
IAuthService::AuthenticationFlowPassword
and
IAuthService::AuthenticationFlowOTP
Task:
Ref: https://app.clickup.com/t/9014802374/86ba2zc6p
What Changed
UserController(app/Http/Controllers/UserController.php)IDeviceTrustService,ITwoFactorAuditService, andITwoFactorGateServicevia constructor.MFAGateService::requiresChallenge()returnstrue, issues a challenge (viaAuthService::issueMFAChallenge) and returns{ error_code: "mfa_required", ... }— no session created yet.resolveClientFromMemento()private helper to extract the OAuth2 client from a pending session memento (deduplicates logic previously repeated in password and OTP flows).postVerify2FA(),postResend2FA(), andpostRecovery2FA()action methods to handle the full MFA step-up login lifecycle.MFACookieManagertrait for reading/writing the trusted-device cookie.MFACookieManagertrait (app/Http/Controllers/Traits/MFACookieManager.php) — new filegetCookieToken(): ?string(reads raw token from cookie).queueDeviceTrustCookie(User $user): void(callsIDeviceTrustService::trustDeviceand queues a secure, HttpOnly cookie).TwoFactorRateLimitMiddleware(app/Http/Middleware/TwoFactorRateLimitMiddleware.php) — new fileverify,recovery, andresendMFA endpoints.verify/recovery: increments only on failed response (mfa_verification_failed,mfa_invalid_recovery).resend: increments on every request.HTTP 429witherror_code: mfa_rate_limitwhen the limit is exceeded.app/Http/Kernel.phpand wired to the new routes inroutes/web.php.AuthService(app/libs/Auth/AuthService.php) andIAuthService(app/libs/Utils/Services/IAuthService.php)validateCredentials(string $username, string $password): User— validates without creating a session.loginUser(User $user, bool $remember): void— establishes the session for an already-validated user.issueMFAChallenge(User $user, MFAChallengeStrategy $strategy, ?Client $client, bool $remember): array— triggers the challenge strategy and stores pending state.DeviceTrustServiceandTwoFactorAuditService(minor fixes)config/two_factor.php— new filecookie_name,device_trust_lifetime_days, rate-limit thresholds per action.EncryptCookiesmiddlewaredevice_trust_tokencookie from encryption (raw HMAC token must be read as-is byIDeviceTrustService).Tests
tests/TwoFactorLoginFlowTest.php(new)tests/DeviceTrustServiceTest.phptests/Unit/TwoFactorAuditServiceTest.phptests/Unit/MFA/EmailOTPMFAChallengeStrategyTest.phpissueMFAChallengepath.phpunit.xml