Feature | MFA Challenge Strategy Pattern (Interface, Abstract, Factory, EmailOTP)#129
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 |
7e9c06b to
82e8fbc
Compare
|
📘 OpenAPI / Swagger preview ➡️ https://OpenStackweb.github.io/openstackid/openapi/pr-129/ This page is automatically updated on each push to this PR. |
caseylocker
left a comment
There was a problem hiding this comment.
Reviewed against ClickUp 86b9j5jup (this task) plus the linked parent 86b8yfdxd phase decomposition (86b9e8wm7 + 86b9j51aa).
The implementation matches the spec — all 6 task items, all 10 ACs, tests green (15/15, 31 assertions). Approving in the context of the phased rollout: this PR is deliberately scoped to the strategy layer with controller wiring deferred to a separate ticket.
A second-pass review surfaced a handful of items that fall between this PR's scope and the (not-yet-created) controller-wiring task. Flagging them here so they don't slip:
-
Cross-client audience check on `verifyChallenge` — the strategy's interface takes `(User, string)` per spec. `AuthService::loginWithOTP:230,273` passes `$client` and rejects on audience mismatch. The controller will need to either pre-check audience or we extend the strategy interface in Phase II.
-
Transaction boundaries — `AuthService::loginWithOTP` uses two separate `tx_service->transaction()` blocks so `logRedeemAttempt` commits before validation can throw. Strategy has none. The controller will need to replicate that two-tx shape.
-
`2fa_recovery_attempts` session key is declared in the abstract (`AbstractMFAChallengeStrategy.php:15`) but never written. Either the controller wires it as throttling, or we drop the constant.
-
Audit logging via `two_factor_audit_log` (introduced in 86b9e8wm7) needs IP / user-agent which the strategy can't see. Confirms this is structurally a controller-layer concern.
-
Minor: `issueChallenge` stores pending session state before OTP creation. If `createOTPFromPayload` throws, session is left dirty. Worth either reordering or having the controller wrap.
@smarcet — happy to file the controller-wiring ticket with these as explicit ACs if that helps. Approving this PR on the assumption that's where they'll be addressed.
|
@caseylocker |
Task:
Ref: https://app.clickup.com/t/86b9j5jup
Depends on
Summary
Implements the MFA Challenge Strategy Pattern to provide a flexible, extensible framework for handling different multi-factor authentication methods. This PR introduces a
strategy-based architecture with an interface, abstract base class, factory pattern, and a complete Email OTP implementation.
Changes
New Components
1. Interface:
IMFAChallengeStrategy2. Abstract Base:
AbstractMFAChallengeStrategy3. Concrete Implementation:
EmailOTPMFAChallengeStrategy4. Factory:
MFAChallengeStrategyFactoryTest Coverage
AbstractMFAChallengeStrategyTest(143 lines)EmailOTPMFAChallengeStrategyTest(167 lines)MFAChallengeStrategyFactoryTest(23 lines)email_otpmethodConfiguration
phpunit.xmlto register the new test suite for MFA functionalityDesign Rationale
Related Issues
Migration Notes
Requested GOAL
Current state: No MFA challenge infrastructure exists. The login flow has no concept of multi-factor verification strategies.
Target state
A complete strategy pattern is in place: IMFAChallengeStrategy interface defines the contract, AbstractMFAChallengeStrategy provides shared session management and recovery code verification, MFAChallengeStrategyFactory resolves method names to strategy instances, and EmailOTPMFAChallengeStrategy wraps the existing OTP infrastructure for email-based 2FA challenges. This pattern is the extension point for Phase II (SMS) and Phase III (TOTP, passkey) without modifying the controller.
TASKS
The factory would just be:
ACCEPTANCE CRITERIA
DEVELOPMENT NOTES
Key files:
Gotchas:
Out of scope:
Controller wiring