Class PasswordResetService
java.lang.Object
com.svenruppert.jsentinel.accountlifecycle.PasswordResetService
Password-reset workflow over a
PasswordResetTokenStore.
Three-step lifecycle:
request(subject, ttl)— generates a fresh plain token, persists only its hash, publishes aPasswordResetRequestedaudit event, and hands the plain token to theJSentinelNotificationSenderso the application can deliver it (mail, SMS, log).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.consume(plain)— marks the record consumed exactly once and publishes aPasswordResetCompletedaudit 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.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordTuple returned fromrequest: the plain token (caller forwards it to the user via the notification sender) and the persisted record (handy for tests / audit hooks). -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intDefault token entropy in bytes (256 bits). -
Constructor Summary
ConstructorsConstructorDescriptionPasswordResetService(PasswordResetTokenStore store, PasswordHasher hasher, JSentinelAuditService auditService, JSentinelNotificationSender notificationSender) Convenience constructor: tenantTenantId.DEFAULT, system clock, 256-bit token source.PasswordResetService(PasswordResetTokenStore store, PasswordHasher hasher, JSentinelAuditService auditService, JSentinelNotificationSender notificationSender, TenantId tenant, Clock clock, Supplier<String> tokenSource) Full constructor. -
Method Summary
Modifier and TypeMethodDescriptionMarks the supplied plain token consumed and publishes aPasswordResetCompletedaudit + aJSentinelNotification.Kind.PASSWORD_RESET_COMPLETEDnotification.intPurges every expired record in the backing store.Issues a new reset token.intDrops every token issued tosubjectIdin this service's tenant.Validates a candidate plain token.
-
Field Details
-
DEFAULT_TOKEN_BYTES
public static final int DEFAULT_TOKEN_BYTESDefault token entropy in bytes (256 bits).- See Also:
-
-
Constructor Details
-
PasswordResetService
public PasswordResetService(PasswordResetTokenStore store, PasswordHasher hasher, JSentinelAuditService auditService, JSentinelNotificationSender notificationSender) Convenience constructor: tenantTenantId.DEFAULT, system clock, 256-bit token source.- Parameters:
store- backing token store; non-nullhasher- password hasher used to hash tokens before persistence; non-nullauditService- audit sink; non-nullnotificationSender- 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-nullhasher- password hasher used to hash tokens before persistence; non-nullauditService- audit sink; non-nullnotificationSender- notification dispatcher; non-nulltenant- tenant scope;nullbecomesTenantId.DEFAULTclock- time source; non-nulltokenSource- supplier producing plain token strings handed to the notification sender; non-null, must return non-blank values
-
-
Method Details
-
request
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-nullttl- lifetime; must be strictly positive- Returns:
- issued token (plain value + persisted record)
-
validate
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 yieldsOptional.empty()- Returns:
- matching live record, if any
-
consume
Marks the supplied plain token consumed and publishes aPasswordResetCompletedaudit + aJSentinelNotification.Kind.PASSWORD_RESET_COMPLETEDnotification. 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
Drops every token issued tosubjectIdin 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
-