Class PasswordResetService

java.lang.Object
com.svenruppert.jsentinel.accountlifecycle.PasswordResetService

@ExperimentalJSentinelApi public final class PasswordResetService extends Object
Password-reset workflow over a PasswordResetTokenStore.

Three-step lifecycle:

  1. request(subject, ttl) — generates a fresh plain token, persists only its hash, publishes a PasswordResetRequested audit event, and hands the plain token to the JSentinelNotificationSender so the application can deliver it (mail, SMS, log).
  2. validate(plain) — looks the token up by its hash and returns the record only when it exists, is in the configured tenant, has not expired, and has not been consumed.
  3. consume(plain) — marks the record consumed exactly once and publishes a PasswordResetCompleted audit event. Subsequent attempts on the same token return empty.

The plain token is generated server-side, returned exactly once from request, and never persisted — only the hash reaches the store. An attacker who exfiltrates the store cannot derive the plain token.

Bound to one TenantId at construction. Multi-tenant deployments instantiate one service per tenant.

  • Field Details

    • DEFAULT_TOKEN_BYTES

      public static final int DEFAULT_TOKEN_BYTES
      Default token entropy in bytes (256 bits).
      See Also:
  • Constructor Details

    • PasswordResetService

      public PasswordResetService(PasswordResetTokenStore store, PasswordHasher hasher, JSentinelAuditService auditService, JSentinelNotificationSender notificationSender)
      Convenience constructor: tenant TenantId.DEFAULT, system clock, 256-bit token source.
      Parameters:
      store - backing token store; non-null
      hasher - password hasher used to hash tokens before persistence; non-null
      auditService - audit sink; non-null
      notificationSender - notification dispatcher; non-null
    • PasswordResetService

      public PasswordResetService(PasswordResetTokenStore store, PasswordHasher hasher, JSentinelAuditService auditService, JSentinelNotificationSender notificationSender, TenantId tenant, Clock clock, Supplier<String> tokenSource)
      Full constructor.
      Parameters:
      store - backing token store; non-null
      hasher - password hasher used to hash tokens before persistence; non-null
      auditService - audit sink; non-null
      notificationSender - notification dispatcher; non-null
      tenant - tenant scope; null becomes TenantId.DEFAULT
      clock - time source; non-null
      tokenSource - supplier producing plain token strings handed to the notification sender; non-null, must return non-blank values
  • Method Details

    • request

      public PasswordResetService.IssuedToken request(SubjectId subjectId, Duration ttl)
      Issues a new reset token. Returns the plain token exactly once (also delivered to the notification sender).
      Parameters:
      subjectId - subject the reset is for; non-null
      ttl - lifetime; must be strictly positive
      Returns:
      issued token (plain value + persisted record)
    • validate

      public Optional<PasswordResetTokenRecord> validate(String plainToken)
      Validates a candidate plain token. Returns the record only when it is known, in this service's tenant, not expired and not yet consumed. Expired records are purged from the store as a side effect.
      Parameters:
      plainToken - plain token from the carrier; null/blank yields Optional.empty()
      Returns:
      matching live record, if any
    • consume

      public Optional<PasswordResetTokenRecord> consume(String plainToken)
      Marks the supplied plain token consumed and publishes a PasswordResetCompleted audit + a JSentinelNotification.Kind.PASSWORD_RESET_COMPLETED notification. Returns the consumed record exactly once; subsequent calls on the same token yield empty.
      Parameters:
      plainToken - plain token; null/blank yields empty
      Returns:
      consumed record on the successful transition, empty otherwise (unknown token, wrong tenant, already consumed, expired)
    • revokeAll

      public int revokeAll(SubjectId subjectId)
      Drops every token issued to subjectId in this service's tenant.
      Parameters:
      subjectId - subject; non-null
      Returns:
      number of tokens removed
    • purgeExpired

      public int purgeExpired()
      Purges every expired record in the backing store. Spans all tenants — call once globally rather than per-tenant.
      Returns:
      number of records purged