Skip to main content

Personal token authentication

Create a token, pass it in X-User-Token, and understand that the client inherits exactly that user's permissions.

Where this page ends: a least-privilege account dedicated to AI access with one token under it, and a command that proves the token reaches /mcp.

1. Create a dedicated account​

Resist the urge to reuse root's token. A token has no permissions of its own — it is a credential to act as that user. What an MCP client can touch is decided entirely by whose token it holds.

Under Organization → Users, add a user such as ai-readonly with the Guest or Standard role (not Admin, which bypasses the business-group layer). Then under Teams, put it in a team that has read access to the business groups you want the AI to see. How the two layers combine is in Permission inheritance and RBAC.

2. Generate the token​

Log in as that account, click the avatar at the bottom left → Profile → the Token management tab (route /account/profile/token).

Click Create token and give it a Token name (required). The list has four columns: token name, token, created at and last used — that last one is what lets you find tokens nobody uses any more.

The value is masked; click View to reveal and copy it.

Expected result: one new row, with an empty "last used".

One token per purpose (this one for CI, that one for the AI client) so an incident is traceable and a single token can be revoked without disturbing anyone else.

3. How to send it​

The header name comes from HeaderUserTokenKey under [HTTP.TokenAuth], default X-User-Token:

curl -s -X POST http://127.0.0.1:17000/mcp \
-H 'X-User-Token: YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
"protocolVersion":"2025-06-18","capabilities":{},
"clientInfo":{"name":"curl","version":"1"}}}'

Expected result: serverInfo.name is Nightingale MCP Server. An invalid or deleted token gets 401 with the plain-text body unauthorized.

The same token works on /a2a and on /api/n9e/* — all three entry points share one auth path.

4. Three ways in, one permission model​

Entry pointHow it authenticatesPermissions come from
BrowserUsername/password or SSO, exchanged for a JWTThe user who logged in
HTTP APIX-User-TokenThe token's owner
MCP / A2A clientThe same, or OAuth Authorization: BearerThe same

An MCP tool call is re-dispatched in-process onto Nightingale's own /api/n9e/... routes carrying your token, through the full middleware chain. So the client can do exactly what that person can do in the UI, and nothing more.

5. Revoking​

Delete the row on the same page; it takes effect immediately. Deletion is per token, so a leaked credential is revoked on its own without rotating everyone else's.

Tokens are long-lived until deleted — there is no expiry. Rotate them on a schedule, or at minimum review the "last used" column periodically and delete what nobody uses.

6. Beyond tokens​

Tokens are the least-effort option, but every integration means issuing another credential. If you already run SSO, or want hosted clients like Claude and ChatGPT to "connect by entering an address", OAuth fits better: the user authorizes with their own account and you issue nothing. See OAuth 2.1 and external identity providers.

Next​