RefreshTokenService

@Service
class RefreshTokenService(@Value(value = "${security.refresh.cookie-name:__Host-rt}") cookieName: String, @Value(value = "${security.refresh.ttl-days:30}") ttlDays: Long, @Value(value = "${security.refresh.allow-rebind-once:false}") allowRebindOnce: Boolean)

Refresh tokens, explained simply:

  • Think of a refresh token as a long-lived “session receipt” stored in an HttpOnly cookie.

  • Every time you use it, we swap it for a brand new one (so an old one can’t be reused).

  • If an old token shows up again, we assume it was stolen and shut down the whole session family.

This in-memory implementation is perfect for dev/single-node. Use Redis/DB for production.

Key ideas:

  • Each refresh token belongs to a family (one login session) and is bound to a DPoP key thumbprint (jkt).

  • Rotate-on-use and reuse detection keep sessions safe.

Constructors

Link copied to clipboard
constructor(@Value(value = "${security.refresh.cookie-name:__Host-rt}") cookieName: String, @Value(value = "${security.refresh.ttl-days:30}") ttlDays: Long, @Value(value = "${security.refresh.allow-rebind-once:false}") allowRebindOnce: Boolean)

Types

Link copied to clipboard
object Companion

Functions

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
fun issue(userId: Long, jwkThumbprint: String?): RefreshTokenIssue

Start a new session: create a fresh refresh token record bound to the user (and DPoP key if present).

Link copied to clipboard

Revoke a session family by presenting one of its token ids. Handy for logout when we read the cookie value.

Link copied to clipboard
fun revokeFamily(familyId: String)

Revoke every refresh token in a session family. Use this when we detect reuse or other anomalies.

Link copied to clipboard
@Scheduled(fixedDelayString = "${security.refresh.cleanup-interval-ms:900000}", initialDelayString = "${security.refresh.cleanup-initial-delay-ms:60000}")
fun scheduledClearExpired()
Link copied to clipboard
fun validateAndRotate(presentedId: String, presentedJkt: String?): RotationResult

Use-then-rotate flow for refresh tokens.