Skip to content

feat(credential-password): opt-in verified email requirement for sign-in #37

Description

@nalejandroveron

Problem

Applications that require a verified email before credential login currently need their own enforcement. Enabling email verification sends a token, but does not prevent an unverified user from signing in or receiving a session during signup.

Confirmed with core v0.2.2 / credential-password v0.2.1 and upstream master at 8660ad3: authenticateUser checks the password without checking EmailVerifiedAt, and automatic sign-in on signup defaults to enabled.

Proposed solution

Add an opt-in credential-plugin option:

credentialpassword.New(
    credentialpassword.WithRequireEmailVerification(true),
)

Proposed behavior:

  • Default to false, preserving existing behavior.
  • When enabled, check verification after successful password validation and before session creation. Reject unverified users with a distinguishable verification-required error (proposed HTTP 403), without issuing a session or cookie.
  • Continue returning the ordinary invalid-credentials error for incorrect passwords, regardless of verification status.
  • Apply the policy to both email and username credential sign-in, including the programmatic sign-in API.
  • Let signup succeed and trigger verification, but suppress automatic sign-in while the new user remains unverified, even if auto-sign-in is otherwise enabled.
  • Keep the policy scoped to credential authentication; do not change other authentication plugins or retroactively revoke existing sessions.

The HTTP sign-in handler currently maps every authentication error to invalid credentials, so it would also need to preserve the verification-required error after a correct password.

Verification and resend flow

Token verification is already public, but POST /email-verifications requires a session. Users who cannot sign in need a way to request another token after expiry or delivery failure.

Before implementation, I would like to agree on whether this should be a public email-based resend flow or a credential-authenticated resend flow. A public flow should return a generic response for unknown/already-verified addresses and include rate limiting. Documentation should cover signup → verify → login and the interaction with disabled email verification.

Alternatives considered

  • A local SessionManagerProvider wrapper can reject unverified session creation, but requires application-specific plumbing and applies more broadly than a credential-only policy.
  • Middleware on protected resources permits login and a session; it does not satisfy the requirement to reject login itself.
  • Disabling automatic sign-in on signup alone still permits manual login.

Affected module

  • plugins/credential-password
  • limen (core), if signed-out resend support is included
  • docs / TypeScript client documentation

Proposed validation

Tests for unchanged defaults, verified login, unverified login with no session/cookie, incorrect passwords, username login, signup without auto-sign-in, and successful login after token verification. Any new resend path should cover expiry/retry behavior, generic responses and rate limiting.

I searched existing issues and pull requests and did not find a matching proposal. I would like to contribute a focused PR once the intended behavior and resend scope are agreed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions