TC-AUTH-007: Purpose-Aware Magic Links
🆕 New on stage — #484, Jun 29 release.
MagicLinkToken now carries a purpose (ACTIVATION or LOGIN; legacy rows have NULL and behave as LOGIN). Before this, ANY valid magic link — including a self-service login link — could reactivate an INACTIVE account, which was a security gap (deactivation could be bypassed by the deactivated user themself). Now only an admin-issued activation/reissue link can do that. See the Test Plan banners.
Module: Authentication & Identity — Magic Links (passwordless auth)
Admin Test User: admin@rcme.membervu.com / Admin123!
Priority: P1 (account-status security boundary)
Objectives
- An admin-issued activation/reissue link for an
INACTIVEmember logs them in AND flips their status toACTIVE(roles restored,membershipExpiresAtrecomputed). - A self-service LOGIN magic link requested by/for an
INACTIVEmember is still blocked — deactivation cannot be self-bypassed via the passwordless-login path. - A legacy magic link (token with
purpose: NULL, pre-#484 data) continues to behave as aLOGIN-purpose link — i.e. does NOT reactivate an INACTIVE account either. - A
SUSPENDEDmember is blocked regardless of link purpose (punitive status, no self-clear via any link).
Scenario summary
| ID | Scenario | Key data assertion |
|---|---|---|
| AU7-01 | Admin activation/reissue link reactivates INACTIVE member | Before: member status = INACTIVE. After clicking the emailed activation link: member status = ACTIVE, the browser is signed in as that member, and any EXPIRED_MEMBER/GUEST roles are removed. |
| AU7-02 | Self-service LOGIN magic link blocked for INACTIVE member | Requesting + clicking a self-service magic link for the same INACTIVE member (before AU7-01, or a second INACTIVE member) returns 403 ACCOUNT_DISABLED on verify — member status remains INACTIVE, no login occurs. |
| AU7-03 | Legacy null-purpose link behaves as LOGIN | A MagicLinkToken row with purpose = NULL against an INACTIVE member also returns 403 on verify — same as AU7-02, confirming NULL is NOT treated as ACTIVATION. |
| AU7-04 | SUSPENDED member blocked regardless of purpose | Both an ACTIVATION-purpose and a LOGIN-purpose link against a SUSPENDED member return 403 ACCOUNT_DISABLED — suspension is never self-clearable. |
| AU7-05 | Used/expired token still rejected (regression) | A magic link already used, or past its 24h expiry, returns 400 TOKEN_USED / 400 TOKEN_EXPIRED regardless of purpose — #484 did not change this existing behavior. |
➡️ Full click-by-click steps: TC-AUTH-007 (Detailed).