SignupPasswordPolicy
\Benecaster\Support\SignupPasswordPolicy
The single definition of the password rules applied when a subscriber chooses their own password during signup. Two surfaces collect one — the free and paid branches of [benecaster_subscribe] — and they live in different classes. Without one shared definition they drift, and a subscriber told “at least twelve characters” on one form and refused at fourteen on another has no way to understand what happened.
[benecaster_follower_signup] is no longer one of them. That form is email-first and collects no password at all: the follower is provisioned with one nobody knows and emailed a single-use signed link that signs them in. A password POSTed to it anyway is dropped before it reaches the signup handler, so this policy never runs for it.
This applies only where a human is signing themselves up. Accounts created for somebody — admin bulk enrollment, manual subscriber add, the donation-completion webhook — have nobody at a keyboard to ask, so they keep a generated password and receive a set-password email instead. That path is benecaster_subscriber_account_provisioned.
The policy is length only, and that is deliberate. There is no composition rule — no required digit, symbol, or mixed case. WordPress core applies no server-side composition policy of its own; its strength meter is an affordance, not a gate. Inventing one here would mean the same person on the same site faces different password rules depending on which form they happen to be looking at.
There is no filter for these values. The minimum is not configurable, because the number displayed on the form comes from WordPress’s own wp_get_password_hint() string — a site that changed the rule would show one figure and enforce another. If you need a different policy, validate in your own handler before the request reaches Benecaster.
Methods
| Method | Visibility | Since | Description |
|---|---|---|---|
validate( string $password ): ?string |
— | — | Returns null when the password is acceptable, or one of the ERROR_* constants. Checks in order: empty, then byte ceiling, then character length — the ceiling is checked before anything expensive touches the input. |
length( string $password ): int |
— | — | Length in characters, not bytes. A twelve-character passphrase in a non-Latin script is twelve characters to the person who typed it; measuring bytes would reject it as too short and fail exactly the users the plugin's internationalisation exists to serve. Falls back to byte length only where mb_strlen() is unavailable. |
message( string $code ): string |
— | — | The translated, form-ready message for an ERROR_* code. Unknown codes fall through to the 'please choose a password' wording rather than throwing. |
Constants
| Name | Value | Description |
|---|---|---|
MIN_LENGTH |
12 |
Minimum length in characters. Twelve is WordPress's own figure, not one invented here — wp_get_password_hint() tells every WordPress user their password should be at least twelve characters, and that hint is the string these forms display. Enforcing a different number would mean showing one rule and applying another. |
MAX_BYTES |
4096 |
Ceiling in bytes. Not a security property of the password — it guards hashing cost. wp_hash_password() is deliberately slow, so an unbounded input on a public, unauthenticated route is a cheap way to spend the site's CPU. Far above any real password and far below anything worth hashing. |
ERROR_REQUIRED |
'required' |
No password was supplied. |
ERROR_TOO_LONG |
'too_long' |
Over MAX_BYTES. Surfaces on the subscribe endpoint as benecaster_password_invalid. |
ERROR_TOO_WEAK |
'too_weak' |
Under MIN_LENGTH. Surfaces on the subscribe endpoint as benecaster_password_too_weak. |
Notes
Client-side checks are a courtesy, never the gate. The subscribe form's JavaScript uses the same minimum so the visitor is not surprised on submit, but POST /shows/{id}/subscribe validates independently — its permission_callback is open, so every submitted password is attacker-controlled until the server says otherwise.
The two public signup surfaces report failure differently, and both are deliberate. [benecaster_subscribe] returns 400 benecaster_password_too_weak (or benecaster_password_invalid) with the message from message(). [benecaster_follower_signup] only ever reaches validation for an address that has no existing account — for one that does, the submitted password is ignored silently and the form reports success, because erroring there would turn the form into an email-enumeration oracle.