Skip to content

fix(workos): mandate POST server-action sign-out in Next.js skill#33

Merged
nicknisi merged 1 commit into
mainfrom
fix/nextjs-signout-post-action
Jun 8, 2026
Merged

fix(workos): mandate POST server-action sign-out in Next.js skill#33
nicknisi merged 1 commit into
mainfrom
fix/nextjs-signout-post-action

Conversation

@nicknisi

@nicknisi nicknisi commented Jun 8, 2026

Copy link
Copy Markdown
Member

Problem

The Next.js AuthKit reference (read by the workos install LLM agent) didn't pin down the sign-out pattern, so the installer scaffolded an unsafe GET /auth/signout route + <form method="GET">. Sign-out mutates state, so a GET handler is CSRF-exposable (<img src="/auth/signout">) and triggered by Next.js <Link> prefetch on hover. workos doctor flags it as SIGNOUT_GET_HANDLER.

Changes

plugins/workos/skills/workos/references/workos-authkit-nextjs.md:

  • New "Sign out with a POST server action, never a GET route" section: inline 'use server' action for Server Components, separate app/auth/actions.ts module for client components, and "delete the GET route, don't switch it to POST".
  • New SIGNOUT_GET_HANDLER troubleshooting entry mapping the doctor finding to the fix.
  • New verification-step grep (audit checklist) that fails if a GET sign-out route exists — so the installer agent self-corrects before marking complete.

Release note

This reaches npx workos@latest users only after a @workos/skills release + a CLI dep bump (currently @workos/skills@0.6.0).

Related

🤖 Generated with Claude Code

Sign-out mutates state, so a GET route handler is unsafe (CSRF + Next.js
<Link> prefetch can trigger logout). The Next.js reference now documents a
POST server-action pattern, a SIGNOUT_GET_HANDLER troubleshooting entry, and
a verification-step grep that fails if a GET sign-out route is generated.

This is the source-side fix for the installer scaffolding an insecure GET
sign-out (workos doctor flags it as SIGNOUT_GET_HANDLER).

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@nicknisi nicknisi merged commit a479b91 into main Jun 8, 2026
3 checks passed
@nicknisi nicknisi deleted the fix/nextjs-signout-post-action branch June 8, 2026 20:56
@greptile-apps

greptile-apps Bot commented Jun 8, 2026

Copy link
Copy Markdown

Greptile Summary

This PR hardens the WorkOS AuthKit Next.js reference guide against a class of sign-out CSRF/prefetch vulnerabilities by mandating POST server actions over GET route handlers. It adds inline code examples for both Server Component and Client Component sign-out patterns, a new SIGNOUT_GET_HANDLER troubleshooting entry, and a rg-based audit check in the verification checklist that fails if a GET sign-out route is detected.

  • New guidance section documents the POST server-action pattern for sign-out in both Server and Client Component contexts, with an explicit instruction to delete any existing GET route rather than convert it.
  • New audit check (feat: consolidate all skills into single-source references #6) uses rg with a path glob to flag export GET in sign-out route files before the installer marks the task complete.
  • New troubleshooting entry maps the workos doctor SIGNOUT_GET_HANDLER finding to the corrective steps.

Confidence Score: 4/5

Safe to merge; the core security guidance is correct and the audit check logic is sound. Two minor documentation clarity issues exist but do not undermine the security intent.

The security guidance itself (use POST server actions, delete the GET route) is correct and the rg audit command reliably catches the most common naming patterns. Two small rough edges: the server-component code snippet omits the signOut import (an LLM installer copying just that block would get a reference error), and a parenthetical in troubleshooting step 3 could lead someone to believe swapping the form method attribute alone is sufficient.

plugins/workos/skills/workos/references/workos-authkit-nextjs.md — the server-component example and troubleshooting step 3 warrant a quick read-through.

Important Files Changed

Filename Overview
plugins/workos/skills/workos/references/workos-authkit-nextjs.md Adds sign-out POST server action guidance, a SIGNOUT_GET_HANDLER troubleshooting entry, and a new audit rg check; the server-component code snippet is missing its signOut import and one troubleshooting step contains a misleading method=POST parenthetical.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User clicks Sign Out] --> B{Component type?}
    B -- Server Component --> C["Inline server action\n(async () => { 'use server'; signOut(); })"]
    B -- Client Component --> D["Import signOutAction\nfrom app/auth/actions.ts"]
    D --> E["app/auth/actions.ts\n'use server'\nexport async function signOutAction()"]
    C --> F["POST request to Next.js runtime"]
    E --> F
    F --> G["signOut() clears session"]
    G --> H["Redirect to WorkOS Logout URI"]
    X["GET /auth/signout route"] -. CSRF / prefetch unsafe .-> FAIL["workos doctor flags\nSIGNOUT_GET_HANDLER"]
    FAIL --> FIX["Delete GET route\nUse POST server action"]
    FIX --> F
Loading

Reviews (1): Last reviewed commit: "fix(workos): mandate POST server-action ..." | Re-trigger Greptile

Comment on lines +209 to +213
```tsx
<form action={async () => { 'use server'; await signOut(); }}>
<button type="submit">Sign out</button>
</form>
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Missing import in server-component snippet

The inline-action code block calls signOut() without showing its import. An LLM installer agent (or a developer) copying only this block would produce ReferenceError: signOut is not defined. The import is shown later in the client-component section (app/auth/actions.ts) but not here. Adding import { signOut } from '@workos-inc/authkit-nextjs'; at the top of the snippet (or in a preceding comment) would make the example self-contained.


1. Move sign-out to a POST server action (see "Sign out with a POST server action, never a GET route" above).
2. Delete the `GET` sign-out route entirely.
3. Ensure the sign-out `<form>` uses a server-action `action={...}` (or `method="POST"`), not `method="GET"`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The parenthetical (or method="POST") is misleading: steps 1 and 2 already say to move sign-out to a server action and delete the GET route, so at this point the form's action should point to the server-action function — there is no remaining GET route to flip to POST. Leaving the hint in implies that simply changing the method attribute on the form is an acceptable alternative, but without a corresponding POST handler the form would 405. Removing the parenthetical keeps the fix unambiguous.

Suggested change
3. Ensure the sign-out `<form>` uses a server-action `action={...}` (or `method="POST"`), not `method="GET"`.
3. Ensure the sign-out `<form>` uses a server-action `action={...}`, not `method="GET"`.

nicknisi added a commit to workos/cli that referenced this pull request Jun 8, 2026
Picks up the Next.js sign-out POST server-action guidance (workos/skills#33),
so the installer agent no longer scaffolds an unsafe GET sign-out route.
nicknisi added a commit to workos/cli that referenced this pull request Jun 8, 2026
)

* fix: gate install success on doctor's auth-pattern security checks

The installer ran build/typecheck self-correction but never ran doctor's
authPatterns checks, so an insecure GET sign-out (SIGNOUT_GET_HANDLER) could
pass the build and ship as a "successful" install while `workos doctor`
immediately flagged it.

- Add src/lib/validation/security-checks.ts: runs doctor's security subset
  (GET sign-out, client-leaked/in-source API keys, ungitignored .env, mixed
  env) against the install dir with no network.
- Wire into agent-runner: the self-correction loop now feeds security findings
  back to the agent, and a final gate throws on error-severity findings that
  survive retries (success: false, non-zero exit, commit step skipped).
- Point the SIGNOUT_GET_HANDLER finding at a live docs URL (old
  /docs/authkit/sign-out 404s).

* chore(deps): bump @workos/skills to 0.6.1

Picks up the Next.js sign-out POST server-action guidance (workos/skills#33),
so the installer agent no longer scaffolds an unsafe GET sign-out route.

* chore: formatting

* test: cover API_KEY_LEAKED_TO_CLIENT blocking path; clarify warning comment

Addresses Greptile review on #175:
- Add a unit test for the API_KEY_LEAKED_TO_CLIENT blocking code (a
  NEXT_PUBLIC_-prefixed secret in .env.local), mirroring the API_KEY_IN_SOURCE
  test, so a regression in the prefix/key detection is caught.
- Correct the self-correction comment: warning findings ride along only when a
  retry is already triggered by an error or build failure; they are otherwise
  surfaced in the final validation report.

* fix: emit retry-summary telemetry only after the security gate passes

Addresses Greptile review on #175:
- Move the 'agent retry summary' (passed_after_retry: true) capture below the
  security gate so a blocked install no longer emits a contradictory
  pass-after-retry event alongside 'security gate blocked install'.
- Use obviously-fake fixture key strings in the spec (still satisfy the
  detection regex) so secrets scanners and the no-hardcoded-secrets rule stay
  quiet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant