From cc960860e4109b4eb50721d0b3338df4b859d559 Mon Sep 17 00:00:00 2001 From: wikiapiserver Date: Thu, 25 Jun 2026 14:47:35 +0200 Subject: feat: token refresh with age-based logic - RefreshTokens checks token age and chooses the right path: - refresh_token > 90 days: re-auth via WikimediaLogin (full login) - access_token > 24 hours: refresh via WikimediaTokenRefresh - otherwise: return current tokens - WikimediaTokenRefresh posts to /v1/token-refresh endpoint - Login also uses WikimediaLogin instead of local RotateTokens - Removed dead RotateTokens, RefreshByToken, and randomHex - DSN includes parseTime=true for timestamp columns --- api/handlers.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'api') diff --git a/api/handlers.go b/api/handlers.go index 7918b40..f98dd6b 100644 --- a/api/handlers.go +++ b/api/handlers.go @@ -38,10 +38,6 @@ type loginReq struct { Password string `json:"password"` } -type refreshReq struct { - RefreshToken string `json:"refresh_token"` -} - // --- helper writers --- func writeJSON(w http.ResponseWriter, code int, v any) { @@ -124,6 +120,12 @@ func (h *Handler) Login(w http.ResponseWriter, r *http.Request) { } // --- Refresh: POST /refresh --- +// Accepts username and refresh_token. The refresh_token is used to +// verify identity; RefreshTokens handles the age-based logic. +type refreshReq struct { + Username string `json:"username"` + RefreshToken string `json:"refresh_token"` +} func (h *Handler) Refresh(w http.ResponseWriter, r *http.Request) { ctx, cancel := context.WithTimeout(r.Context(), defaultTimeout) @@ -135,17 +137,17 @@ func (h *Handler) Refresh(w http.ResponseWriter, r *http.Request) { return } - if req.RefreshToken == "" { - badRequest(w, "refresh_token is required") + if req.Username == "" || req.RefreshToken == "" { + badRequest(w, "username and refresh_token are required") return } - - acct, err := h.db.RefreshByToken(ctx, req.RefreshToken) + acct, err := h.db.RefreshTokens(ctx, req.Username, req.RefreshToken) if err != nil { - if err.Error() == "invalid refresh token" { + if err.Error() == "account not found" || err.Error() == "invalid refresh token" { unauthorized(w) return } + log.Printf("refresh error: %v", err) serverError(w, "could not refresh token") return } -- cgit v1.2.3