Class TokenStore

java.lang.Object
ubic.gemma.rest.security.TokenStore

@Component public class TokenStore extends Object
In-memory bearer-token store backing the /rest/v2/login flow used by the curation-UI SPA (see AUTH_FOR_SPA_RECCE.md Option C).

Tokens are opaque random UUIDs minted on a successful POST /rest/v2/login and resolved back to the original Authentication object by BearerTokenAuthenticationFilter.

NOTE: design choices (deliberately punted for the MVP — flagged for follow-up)

  • TTL: 8h sliding (Caffeine.expireAfterAccess(Duration)). Hardcoded; easy to promote to a configurable Gemma property later. Picked to cover one curator workday without forcing a re-login mid-session.
  • Concurrent sessions: allowed. Multiple live tokens per principal is fine (curators may have a laptop + desktop). No single-session enforcement here; gemma-web's <s:concurrency-control> only applied to the JSESSIONID flow which the standalone REST WAR doesn't speak.
  • Audit-log auth events: skipped for v1. Gemma's audit machinery is entity-scoped (AuditTrail on Securables); plumbing "session created / revoked" auth events through it is non-trivial and not blocking for the curator-UI MVP. Add later if/when ops wants login auditing.
  • In-memory only. WAR restart invalidates every live token; curators re-login. Acceptable for the MVP. Graduation path is a gemd.auth_tokens table or Redis; the store abstraction does not preclude either.

Thread-safe by virtue of Caffeine's underlying ConcurrentMap.

See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    static final Duration
    Sliding TTL: a token is invalidated 8 hours after its last successful lookup.
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    issue(org.springframework.security.core.Authentication authentication)
    Mint a new opaque token for the given authenticated principal.
    org.springframework.security.core.Authentication
    lookup(String token)
    Look up the Authentication previously associated with this token, refreshing the sliding-TTL clock.
    void
    revoke(String token)
    Revoke a token.

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • TTL

      public static final Duration TTL
      Sliding TTL: a token is invalidated 8 hours after its last successful lookup. Picked to cover one curator workday; promoted to a config property later if needed.
  • Constructor Details

    • TokenStore

      public TokenStore()
  • Method Details

    • issue

      public String issue(org.springframework.security.core.Authentication authentication)
      Mint a new opaque token for the given authenticated principal.
      Parameters:
      authentication - a successful Authentication (must be isAuthenticated() == true); typically the result of AuthenticationManager.authenticate(...).
      Returns:
      a fresh random UUID token string. Callers should treat it as opaque.
    • lookup

      @Nullable public org.springframework.security.core.Authentication lookup(String token)
      Look up the Authentication previously associated with this token, refreshing the sliding-TTL clock. Returns null if the token is unknown or expired.
    • revoke

      public void revoke(String token)
      Revoke a token. Idempotent: removing an already-removed token is a no-op (does not throw, does not log). Used by POST /rest/v2/logout.