Skip to content

feat(mfa): add schema for recovery codes factor - #2725

Open
fadymak wants to merge 3 commits into
masterfrom
fm/auth-1526
Open

feat(mfa): add schema for recovery codes factor#2725
fadymak wants to merge 3 commits into
masterfrom
fm/auth-1526

Conversation

@fadymak

@fadymak fadymak commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Adds the schemas required to support MFA recovery codes factor.

Note

To avoid long running migration on Auth server startup due to mfa_factors (user_id) where factor_type = 'recovery_codes', we've decided to denormalize the user_id field and add it to the mfa_recovery_code_sets which would provide similar guarantees of a user only allowed to have a single set of recovery codes.

@fadymak
fadymak requested a review from a team as a code owner August 24, 2026 13:52
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql Outdated
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql

@xlgmokha xlgmokha left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a few questions for you to consider. Otherwise, it looks good to me.

Comment thread migrations/20260824000000_add_recovery_codes_factor_type.up.sql Outdated
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql Outdated
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql Outdated
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql Outdated
id uuid primary key,
user_id uuid not null unique references {{ index .Options "Namespace" }}.users (id) on delete cascade,
mfa_factor_id uuid not null unique references {{ index .Options "Namespace" }}.mfa_factors (id) on delete cascade,
failed_verification_count integer not null default 0 check (failed_verification_count >= 0),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think about failed_attempts vs. failed_verification_count? thinking this terminology would be a good thing to align on because I'll be adding a similar column as part of the OTP work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion as both make sense. The verification terminology comes from the POST /factors/recovery-codes/verify and the rest of the MFA factors.

It boils down to building the feature around the specific MFA terminology versus having something more generic: #2725 (comment)

Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
user_id uuid not null unique references {{ index .Options "Namespace" }}.users (id) on delete cascade,
mfa_factor_id uuid not null unique references {{ index .Options "Namespace" }}.mfa_factors (id) on delete cascade,
failed_verification_count integer not null default 0 check (failed_verification_count >= 0),
verification_locked_until timestamptz,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: wondering if verification_* as a prefix is necessary, or if we could just do locked_until

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's for consistency between failed_verification_count and verification_locked_until.

Comment thread migrations/20260824000001_add_recovery_codes_tables.up.sql
@fadymak
fadymak force-pushed the fm/auth-1526 branch 2 times, most recently from 713c62f to 5f66657 Compare August 31, 2026 09:11
- Adds unique user_id to mfa_recovery_code_sets as a workaround to avoid creating a unique index on mfa_factors (user_id) which would impact large tables.
- Renames fields for consistency
- Adds unique index on mfa_recovery_codes (mfa_recovery_code_set_id, code_hash) to prevent duplicate codes per set.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants