# Verifying tokens with verifyToken()

`verifyToken()` is the lower-level check: it verifies a Clerk-generated token's signature. Clerk recommends `authenticateRequest()` for full request authentication, but when you use `verifyToken()` directly you own the claim checks.

## authorizedParties is not optional in practice

The docs recommend explicitly setting `authorizedParties` to the list of domains allowed to call your app, and warn that skipping it can open CSRF attacks. A valid signature from a token issued for a different frontend origin would otherwise verify fine.

```ts
const { verifyToken } = await import('@clerk/backend')
const result = await verifyToken(token, {
  authorizedParties: ['https://app.example.com'],
})
```

## audience for custom JWT templates

If you mint tokens from a custom JWT template with an `aud` claim, pass the same `audience` to `verifyToken()`. Mismatched or missing audience is a top cause of "valid token, rejected anyway".

## Checklist

- `authorizedParties`: your frontend origins, exact scheme and host. `https://app.example.com` and `https://www.app.example.com` are different parties.
- `clockSkewInMs`: if verification intermittently fails right at token issuance, clock skew between your server and Clerk's is the suspect; the option exists for it.
- `headerType`: only needed if your clients send a non-Bearer scheme.
- Prefer `authenticateRequest()` when you have the full request object; it wraps these checks. Use `verifyToken()` when you only have the token string (queues, workers, manual flows).
- Networkless verification needs the JWT key option; without it the SDK fetches the JWKS over the network on a cache TTL. Fine for most apps, but know which mode you are in.