package jwt import ( "database/sql" "github.com/google/uuid" ) // Token is the common interface implemented by both AccessToken and RefreshToken. // It provides methods to access token claims and manage token revocation. type Token interface { // GetJTI returns the unique token identifier (JTI claim) GetJTI() uuid.UUID // GetEXP returns the expiration timestamp (EXP claim) GetEXP() int64 // GetSUB returns the subject/user ID (SUB claim) GetSUB() int // GetScope returns the token scope ("access" or "refresh") GetScope() string // Revoke adds this token to the blacklist, preventing future use. // Must be called within a database transaction context. Revoke(*sql.Tx) error // CheckNotRevoked verifies that this token has not been blacklisted. // Returns true if the token is valid, false if revoked. // Must be called within a database transaction context. CheckNotRevoked(*sql.Tx) (bool, error) } // AccessToken represents a JWT access token with all its claims. // Access tokens are short-lived and used for authenticating API requests. // They can be marked as "fresh" for sensitive operations like password changes. type AccessToken struct { ISS string // Issuer, generally TrustedHost IAT int64 // Time issued at EXP int64 // Time expiring at TTL string // Time-to-live: "session" or "exp". Used with 'remember me' SUB int // Subject (user) ID JTI uuid.UUID // UUID-4 used for identifying blacklisted tokens Fresh int64 // Time freshness expiring at Scope string // Should be "access" gen *TokenGenerator } // RefreshToken represents a JWT refresh token with all its claims. // Refresh tokens are longer-lived and used to obtain new access tokens // without requiring the user to re-authenticate. type RefreshToken struct { ISS string // Issuer, generally TrustedHost IAT int64 // Time issued at EXP int64 // Time expiring at TTL string // Time-to-live: "session" or "exp". Used with 'remember me' SUB int // Subject (user) ID JTI uuid.UUID // UUID-4 used for identifying blacklisted tokens Scope string // Should be "refresh" gen *TokenGenerator } func (a AccessToken) GetJTI() uuid.UUID { return a.JTI } func (r RefreshToken) GetJTI() uuid.UUID { return r.JTI } func (a AccessToken) GetEXP() int64 { return a.EXP } func (r RefreshToken) GetEXP() int64 { return r.EXP } func (a AccessToken) GetSUB() int { return a.SUB } func (r RefreshToken) GetSUB() int { return r.SUB } func (a AccessToken) GetScope() string { return a.Scope } func (r RefreshToken) GetScope() string { return r.Scope } func (a AccessToken) Revoke(tx *sql.Tx) error { return a.gen.revoke(tx, a) } func (r RefreshToken) Revoke(tx *sql.Tx) error { return r.gen.revoke(tx, r) } func (a AccessToken) CheckNotRevoked(tx *sql.Tx) (bool, error) { return a.gen.checkNotRevoked(tx, a) } func (r RefreshToken) CheckNotRevoked(tx *sql.Tx) (bool, error) { return r.gen.checkNotRevoked(tx, r) }