{"record":{"id":"ae52ec62503aaf8b","repo":"kataras/iris","slug":"auth-refresh-w","errorCode":null,"errorMessage":"auth: refresh: %w","messagePattern":"auth: refresh: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/auth.go","lineNumber":481,"sourceCode":"\tif accessToken == \"\" {\n\t\tif cookieName := s.config.Cookie.Name; cookieName != \"\" {\n\t\t\taccessToken = ctx.GetCookie(cookieName, context.CookieEncoding(s.securecookie))\n\t\t}\n\t}\n\n\treturn accessToken\n}\n\n// Refresh accepts a previously generated refresh token (from SigninHandler) and\n// returns a new access and refresh token pair.\nfunc (s *Auth[T]) Refresh(ctx stdContext.Context, refreshToken []byte) ([]byte, []byte, error) {\n\tif !s.refreshEnabled {\n\t\treturn nil, nil, fmt.Errorf(\"auth: refresh: disabled\")\n\t}\n\n\tt, _, err := s.verify(ctx, refreshToken)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"auth: refresh: %w\", err)\n\t}\n\n\t// refresh the tokens, both refresh & access tokens will be renew to prevent\n\t// malicious 😈 users that may hold a refresh token.\n\taccessTok, refreshTok, err := s.sign(t)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"auth: refresh: %w\", err)\n\t}\n\n\treturn accessTok, refreshTok, nil\n}\n\n// RefreshHandler reads the request body which should include data for `RefreshRequest` structure\n// and sends a new access and refresh token pair,\n// also sets the cookie to the new encrypted access token value.\n// See `Refresh` method for more.\nfunc (s *Auth[T]) RefreshHandler(ctx *context.Context) {\n\tvar req RefreshRequest","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/auth/auth.go#L463-L499","documentation":"Auth.Refresh failed while verifying the supplied refresh token via the internal s.verify(). The refresh token could not be parsed, its signature is invalid, or it has expired.","triggerScenarios":"Auth.Refresh(ctx, refreshToken) receives token bytes that fail s.verify: expired refresh token, signed with a revoked/rotated KIDRefresh key, or garbage/truncated bytes from the client.","commonSituations":"A client holds a refresh token past its TTL; the server rotated its refresh signing secret; the client sent an access token instead of a refresh token to the refresh endpoint.","solutions":["Inspect the wrapped error (expired vs signature vs malformed)","Have the client fall back to a full Signin when the refresh token is expired","Ensure the client sends the refresh token (not the access token) to RefreshHandler","Keep KIDRefresh key material stable across instances, or persist old keys for a grace window"],"exampleFix":"// before\nnewAccess, newRefresh, err := auth.Refresh(ctx, body.Token) // sends access token\n// after\nnewAccess, newRefresh, err := auth.Refresh(ctx, body.RefreshToken)\nif err != nil { // expired: force re-login\n    http.Error(w, \"session expired\", 401); return\n}","handlingStrategy":"try-catch","validationCode":"body := new(RefreshRequest)\nif err := json.NewDecoder(r.Body).Decode(body); err != nil || len(body.RefreshToken) == 0 {\n    http.Error(w, \"refresh token required\", http.StatusBadRequest); return\n}","typeGuard":"func isRefreshToken(b []byte) bool { return len(b) > 0 && strings.Count(string(b), \".\") == 2 }","tryCatchPattern":"access, refresh, err := auth.Refresh(ctx, refreshToken)\nif err != nil {\n    // expired/invalid refresh token cannot be renewed — force full re-login\n    http.Error(w, \"session expired, please sign in\", http.StatusUnauthorized); return\n}","preventionTips":["Always send the refresh token, not the access token, to the refresh endpoint","Treat any Refresh verification failure as terminal: require Signin, never retry the same token","Keep KIDRefresh key material stable or support a verification grace window during rotation","Set refresh-token TTL appropriately for expected session lengths"],"tags":["jwt","refresh-token","expired-token"],"backgroundTag":"jwt-refresh-token-expired","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}