{"record":{"id":"da36acfa9c76e23b","repo":"kataras/iris","slug":"auth-signout-verify-w","errorCode":null,"errorMessage":"auth: signout: verify: %w","messagePattern":"auth: signout: verify: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"auth/auth.go","lineNumber":532,"sourceCode":"\trefreshToken := jwt.BytesToString(refreshTokenBytes)\n\n\ts.trySetCookie(ctx, accessToken)\n\n\tresp := SigninResponse{\n\t\tAccessToken:  accessToken,\n\t\tRefreshToken: refreshToken,\n\t}\n\tctx.JSON(resp)\n}\n\n// Signout accepts the access token and a boolean which reports whether\n// the signout should be applied to all tokens generated for a specific user (logout from all devices)\n// or just the provided token's one.\n// It calls the Provider's InvalidateToken(all=false) or InvalidateTokens (all=true).\nfunc (s *Auth[T]) Signout(ctx stdContext.Context, token []byte, all bool) error {\n\tt, standardClaims, err := s.verify(ctx, token)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"auth: signout: verify: %w\", err)\n\t}\n\n\tfor i, n := 0, len(s.providers)-1; i <= n; i++ {\n\t\tp := s.providers[i]\n\n\t\tif all {\n\t\t\terr = p.InvalidateTokens(ctx, t)\n\t\t} else {\n\t\t\terr = p.InvalidateToken(ctx, standardClaims, t)\n\t\t}\n\n\t\tif err != nil {\n\t\t\tif i == n { // last provider errored.\n\t\t\t\treturn err\n\t\t\t}\n\t\t\t// keep trying.\n\t\t\tcontinue\n\t\t}","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/kataras/iris/blob/7bedaf55a0b64bbb2248a5845a2c60d81a30996a/auth/auth.go#L514-L550","documentation":"Auth.Signout failed while verifying the token that identifies the session to invalidate. Before revoking tokens via providers, Signout verifies the presented token; a failed verification aborts signout with this wrapper.","triggerScenarios":"Auth.Signout(ctx, token, all) is called with token bytes that s.verify rejects: expired access token, wrong signing key, or malformed input — reached via signoutHandler.","commonSituations":"Client tries to sign out with an already-expired token; the server rotated keys so old tokens no longer verify; a client posts an empty body to the signout endpoint.","solutions":["Inspect the wrapped verification error (expired vs signature)","Allow signout with expired tokens by relaxing verification for signout, or treat this as already-signed-out and return success","Ensure clients still hold a valid (unexpired) token when calling signout","Check key configuration matches what issued the token"],"exampleFix":"// before\nif err := auth.Signout(ctx, tok, false); err != nil { http.Error(w, err.Error(), 500) }\n// after\nif err := auth.Signout(ctx, tok, false); err != nil {\n    // expired token = already logged out client-side; do not hard-fail\n    http.Error(w, \"already signed out\", 401); return\n}","handlingStrategy":"try-catch","validationCode":"tok := strings.TrimSpace(strings.TrimPrefix(req.Header.Get(\"Authorization\"), \"Bearer \"))\nif tok == \"\" { http.Error(w, \"missing token\", http.StatusUnauthorized); return }","typeGuard":null,"tryCatchPattern":"if err := auth.Signout(ctx, token, all); err != nil {\n    // an expired token often means the user is already signed out client-side\n    log.Printf(\"signout verify failed: %v\", err)\n    http.Error(w, \"already signed out\", http.StatusUnauthorized); return\n}","preventionTips":["Call signout while the access token is still valid","Consider treating expired-token signout as a no-op success UX-wise","Keep prior keys valid during rotation so in-flight sessions can sign out","Never log full tokens when debugging verification failures"],"tags":["jwt","token-verification","signout"],"backgroundTag":"jwt-token-expired","analyzedSha":"7bedaf55a0b64bbb2248a5845a2c60d81a30996a","analyzedAt":"2026-08-30T20:38:16.250Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}