Skip to main content

Api

Test Descope auth from your IDE before production keys

Use FetchSandbox MCP to run Descope OTP, magic link, session refresh, and access-key workflows from Cursor or Claude Code — and catch JWT verification bugs before real users.

FetchSandbox EngineeringFetchSandbox Engineering

You can wire Descope OTP or magic-link sign-in in an afternoon. The part that still breaks in production is what your app does with the session JWT after Descope returns it.

That is awkward to test with real keys. You need a project, a mailbox, and you still might miss the handler bug that accepts a forged token.

What to test from the IDE

From Cursor or Claude Code, FetchSandbox MCP can route to the Descope sandbox and run curated workflows without a Descope account:

  • email OTP signup
  • email magic-link sign-in
  • session refresh
  • agentic access-key exchange

The useful part is not "OTP works once." It is whether your protected routes verify the session JWT, whether refresh behaves, and whether scoped access keys stay scoped.

The failure mode worth proving first

The common bug is trusting a decoded JWT instead of verifying it:

const claims = jwt.decode(sessionJwt);
if (claims.role === "admin") allow();

A forged alg: none token can become role=admin if the handler never checks the signature against Descope JWKS.

The fix verifies the session JWT with Descope's SDK or JWKS path and rejects bad signatures, expired sessions, and replayed magic links.

FetchSandbox matches that gap to a known failure pattern — descope_jwt_signature_unverified — and hands back the exact cause, the fix, and a run trace to check your handler against, before you touch production users.

A concrete MCP flow

  1. Ask your coding agent to list Descope workflows in FetchSandbox.
  2. Run magiclink_signin_email and capture the returned sessionJwt.
  3. Hit your protected route with a valid token and a forged unsigned token.
  4. Ask your agent to audit the Descope JWT verification — FetchSandbox routes it to the descope_jwt_signature_unverified pattern and returns the cause + the fix.
  5. Share the receipt URL in your PR as proof your handler rejects the forged token.

That is the whole point: prove the session you trust is actually verified.

Async auth events matter too

Descope integrations also fail on lifecycle, not just the first 200.

Run the sandbox with webhook_retries and watch duplicate delivery events on OTP signup. If your app creates two users or two sessions from the same event ID, you will see it in the run trace before production.

Where to start

  • FetchSandbox MCP setup
  • Descope sandbox docs on FetchSandbox
  • Run workflows from your IDE before wiring server/main.py or your auth middleware

The finish line is not "magic link returned 200." It is "forged session JWT gets rejected, refresh works, and duplicate auth events do not duplicate side effects."