Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
193 commits
Select commit Hold shift + click to select a range
7dc05d7
Add a filter so consumers can add links to the problem area.
StevenDufresne Jul 11, 2024
16a1d5c
Document filter.
StevenDufresne Jul 11, 2024
8918127
Pass all the links so we can control link location.
StevenDufresne Jul 12, 2024
5a60522
Refactor to display links outside of backup_providers.
StevenDufresne Sep 23, 2024
61121cd
Update doc block for filter and bump version.
StevenDufresne Sep 23, 2024
5ac8a23
Update documentation and remove <li> from the string.
StevenDufresne Sep 23, 2024
98f3571
add abspath
masteradhoc Jan 30, 2026
4ae9f1f
add abspath to two-factor.php
masteradhoc Jan 30, 2026
198f9b9
add abspath to class-two-factor-fido-u2f.php
masteradhoc Jan 30, 2026
c7e7a07
add abspath to class-two-factor-fido-u2f-admin.php
masteradhoc Jan 30, 2026
f0e9baf
add abspath to class-two-factor-dummy.php
masteradhoc Jan 30, 2026
ae8f578
add abspath to class-two-factor-totp.php
masteradhoc Jan 30, 2026
4e504ec
add abspath to class-two-factor-backup-codes.php
masteradhoc Jan 30, 2026
6ce4761
add abspath to class-two-factor-email.php
masteradhoc Jan 30, 2026
a819e3a
add abspath to class-two-factor-core.php
masteradhoc Jan 30, 2026
dc8b9d8
Clarify TOTP setup instructions - draft
masteradhoc Jan 31, 2026
435a7b9
update required wordpress version
masteradhoc Feb 1, 2026
2b9f54b
Merge branch 'master' into patch-7
kasparsd Feb 1, 2026
e1567f1
Merge branch 'master' into patch-5
masteradhoc Feb 1, 2026
fa284be
Merge branch 'master' into patch-3
masteradhoc Feb 1, 2026
c1224e5
add date and time information above setup instructions
masteradhoc Feb 1, 2026
d73217c
fix WordPress.Security.EscapeOutput.OutputNotEscaped
masteradhoc Feb 1, 2026
79894fa
adjust error message
masteradhoc Feb 2, 2026
6f94160
Merge branch 'master' into patch-7
masteradhoc Feb 3, 2026
a8510d8
Merge branch 'master' into patch-8
kasparsd Feb 9, 2026
0f71524
Merge branch 'WordPress:master' into patch-5
masteradhoc Feb 9, 2026
3604e2d
rework semantic
masteradhoc Feb 9, 2026
f96f67a
Merge branch 'WordPress:master' into patch-8
masteradhoc Feb 9, 2026
2244b84
fix feedback of kasparsd
masteradhoc Feb 9, 2026
1be422d
fix: ensure execution stops after redirects.
sjinks Feb 9, 2026
f5c2619
style: use `exit;` to stay aligned with WP coding standards
sjinks Feb 9, 2026
0f2bc77
Merge branch 'master' into patch-7
masteradhoc Feb 10, 2026
d134cc5
Update RELEASING.md
jeffpaul Feb 11, 2026
e188e87
add html data attribute with unix timestamp
masteradhoc Feb 11, 2026
b22a264
Merge branch 'master' into patch-1
masteradhoc Feb 11, 2026
f062bab
fix: ensure execution stops after redirects
kasparsd Feb 13, 2026
52d6389
add date and time information above totp setup instructions
kasparsd Feb 13, 2026
748ffe8
Update required WordPress Version
kasparsd Feb 13, 2026
73b376c
Clarify TOTP setup instructions
kasparsd Feb 13, 2026
ebd78e6
Update RELEASING.md
kasparsd Feb 13, 2026
f170ee7
Default to escaping since _default_wp_die_handler doesn't do it and w…
kasparsd Feb 13, 2026
ef984bc
Merge branch 'master' into patch-8
kasparsd Feb 13, 2026
9520331
Merge pull request #776 from masteradhoc/patch-8
kasparsd Feb 13, 2026
3991f53
optimize email text for totp
masteradhoc Feb 13, 2026
111a1fd
remove ABSPATH
masteradhoc Feb 13, 2026
da9caec
remove ABSPATH
masteradhoc Feb 13, 2026
f598dcb
remove ABSPATH
masteradhoc Feb 13, 2026
1b4f213
remove ABSPATH
masteradhoc Feb 13, 2026
4381148
remove ABSPATH
masteradhoc Feb 13, 2026
d762e49
remove ABSPATH
masteradhoc Feb 13, 2026
96fd30d
remove ABSPATH
masteradhoc Feb 13, 2026
3488646
remove ABSPATH
masteradhoc Feb 13, 2026
70eb07f
Merge pull request #760 from masteradhoc/patch-3
kasparsd Feb 13, 2026
a11d9fc
@kasparsd feedback
masteradhoc Feb 13, 2026
012778b
Merge branch 'master' into patch-1
masteradhoc Feb 13, 2026
793ce26
Group styles, scripts and remove extra leftover markup
kasparsd Feb 13, 2026
423abae
Additional markup to allow dynamic time updates
kasparsd Feb 13, 2026
30cbe1e
Group the input as step 3
kasparsd Feb 13, 2026
0aef4af
Inline right away
kasparsd Feb 13, 2026
fd2f3db
Better wording
kasparsd Feb 13, 2026
f13b5cc
Make it shorter and to the point
kasparsd Feb 13, 2026
759a186
Match the UX
kasparsd Feb 13, 2026
0c8e3a5
Spelling
kasparsd Feb 13, 2026
ddf09ad
feat(totp): Consistent user experience for TOTP setup
kasparsd Feb 13, 2026
afd2af9
Merge branch 'master' into patch-1
kasparsd Feb 13, 2026
295dc23
Use constant and input directly
kasparsd Feb 13, 2026
4d54d51
Move into own line
kasparsd Feb 13, 2026
94e24d5
Doesn’t need double quotes
kasparsd Feb 13, 2026
8a7dec3
Include username and how user login with password was successfull
kasparsd Feb 13, 2026
66bc1ef
Merge pull request #789 from masteradhoc/patch-1
kasparsd Feb 13, 2026
f4d9b71
Request two factor only if session is not present
kasparsd Feb 13, 2026
463abe2
chore: clear spaces
kasparsd Feb 13, 2026
e4a1867
Describe why we’re calling a provider fetcher
kasparsd Feb 13, 2026
10e8f74
Match the current behavior
kasparsd Feb 13, 2026
8b49903
Always disable WP core login cookies
kasparsd Feb 13, 2026
c2cd777
Specify the return types
kasparsd Feb 17, 2026
e547cfc
Only configured providers should be set to enabled
kasparsd Feb 17, 2026
cbe4754
Ensure the method is configured before storing it as enabled
kasparsd Feb 17, 2026
b908f44
this is now a key
kasparsd Feb 17, 2026
a807a58
Specify the return type
kasparsd Feb 17, 2026
4460a6e
Account for the list being instances of providers
kasparsd Feb 17, 2026
0bb6825
Add error tracking
kasparsd Feb 17, 2026
c6283a8
Relay our errors to WP core profile logic
kasparsd Feb 17, 2026
7ebde70
Pass along our errors
kasparsd Feb 17, 2026
93c16c4
Describe the return type
kasparsd Feb 17, 2026
3badf51
Introduce our own error API
kasparsd Feb 17, 2026
6a52da8
Ensure there are errors to render
kasparsd Feb 17, 2026
f434e31
Add an error per provider
kasparsd Feb 17, 2026
2f6316d
Type inputs
kasparsd Feb 17, 2026
1a7853d
Per linter
kasparsd Feb 17, 2026
8d1c840
This is actually different from all others
kasparsd Feb 17, 2026
a5397aa
Per linter
kasparsd Feb 17, 2026
fdec4b0
Per linter
kasparsd Feb 17, 2026
9707660
Per phpstan this is always WP_Error
kasparsd Feb 17, 2026
6def757
Match the filter_authenticate argument count
kasparsd Feb 17, 2026
2672bc6
no blank trailing spaces per linter
kasparsd Feb 17, 2026
6664dfc
Merge pull request #793 from WordPress/fix-two-factor-enable-enforce
kasparsd Feb 17, 2026
e4444e5
Release 0.15.0 (#790)
kasparsd Feb 17, 2026
47e8f51
Bump qs from 6.14.1 to 6.14.2 (#794)
dependabot[bot] Feb 17, 2026
3060a4d
chore: Apply automatic linter formatter and updated associated Compos…
kasparsd Feb 17, 2026
84b9449
Ensure that doesn't 'fail open' if existing providers poof. (#586)
georgestephanis Feb 18, 2026
b817723
fix(backup-codes): minor UI issues and JS var leak
sjinks Feb 21, 2026
15514d4
fix: constructors must not return value
sjinks Feb 21, 2026
76f4584
remove version update in this PR
masteradhoc Feb 22, 2026
8409840
fix @since version number
masteradhoc Feb 22, 2026
96f611e
remove type from script
masteradhoc Feb 22, 2026
59190c9
remove type from email provider
masteradhoc Feb 22, 2026
3fe4d28
remove type from totp provider
masteradhoc Feb 22, 2026
2dbd1f9
remove type from backup codes
masteradhoc Feb 22, 2026
2316910
add css from style tag to css file
masteradhoc Feb 22, 2026
ebe94fb
remove style from totp
masteradhoc Feb 22, 2026
8b979e2
Fix lint
masteradhoc Feb 22, 2026
066a582
cleanup
masteradhoc Feb 23, 2026
1f03ba4
add since docs to backup-codes
masteradhoc Feb 23, 2026
f9632af
add since docs
masteradhoc Feb 23, 2026
0a86103
add since docs
masteradhoc Feb 23, 2026
9b097ba
add since to docblocks
masteradhoc Feb 23, 2026
19b04cd
add since docs
masteradhoc Feb 23, 2026
0c7e766
add since docs
masteradhoc Feb 23, 2026
c6aabe0
fix parameter doc
masteradhoc Feb 23, 2026
b5f6292
add phpstan error
masteradhoc Feb 23, 2026
7cbf109
fix phpstan issues
masteradhoc Feb 23, 2026
f2ce8e9
Revert "add since docs"
masteradhoc Feb 23, 2026
240e700
Revert "add since docs"
masteradhoc Feb 23, 2026
57cc207
Merge branch 'phpstan-fixes' of https://github.com/masteradhoc/two-fa…
masteradhoc Feb 23, 2026
282bde3
update phpstan version
masteradhoc Feb 23, 2026
ba96fbb
Merge pull request #809 from masteradhoc/since-documentations
masteradhoc Feb 24, 2026
5d6e459
Merge pull request #805 from masteradhoc/script-types
masteradhoc Feb 24, 2026
1a37785
Merge pull request #803 from sjinks/fix/ctor
masteradhoc Feb 24, 2026
8bb0ea7
Merge pull request #801 from sjinks/fix/backup-codes
masteradhoc Feb 24, 2026
813a97f
Merge branch 'master' into style-totp-file
masteradhoc Feb 24, 2026
fe10ce0
Merge pull request #806 from masteradhoc/style-totp-file
masteradhoc Feb 24, 2026
8963111
fix phpcs
masteradhoc Feb 24, 2026
5fb7af8
Merge branch 'master' into remove-php-version-compare
masteradhoc Feb 24, 2026
7194981
Merge branch 'master' into add/filter-for-support-links
masteradhoc Feb 24, 2026
fa8e05d
fix Syntax error from merge conflicts
masteradhoc Feb 24, 2026
c8fcc8c
New Style for Backup Codes (#804)
masteradhoc Feb 24, 2026
b8d4ad5
revert phpstan update
masteradhoc Feb 24, 2026
fe00276
apply georges suggestions
masteradhoc Feb 24, 2026
94c6f46
change to int as mixed is not available <php7.4
masteradhoc Feb 25, 2026
df7541f
Merge pull request #810 from masteradhoc/phpstan-fixes
masteradhoc Feb 25, 2026
0eceadb
Fix inline documentation for hooks to follow WordPress Coding Standar…
aslamdoctor Feb 26, 2026
34428d7
Merge pull request #808 from masteradhoc/remove-php-version-compare
masteradhoc Feb 28, 2026
a623f28
Address review feedback: fix @since versions and @param spacing
aslamdoctor Mar 1, 2026
3e31f4d
Merge branch 'master' into 815-inline-docs-hooks
masteradhoc Mar 1, 2026
933fd5a
Merge pull request #817 from aslamdoctor/815-inline-docs-hooks
masteradhoc Mar 1, 2026
74b52ba
Bump basic-ftp from 5.0.5 to 5.2.0 (#816)
dependabot[bot] Mar 1, 2026
a778ec9
Remove U2F (#439)
georgestephanis Mar 1, 2026
829b64c
Apply suggestion from @masteradhoc
georgestephanis Mar 2, 2026
f43c351
Apply suggestion from @masteradhoc
georgestephanis Mar 2, 2026
fcb0acc
Apply suggestion from @masteradhoc
georgestephanis Mar 2, 2026
93f194e
Apply suggestion from @masteradhoc
georgestephanis Mar 2, 2026
6c38a52
Apply suggestion from @masteradhoc
georgestephanis Mar 2, 2026
ef9455c
Apply suggestion from @masteradhoc
georgestephanis Mar 2, 2026
da2f7a0
Apply suggestion from @georgestephanis
georgestephanis Mar 2, 2026
1d6cdc5
Merge pull request #615 from StevenDufresne/add/filter-for-support-links
masteradhoc Mar 2, 2026
107b7b6
Move class-two-factor-core.php login styles from inline to enqueued s…
masteradhoc Mar 2, 2026
8d26530
commit as those changes were left out accidentely in #807
masteradhoc Mar 2, 2026
258e11b
fix(totp): delete user TOTP key after disabling the provider (#802)
sjinks Mar 2, 2026
a328ead
upgrade readme header
masteradhoc Mar 13, 2026
ae23b23
revert commit
masteradhoc Mar 13, 2026
aca617f
upgrade checkout and node actions
masteradhoc Mar 14, 2026
85914c8
upgrade checkout and node action
masteradhoc Mar 14, 2026
acb26c0
Merge pull request #835 from masteradhoc/readme-update
masteradhoc Mar 15, 2026
2396bb5
adjust static version numbers to SHA
masteradhoc Mar 16, 2026
1033457
switch from static version
masteradhoc Mar 16, 2026
0ca4d87
Merge pull request #837 from masteradhoc/job-upgrades
jeffpaul Mar 16, 2026
2f97fc5
Bump @tootallnate/once and @wordpress/scripts (#839)
dependabot[bot] Mar 18, 2026
04e80a5
accessibility fix (#830)
masteradhoc Mar 18, 2026
ce931ef
Bump immutable from 5.1.3 to 5.1.5 (#823)
dependabot[bot] Mar 18, 2026
28f759d
Bump svgo from 3.3.2 to 3.3.3 (#824)
dependabot[bot] Mar 18, 2026
97b4a1f
Bump simple-git from 3.28.0 to 3.33.0 (#826)
dependabot[bot] Mar 18, 2026
10072b3
fix wrong settings link anchor (#828)
masteradhoc Mar 18, 2026
3c6bcd6
[468] Improves test coverage and reliability (#825)
nimesh-xecurify Mar 18, 2026
98a9ad8
fix deploy error
masteradhoc Mar 18, 2026
7ba92ee
reimplement commit #835
masteradhoc Mar 18, 2026
0773017
Small typos & i18n updates (#829)
masteradhoc Mar 18, 2026
f3b454d
Move inline JS to external script files (#814)
aslamdoctor Mar 18, 2026
5a8a654
Add AGENTS.md, TESTS.md and CLAUDE.md
georgestephanis Mar 18, 2026
84132b7
Update AGENTS.md
masteradhoc Mar 18, 2026
f3ede1f
Merge pull request #840 from WordPress/add/AGENTS.md
masteradhoc Mar 18, 2026
be3bf6f
Add Settings Page (#764)
masteradhoc Mar 18, 2026
6e94348
Merge remote-tracking branch 'origin/master' into 797-ensure-configur…
kasparsd Mar 19, 2026
3bf71f0
fix: generic errors have the provider empty
kasparsd Mar 19, 2026
65e28fd
fix: use only string error types, if persent
kasparsd Mar 19, 2026
4f7a41c
chore: the first one is returned
kasparsd Mar 19, 2026
7dde89d
Both enabled_providers and existing_providers are arrays with string …
kasparsd Mar 19, 2026
fb8ccb2
Merge remote-tracking branch 'origin/master' into 797-ensure-configur…
kasparsd Mar 19, 2026
3c8c088
This gets populated with instances during array_intersect_key()
kasparsd Mar 19, 2026
ab51db1
Merge pull request #798 from WordPress/797-ensure-configured-on-save
kasparsd Mar 19, 2026
cbc73d5
typo
masteradhoc Mar 19, 2026
a0f6973
Add email verification before activation
faisalahammad Mar 20, 2026
1bca12d
Fix @since tags and resolve CI test failures
faisalahammad Mar 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

- name: Setup Node
uses: actions/setup-node@v3
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
node-version-file: '.nvmrc'

- name: Setup PHP and Composer
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
with:
php-version: '5.6'
tools: composer:v2
Expand All @@ -36,7 +36,7 @@ jobs:
run: npm run build

- name: WordPress.org asset and readme update
uses: 10up/action-wordpress-plugin-asset-update@stable
uses: 10up/action-wordpress-plugin-asset-update@2480306f6f693672726d08b5917ea114cb2825f7 # v2.2.0
if: github.ref_name == 'trunk'
env:
# Note: this action doesn't support BUILD_DIR so it pushes the raw readme.txt
Expand All @@ -46,7 +46,7 @@ jobs:

- name: WordPress.org deploy
id: deploy
uses: 10up/action-wordpress-plugin-deploy@stable
uses: 10up/action-wordpress-plugin-asset-update@2480306f6f693672726d08b5917ea114cb2825f7 # v2.2.0
if: startsWith( github.ref, 'refs/tags/' )
with:
generate-zip: true
Expand All @@ -57,7 +57,7 @@ jobs:


- name: Upload release asset
uses: softprops/action-gh-release@v2
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1
if: startsWith( github.ref, 'refs/tags/' )
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/props-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:

steps:
- name: Gather a list of contributors
uses: WordPress/props-bot-action@trunk
uses: WordPress/props-bot-action@992186595bc18334988a431c317237c48b7711a5 # v1.0.0
with:
format: 'git'

Expand Down
24 changes: 12 additions & 12 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
node-version-file: '.nvmrc'
Expand All @@ -37,15 +37,15 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

- name: Setup PHP and Composer
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
with:
php-version: '8.3'

- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
node-version-file: '.nvmrc'
Expand Down Expand Up @@ -94,15 +94,15 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
with:
php-version: '8.3'

- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
node-version-file: '.nvmrc'
Expand All @@ -111,7 +111,7 @@ jobs:
run: npm install

- name: Start the Docker testing environment
uses: nick-fields/retry@v3
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with:
timeout_minutes: 10
max_attempts: 3
Expand All @@ -135,15 +135,15 @@ jobs:
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0

- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2.37.0
with:
php-version: '8.3'

- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: 'npm'
node-version-file: '.nvmrc'
Expand Down
2 changes: 1 addition & 1 deletion .wordpress-org/blueprints/blueprint.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
"landingPage": "/wp-admin/profile.php#application-passwords-section",
"landingPage": "/wp-admin/profile.php#two-factor-options",
"preferredVersions": {
"php": "7.4",
"wp": "latest"
Expand Down
Binary file modified .wordpress-org/screenshot-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .wordpress-org/screenshot-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .wordpress-org/screenshot-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .wordpress-org/screenshot-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed .wordpress-org/screenshot-5.png
Binary file not shown.
109 changes: 109 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# AI Instructions

Two-Factor is a WordPress plugin, potentially eventually merging into WordPress Core, that provides Multi-Factor Authentication for WordPress interactive logins. It is network-enabled and can be activated across a WordPress multisite network.

## Development Environment

Requires Docker. Uses `@wordpress/env` to run a local WordPress install in containers.

```bash
npm install
npm run build
npm run env start
```

For code coverage support: `npm run env start -- --xdebug=coverage`

`npm test` and `npm run composer` are wrappers that execute commands inside the `tests-cli` wp-env container at the plugin path. Tests must be run through these wrappers, not directly with `phpunit`.

## Commands

### Testing

@TESTS.md

### Linting & Static Analysis

```bash
npm run lint # all linters (PHP, CSS, JS)
npm run lint:php # PHPCS with WordPress + VIP-Go standards
npm run lint:phpstan # PHPStan static analysis (level 0)
npm run lint:css # wp-scripts lint-style
npm run lint:js # wp-scripts lint-js
npm run format # auto-fix PHPCS and JS/CSS issues
```

### Build

```bash
npm run build
```

The Grunt build copies all distributable files to `dist/` (respecting `.distignore`) and copies `node_modules/qrcode-generator/qrcode.js` into `dist/includes/`. The `qrcode-generator` package is a **runtime JS dependency** — it is not present in `includes/` in the source tree and must be built before the plugin is usable in a browser context. Always run `npm run build` after a fresh checkout.

## Architecture

The plugin follows a provider pattern. `Two_Factor_Core` owns the login interception and orchestration; individual providers handle their own credential prompts and validation.

### Core Files

- **`two-factor.php`** — Entry point. Defines `TWO_FACTOR_DIR` and `TWO_FACTOR_VERSION`, loads all core files, instantiates `Two_Factor_Compat`, and calls `Two_Factor_Core::add_hooks()`.
- **`class-two-factor-core.php`** — Central class. Owns the login flow, user meta, nonce management, rate limiting, session tracking, REST API endpoints, and the user profile settings UI.
- **`class-two-factor-compat.php`** — Compatibility shims for third-party plugins (currently: Jetpack SSO). New integrations go here; the goal is to avoid any plugin-specific logic outside this file.
- **`providers/class-two-factor-provider.php`** — Abstract base class all providers extend. Defines the required interface: `get_label()`, `is_available_for_user()`, `authentication_page()`, `validate_authentication()`, and optional hooks for REST routes, settings UI, and uninstall cleanup.
- **`providers/`** — Concrete providers: `class-two-factor-totp.php`, `class-two-factor-email.php`, `class-two-factor-backup-codes.php`, `class-two-factor-dummy.php`.
- **`includes/`** — Custom `login_header()` and `login_footer()` template functions that replace the WordPress core versions with additional filter hooks. Excluded from PHPCS because they intentionally deviate from core function signatures. Do not modify files in includes/ directly. They are intentionally kept close to WordPress core function signatures to ease future merging into Core. Any functional changes should go through the filter hooks they expose instead.
- **`tests/`** — PHPUnit tests. See [TESTS.md](TESTS.md).

### Login Flow

1. User submits username/password.
2. `Two_Factor_Core::filter_authenticate()` runs at priority **31** on the `authenticate` filter (one above WP core's 30). If 2FA is required, it intercepts the `WP_User` object to prevent WP from issuing auth cookies.
3. `Two_Factor_Core::wp_login()` runs at priority `PHP_INT_MAX` on `wp_login`, renders the 2FA prompt, and exits.
4. On 2FA form submission, `login_form_validate_2fa` action handles validation and issues the final auth cookie only if the second factor passes.

Auth cookies set during the password phase are tracked via `collect_auth_cookie_tokens` and invalidated before the 2FA step.

### Provider Registration

Providers are registered via the `two_factor_providers` filter, which receives and returns an array of the form:

```php
array( 'Class_Name' => '/absolute/path/to/class-file.php' )
```

The key (class name) is what gets stored in user meta. A per-provider `two_factor_provider_classname_{$provider_key}` filter allows swapping a provider's implementing class without changing its key. Use `two_factor_providers_for_user` to control which providers are available to a specific user.

**The `Two_Factor_Dummy` provider is only available when `WP_DEBUG` is `true`.** It is removed at runtime by `enable_dummy_method_for_debug()` in all other environments. If a dummy provider isn't appearing, check `WP_DEBUG`.

### Provider Self-Registration Pattern

Each concrete provider registers its own hooks in its constructor:

- REST routes → `rest_api_init`
- Assets → `admin_enqueue_scripts`, `wp_enqueue_scripts`
- User profile UI section → `two_factor_user_options_{ClassName}` action

New providers should follow this pattern rather than registering hooks from outside the class.

### Key User Meta (constants on `Two_Factor_Core`)

| Constant | Meta Key | Purpose |
|---|---|---|
| `PROVIDER_USER_META_KEY` | `_two_factor_provider` | Active provider class name |
| `ENABLED_PROVIDERS_USER_META_KEY` | `_two_factor_enabled_providers` | Array of enabled provider class names |
| `USER_META_NONCE_KEY` | `_two_factor_nonce` | Login nonce |
| `USER_RATE_LIMIT_KEY` | `_two_factor_last_login_failure` | Rate limiting timestamp |
| `USER_FAILED_LOGIN_ATTEMPTS_KEY` | `_two_factor_failed_login_attempts` | Failed attempt count |
| `USER_PASSWORD_WAS_RESET_KEY` | `_two_factor_password_was_reset` | Flags compromised-password reset |

### REST API

Namespace: `two-factor/1.0` (constant `Two_Factor_Core::REST_NAMESPACE`). Each provider that exposes REST endpoints registers its own routes in `register_rest_routes()` called from its constructor.

## Code Standards

- PHP 7.2+ compatibility required; enforced by PHPCompatibilityWP.
- Follows WordPress coding standards (WPCS) and WordPress-VIP-Go rules.
- `includes/` is excluded from PHPCS — those files intentionally override core functions.
- The codebase does not fully pass all PHPCS checks (known issue [#437](https://github.com/WordPress/two-factor/issues/437)). Do not treat existing violations as license to introduce new ones.
63 changes: 59 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,62 @@

All notable changes to this project will be documented in this file, per [the Keep a Changelog standard](http://keepachangelog.com/), and will adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased] - TBD
## [0.15.0] - 2026-02-13

### Breaking Changes

- Trigger two-factor flow only when expected by @kasparsd in [#660](https://github.com/WordPress/two-factor/pull/660) and [#793](https://github.com/WordPress/two-factor/pull/793).

### New Features

- Include user IP address and contextual warning in two-factor code emails by @todeveni in [#728](https://github.com/WordPress/two-factor/pull/728)
- Consistent user experience for TOTP setup by @kasparsd in [#792](https://github.com/WordPress/two-factor/pull/792)
- Optimize email text for TOTP by @masteradhoc in [#789](https://github.com/WordPress/two-factor/pull/789)
- Add "Settings" action link to plugin list for quick access to profile by @hardikRathi in [#740](https://github.com/WordPress/two-factor/pull/740)
- Additional form hooks by @eric-michel in [#742](https://github.com/WordPress/two-factor/pull/742)
- Full RFC6238 Compatibility by @ericmann in [#656](https://github.com/WordPress/two-factor/pull/656)

### Documentation

- `@since` docs by @masteradhoc in [#781](https://github.com/WordPress/two-factor/pull/781)
- Update user and admin docs, prepare for more screenshots by @jeffpaul in [#701](https://github.com/WordPress/two-factor/pull/701)
- Add changelog & credits, update release notes by @jeffpaul in [#696](https://github.com/WordPress/two-factor/pull/696)
- Clear readme.txt by @masteradhoc in [#785](https://github.com/WordPress/two-factor/pull/785)
- Add date and time information above TOTP setup instructions by @masteradhoc in [#772](https://github.com/WordPress/two-factor/pull/772)
- Clarify TOTP setup instructions by @masteradhoc in [#763](https://github.com/WordPress/two-factor/pull/763)
- Update RELEASING.md by @jeffpaul in [#787](https://github.com/WordPress/two-factor/pull/787)

### Development Updates

- Pause deploys to SVN trunk for merges to `master` by @kasparsd in [#738](https://github.com/WordPress/two-factor/pull/738)
- Fix CI checks for PHP compatability by @kasparsd in [#739](https://github.com/WordPress/two-factor/pull/739)
- Fix Playground refs by @kasparsd in [#744](https://github.com/WordPress/two-factor/pull/744)
- Persist existing translations when introducing new helper text in emails by @kasparsd in [#745](https://github.com/WordPress/two-factor/pull/745)
- Fix `missing_direct_file_access_protection` by @masteradhoc in [#760](https://github.com/WordPress/two-factor/pull/760)
- Fix `mismatched_plugin_name` by @masteradhoc in [#754](https://github.com/WordPress/two-factor/pull/754)
- Introduce Props Bot workflow by @jeffpaul in [#749](https://github.com/WordPress/two-factor/pull/749)
- Plugin Check: Fix Missing $domain parameter by @masteradhoc in [#753](https://github.com/WordPress/two-factor/pull/753)
- Tests: Update to supported WP version 6.8 by @masteradhoc in [#770](https://github.com/WordPress/two-factor/pull/770)
- Fix PHP 8.5 deprecated message by @masteradhoc in [#762](https://github.com/WordPress/two-factor/pull/762)
- Exclude 7.2 and 7.3 checks against trunk by @masteradhoc in [#769](https://github.com/WordPress/two-factor/pull/769)
- Fix Plugin Check errors: `MissingTranslatorsComment` & `MissingSingularPlaceholder` by @masteradhoc in [#758](https://github.com/WordPress/two-factor/pull/758)
- Add PHP 8.5 tests for latest and trunk version of WP by @masteradhoc in [#771](https://github.com/WordPress/two-factor/pull/771)
- Add `phpcs:ignore` for falsepositives by @masteradhoc in [#777](https://github.com/WordPress/two-factor/pull/777)
- Fix(totp): `otpauth` link in QR code URL by @sjinks in [#784](https://github.com/WordPress/two-factor/pull/784)
- Update deploy.yml by @masteradhoc in [#773](https://github.com/WordPress/two-factor/pull/773)
- Update required WordPress Version by @masteradhoc in [#765](https://github.com/WordPress/two-factor/pull/765)
- Fix: ensure execution stops after redirects by @sjinks in [#786](https://github.com/WordPress/two-factor/pull/786)
- Fix `WordPress.Security.EscapeOutput.OutputNotEscaped` errors by @masteradhoc in [#776](https://github.com/WordPress/two-factor/pull/776)

### Dependency Updates

- Bump qs and express by @dependabot[bot] in [#746](https://github.com/WordPress/two-factor/pull/746)
- Bump lodash from 4.17.21 to 4.17.23 by @dependabot[bot] in [#750](https://github.com/WordPress/two-factor/pull/750)
- Bump lodash-es from 4.17.21 to 4.17.23 by @dependabot[bot] in [#748](https://github.com/WordPress/two-factor/pull/748)
- Bump phpunit/phpunit from 8.5.44 to 8.5.52 by @dependabot[bot] in [#755](https://github.com/WordPress/two-factor/pull/755)
- Bump symfony/process from 5.4.47 to 5.4.51 by @dependabot[bot] in [#756](https://github.com/WordPress/two-factor/pull/756)
- Bump qs and body-parser by @dependabot[bot] in [#782](https://github.com/WordPress/two-factor/pull/782)
- Bump webpack from 5.101.3 to 5.105.0 by @dependabot[bot] in [#780](https://github.com/WordPress/two-factor/pull/780)

## [0.14.2] - 2025-12-11
### New Features
Expand Down Expand Up @@ -220,9 +275,9 @@ All notable changes to this project will be documented in this file, per [the Ke
## [0.2.0] - 2018-10-16
- Add developer tools for deploying to WP.org manually.

[Unreleased]: https://github.com/WordPress/two-factor/compare/master...develop
[0.14.0]: https://github.com/WordPress/two-factor/compare/0.14.1...0.14.2
[0.14.0]: https://github.com/WordPress/two-factor/compare/0.14.0...0.14.1
[0.15.0]: https://github.com/WordPress/two-factor/compare/0.14.1...0.15.0
[0.14.2]: https://github.com/WordPress/two-factor/compare/0.14.1...0.14.2
[0.14.1]: https://github.com/WordPress/two-factor/compare/0.14.0...0.14.1
[0.14.0]: https://github.com/WordPress/two-factor/compare/0.13.0...0.14.0
[0.13.0]: https://github.com/WordPress/two-factor/compare/0.12.0...0.13.0
[0.12.0]: https://github.com/WordPress/two-factor/compare/0.11.0...0.12.0
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
Loading
Loading