package hwsauth import ( "net/http" "git.haelnorr.com/h/golib/jwt" "github.com/pkg/errors" ) // RefreshAuthTokens manually refreshes the user's authentication tokens. // This revokes the old tokens and issues new ones. // Requires a database transaction for token operations. // // Note: Token refresh is normally handled automatically by the Authenticate middleware. // Use this method only when you need explicit control over token refresh. // // Example: // // func refreshHandler(w http.ResponseWriter, r *http.Request) { // tx, _ := db.BeginTx(r.Context(), nil) // defer tx.Rollback() // if err := auth.RefreshAuthTokens(tx, w, r); err != nil { // http.Error(w, "Refresh failed", http.StatusUnauthorized) // return // } // tx.Commit() // w.WriteHeader(http.StatusOK) // } func (auth *Authenticator[T, TX]) RefreshAuthTokens(tx TX, w http.ResponseWriter, r *http.Request) error { aT, rT, err := auth.getTokens(tx, r) if err != nil { return errors.Wrap(err, "getTokens") } rememberMe := map[string]bool{ "session": false, "exp": true, }[aT.TTL] // issue new tokens for the user err = jwt.SetTokenCookies(w, r, auth.tokenGenerator, rT.SUB, true, rememberMe, auth.SSL) if err != nil { return errors.Wrap(err, "jwt.SetTokenCookies") } err = revokeTokenPair(jwt.DBTransaction(tx), aT, rT) if err != nil { return errors.Wrap(err, "revokeTokenPair") } return nil } // Get the tokens from the request func (auth *Authenticator[T, TX]) getTokens( tx TX, r *http.Request, ) (*jwt.AccessToken, *jwt.RefreshToken, error) { // get the existing tokens from the cookies atStr, rtStr := jwt.GetTokenCookies(r) aT, err := auth.tokenGenerator.ValidateAccess(jwt.DBTransaction(tx), atStr) if err != nil { return nil, nil, errors.Wrap(err, "tokenGenerator.ValidateAccess") } rT, err := auth.tokenGenerator.ValidateRefresh(jwt.DBTransaction(tx), rtStr) if err != nil { return nil, nil, errors.Wrap(err, "tokenGenerator.ValidateRefresh") } return aT, rT, nil } // Revoke the given token pair func revokeTokenPair( tx jwt.DBTransaction, aT *jwt.AccessToken, rT *jwt.RefreshToken, ) error { err := aT.Revoke(tx) if err != nil { return errors.Wrap(err, "aT.Revoke") } err = rT.Revoke(tx) if err != nil { return errors.Wrap(err, "rT.Revoke") } return nil }