ForgeWP

Registration & Default Roles

Create accounts with server-owned registration policy and approved profile fields.

Registration and default roles

Registration creates a WordPress account. Signing in establishes a session. These are separate outcomes: an account can be created successfully while the visitor remains signed out.

Account creation and sign-in are separate

A successful register() call means account creation succeeded. Check useWpUser() before showing content that assumes a signed-in session.

Start with a registration form

src/components/MemberSignup.tsx
1import { WpAuthProvider, WpRegisterForm } from "@forgewp/auth"
2
3export default function MemberSignup() {
4  return (
5    <WpAuthProvider>
6      <WpRegisterForm className="max-w-md" />
7    </WpAuthProvider>
8  )
9}

WpRegisterForm requires a provider and accepts className and an optional onSuccess callback. Its built-in interface asks for username, email, and password. In email-only server mode, WordPress generates the username from the email; build a custom interface if you want to omit the username control.

For custom forms, call register(username, email, password, metadata?) from useWpAuth(). It returns a boolean promise: true means the registration request succeeded, not that a user is necessarily signed in. Read useWpUser() for the resulting user and render error from useWpAuth() for failures. Avoid automatically redirecting every successful registration to a protected page.

Configure the initial policy

wp.config.ts — Auth policy excerpt
1auth: {
2  defaultRole: "subscriber",
3  features: {
4    registration: true,
5    emailVerification: true,
6    blockLoginUntilVerified: true,
7    autoLoginAfterSignup: false,
8  },
9  registrationMetaFields: ["first_name", "last_name"],
10}

Place this auth property inside your existing theme configuration. Administrators with manage_options can manage the installed policy at Settings → ForgeWP Auth. Saved WordPress settings take priority over source defaults. The approved metadata keys remain developer-owned configuration.

Table · 3 columns
Source setting
Default
Effect
features.registration
true
Allows the generated signup endpoint to create accounts
defaultRole
subscriber
Role assigned by the server to newly created accounts
features.emailVerification
false
Sends a verification email and marks a new account unverified
features.blockLoginUntilVerified
false
Rejects password login for an unverified account when verification is enabled
features.autoLoginAfterSignup
true
Requests automatic sign-in after signup when verification is disabled

Choose an existing role with the permissions new public members actually need. A role is a collection of capabilities; use an unprivileged role such as subscriber for ordinary membership. The public request does not select the role.

When verification is enabled, signup does not auto-login even when autoLoginAfterSignup is enabled. Blocking later password login is controlled separately by blockLoginUntilVerified. A successful verification link currently signs the account in.

Follow the registration outcome

Flowchart
Rendering diagram...

For example, a verified-membership site can enable verification and block unverified password login. Successful signup should show a check-your-email message rather than immediately sending the visitor into a protected page.

Optional profile metadata

Public signup accepts no extra metadata keys by default. Declare permitted profile keys through auth.registrationMetaFields, then pass only those keys in the fourth argument to register(), for example { first_name: "Alex" }.

Keys must be unique lowercase identifiers using letters, digits, and underscores, beginning with a letter. Role, capability, session, and ForgeWP-owned keys are reserved. Approved values must be scalars and are sanitized as text; nested arrays or objects are rejected. Do not approve plugin-owned control or authorization fields as public profile data.

An unsupported key or non-scalar value rejects the request before account creation. These writes are server-side profile data; the allowlist does not generate extra form controls or profile editing screens.

Approve profile data deliberately

first_name and last_name describe a person. Roles, capabilities, session tokens, and verification flags control access and remain server-owned. The metadata allowlist also does not create input controls for you.

What success means

Table · 2 columns
Server policy
Successful signup result
Verification enabled
Account created; show a check-your-email message
Verification disabled, auto-login disabled
Account created; offer a login link
Verification disabled, auto-login enabled
Account created and the server attempts to establish a session

If automatic sign-in fails after account creation, the endpoint preserves registration success and asks the visitor to sign in. It does not claim an authenticated user or undo the newly created account.

The endpoint returns success: true; a response without an authenticated user also includes requiresVerification. Both provider and standalone hooks accept that account-created response. register() returns a boolean rather than the raw response object.

Provider and standalone registration share local preview rules for disabled registration, duplicate accounts, email-only username generation, approved scalar profile fields, role capabilities, and whether signup should establish a mock session. In Vite, these public defaults come from wp.config.ts; changing that configuration requests a full reload. Both paths record mock users and simulated verification messages through the development API. Confirm real role assignment, WordPress sanitization, cookies, and delivery on an installed theme.

Continue with Email Verification.

Show account-created feedback

A verification email can fail after the account has been created. In that case register() still returns true and exposes a separate notice explaining the next step. Do not submit registration again for the same account; offer a resend action instead. The built-in WpRegisterForm renders this notice.

Place this status component inside the same WpAuthProvider as your custom signup form:

src/components/SignupStatus.tsx
1import { useWpAuth } from "@forgewp/auth"
2
3export default function SignupStatus() {
4  const { loading, error, notice } = useWpAuth()
5  if (loading) return <p role="status">Working on your request?</p>
6  if (error) return <p role="alert">{error}</p>
7  return notice ? <p role="status">{notice}</p> : null
8}

The raw signup response includes verificationEmailSent when returning an account-created result without a user: true means WordPress mail transport accepted the send, false means it failed, and null means verification was not required. Acceptance by mail transport does not prove inbox delivery. The hook exposes the server message through notice rather than returning this raw response object.