Skip to main content

What you get

When a workspace connects your MCP server with Send who is chatting turned on, every request from Noxus to your server carries one extra header:
The value is a JSON Web Token (JWT) signed by Noxus for the person who is chatting, or running the flow. Your server verifies the signature with the public keys Noxus publishes, then reads who the person is. You do not call Noxus per request, and you do not share a secret with Noxus. Other headers you configured on the connection, such as your own API key, are still sent as before.

The values you need

Open the connection in Noxus (Workspace control, Connections, the connection, Identity token). It shows every value below, ready to copy. The token also carries scope: the tools it may call. It changes per call, so the connection does not show it.

The claims

sub is the Noxus user id. It is stable for the person. email is the email of their Noxus account. Map either one to a user in your system. scope lists the tools this token may call, separated by spaces. It holds the tools the agent may use on your server (or the one tool an MCP Tool node calls), minus the tools the workspace turned off. When Noxus only lists your tools, for example when an admin presses Refresh tools, scope is empty.

Checks your server must make

Reject the request (HTTP 401) unless every check passes:
  1. The X-Noxus-Identity header is present.
  2. The algorithm is ES256. Fix it in your verify call and accept nothing else.
  3. The key id (kid in the token header) is in the published key set. If it is not, fetch the key set again once, then reject.
  4. The signature verifies.
  5. iss equals the issuer and aud is a workspace you allow. One Noxus deployment signs tokens for all of its workspaces, so the audience check is what makes the token yours.
  6. The token has not expired. Allow about 60 seconds of clock skew.
  7. token_use is mcp_identity.
Then map sub or email to your user, and return 403 if you do not know them. For a tool call (tools/call), also return an error unless the tool name is in scope. Listing tools (tools/list) does not need a scope. A tool the server added after the last Refresh tools is not in scope until an admin presses Refresh tools in Noxus. Protect every MCP route. With the SSE transport that is both the stream (GET /sse) and the message endpoint (POST /messages), because tool calls arrive on the message endpoint. Cache the key set. Fetch it on start, refresh it every few hours, and when a token names a key id you have not seen. Do not fetch it per request.

Example: TypeScript with jose

jwtVerify selects the key by kid, checks the signature, issuer, audience (the workspace) and expiry. The if line checks the token type. Before a tool runs, check that req.scope has its name.

Example: Python with PyJWT

When there is no token

Noxus sends the token only when a signed-in person is behind the call. Calls from a workspace API key, a trigger, or a chat channel without a Noxus user stop inside Noxus and never reach your server. The person sees why in the chat or in the run error.

Do not

  • Trust an email or user header without a signature. Anyone who knows your URL can send one.
  • Skip the audience or scope checks.
  • Forward the token to another service. It names the workspace, not your server.
  • Log the raw token. Log sub, aud and the result instead.