Skip to content

feat(seed): enroll TOTP auth factors from user config - #77

Merged
gjtorikian merged 2 commits into
mainfrom
fix/seed-totp-factor
Aug 21, 2026
Merged

feat(seed): enroll TOTP auth factors from user config#77
gjtorikian merged 2 commits into
mainfrom
fix/seed-totp-factor

Conversation

@gjtorikian

Copy link
Copy Markdown
Collaborator

Summary

  • Adds totp: true to WorkOSSeedUser: the seed inserts the same ws.authFactors record POST /user_management/users/{id}/auth_factors writes (object: 'authentication_factor', type: 'totp', totp: { issuer, user, uri }), defaulting issuer to WorkOS Emulator the way that route does.
  • Factors were the one authentication method a seed could not give a user — password and oauth_provider already are — so MFA administration needed post-boot enrollment calls whose state a restart loses, and an empty ListAuthFactors was indistinguishable from "this user has no MFA".
  • A seeded factor also drives the existing login step-up: a password sign-in for the user answers with the spec's mfa_challenge (pending token + challenge) instead of a session, completed with the urn:workos:oauth:grant-type:mfa-totp grant. The new spec walks that whole flow end to end.
  • validateSeedConfig rejects a non-boolean totp (YAML's totp: yes parses to true, but totp: "yes" would not), and the README documents the key under a new "Seeded MFA factors" section.

On the optional pinned totp_secret: left out, deliberately. Challenge verification compares the submitted code against the challenge's stored one-time code — it never computes a TOTP from the factor's secret — so a pinned secret would only make the otpauth URI deterministic while implying that a client can compute valid codes from it, which it can't. If real TOTP computation lands someday, a totp_secret seed key would make sense alongside it.

Fixes #75

Factors were the one authentication method a seed could not give a
user — password and oauth_provider already are — so anything touching
MFA administration needed post-boot enrollment calls whose state a
restart loses: the environment came back with its users but no
factors, and an empty ListAuthFactors is indistinguishable from
"this user has no MFA". `totp: true` writes the same record the
enrollment route writes, so the seeded factor is listed by
GET .../auth_factors and drives the password grant's existing
mfa_challenge step-up.
@greptile-apps

greptile-apps Bot commented Aug 21, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds declarative TOTP-factor enrollment for seeded users and integrates those factors with the existing MFA challenge flow.

  • Adds the optional totp seed-user field and validates that supplied values are booleans.
  • Inserts seeded authentication-factor records using the existing route-compatible shape.
  • Documents seeded MFA behavior and adds end-to-end coverage for factor listing and password-to-MFA authentication.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the previous YAML parsing documentation issue is corrected, and the configured parser and validation path match the revised explanation.

Important Files Changed

Filename Overview
src/workos/config-validator.ts Validates that the optional TOTP seed setting is boolean and now accurately describes YAML 1.2 parsing behavior.
src/workos/index.ts Adds the public seed option and inserts a route-compatible TOTP authentication factor for opted-in users.
src/workos/seed-auth-factors.spec.ts Covers seeded factor listing, MFA step-up completion, opt-out behavior, and configuration validation.
README.md Documents how seeded TOTP factors affect factor administration and password authentication.

Sequence Diagram

sequenceDiagram
    participant C as Seed config
    participant V as Config validator
    participant S as Seed loader
    participant D as WorkOS store
    participant A as Authenticate route
    C->>V: User with totp: true
    V-->>S: Validated boolean
    S->>D: Insert user and TOTP factor
    A->>D: Check enrolled factors
    D-->>A: TOTP factor exists
    A-->>C: MFA challenge
    C->>A: MFA continuation
    A-->>C: Authenticated session
Loading

Reviews (2): Last reviewed commit: "docs(seed): correct the YAML semantics i..." | Re-trigger Greptile

Comment thread src/workos/config-validator.ts Outdated
The comment claimed YAML parses `totp: yes` to true, but the CLI's
yaml v2 parser follows YAML 1.2, where `yes` — and `no` — are plain
strings. Both are truthy, which is the actual hazard the check
guards against: `totp: no` would otherwise enroll a factor the
config explicitly declined.
@gjtorikian
gjtorikian merged commit df078b0 into main Aug 21, 2026
9 checks passed
@gjtorikian
gjtorikian deleted the fix/seed-totp-factor branch August 21, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Authentication factors cannot be seeded, so MFA administration needs post-boot API calls

1 participant