Getting Started¶
Requirements¶
| Dependency | Version |
|---|---|
| PHP | ≥ 7.4 |
| WordPress | ≥ 6.0 |
| WPGraphQL (optional) | ≥ 1.14 |
| wp-graphql-headless-login / AxeWP (optional) | any |
WPGraphQL and AxeWP are only required for the headless/GraphQL flow. The plugin works as a pure WordPress OTP replacement without them.
Installation¶
The plugin is a Composer package. Install it into a WordPress project that manages its plugins via Composer (e.g. Bedrock or a custom root composer.json).
Via Packagist (production)¶
Via path repository (local development)¶
// composer.json in your WordPress project root
{
"repositories": [
{
"type": "path",
"url": "../../plugins/package-wp-otp"
}
],
"require": {
"subscribed/wp-otp": "*"
}
}
Composer (with composer/installers) installs the plugin to wp-content/plugins/wp-otp/ automatically because composer.json declares "type": "wordpress-plugin".
After installation¶
Activate the plugin in WP Admin → Plugins, or via WP-CLI:
Configuration¶
Settings are managed under Settings → WP OTP in the WordPress admin.
| Setting | Default | Description |
|---|---|---|
| Token duration | 5 minutes | How long a code remains valid before expiring |
| Code length | 6 | Number of characters in the generated code (4–12) |
| Character set | numeric | numeric, alpha, or alphanumeric — see below |
| Max failed attempts | 5 | Token is revoked after this many wrong codes, forcing the user to request a new one |
| Email logo URL | (empty) | URL to the logo shown at the top of the OTP email. Leave empty to use the site name as text |
| Email logo max height | 50 px | Maximum height of the logo image in the email (20–500 px) |
Character sets¶
| Value | Example | Notes |
|---|---|---|
numeric | 483920 | Digits only. Best for SMS-style entry; mobile shows numeric keyboard |
alpha | xkqmbt | Lowercase letters only |
alphanumeric | x4k9mq | Lowercase letters + digits |
Note: If wp-graphql-headless-login (AxeWP) is not installed, the settings page under Settings → WP OTP is always visible. When AxeWP is installed the same settings page is still the single source of truth — AxeWP's own settings panel is not used for OTP settings.
WordPress login vs GraphQL login¶
The plugin supports two independent login flows that can run side by side:
- Traditional WP login (
wp-login.php) — replaces the password form with an OTP flow. All users (admins, shop managers, editors, etc.) are affected. - GraphQL / headless login — exposes a
requestOtpmutation and integrates with AxeWP'sloginmutation. Used by Nuxt or other headless frontends.
Both flows share the same OtpStore (WordPress Transients) and OtpSettings.