feat(09-01): implement separate-admin genre list tracer
- Audience-aware mint, verify, refresh, and backend guard keep frontend tokens compatible - Cabana mounts raw admin login, list schema, and record list behind admin.jwt.secret - Framework migration seeds Winter backend users and developer/publisher roles
This commit is contained in:
@@ -15,6 +15,18 @@ import (
|
||||
// jwt-auth: the later of the old exp and iat+refreshTTL, plus one minute, so
|
||||
// a logged-out token cannot be refreshed again for the rest of its refresh window.
|
||||
func Refresh(secret, tokenString string, refreshTTL time.Duration, bl BlacklistStore, grace time.Duration, issuerURL string) (string, error) {
|
||||
return refreshAudience(secret, tokenString, AudienceUser, true, refreshTTL, bl, grace, issuerURL)
|
||||
}
|
||||
|
||||
// RefreshAudience reissues a token that already carries audience. Missing aud is rejected.
|
||||
func RefreshAudience(secret, tokenString, audience string, refreshTTL time.Duration, bl BlacklistStore, grace time.Duration, issuerURL string) (string, error) {
|
||||
if strings.TrimSpace(audience) == "" {
|
||||
return "", errors.New("bouncer: jwt audience is empty")
|
||||
}
|
||||
return refreshAudience(secret, tokenString, audience, false, refreshTTL, bl, grace, issuerURL)
|
||||
}
|
||||
|
||||
func refreshAudience(secret, tokenString, audience string, allowMissing bool, refreshTTL time.Duration, bl BlacklistStore, grace time.Duration, issuerURL string) (string, error) {
|
||||
if strings.TrimSpace(secret) == "" {
|
||||
return "", errors.New("bouncer: jwt secret is empty")
|
||||
}
|
||||
@@ -29,6 +41,14 @@ func Refresh(secret, tokenString string, refreshTTL time.Duration, bl BlacklistS
|
||||
if sub == "" {
|
||||
return "", errors.New(msgRequiredClaims)
|
||||
}
|
||||
auds := claimAudiences(claims)
|
||||
if len(auds) == 0 {
|
||||
if !allowMissing {
|
||||
return "", errors.New(msgBadSignature)
|
||||
}
|
||||
} else if !audienceMatches(claims, audience) {
|
||||
return "", errors.New(msgBadSignature)
|
||||
}
|
||||
iat, ok := claimTime(claims, "iat")
|
||||
if !ok || time.Now().After(iat.Add(refreshTTL)) {
|
||||
return "", errors.New("Token has expired and can no longer be refreshed")
|
||||
@@ -48,7 +68,7 @@ func Refresh(secret, tokenString string, refreshTTL time.Duration, bl BlacklistS
|
||||
if !expOK || ttl <= 0 {
|
||||
return "", errors.New(msgRequiredClaims)
|
||||
}
|
||||
next, _, err := Mint(secret, sub, issuerURL, ttl)
|
||||
next, _, err := MintAudience(secret, sub, issuerURL, ttl, audience)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user