Skip to content
Book a demo

Reference

Authentication

Each person signs in with their own Nylon account. The Nylon MCP server is an OAuth 2.1 resource server, and Nylon’s sign-in at https://app.usenylon.com is the authorisation server. Clients discover everything from the first 401, so most users never see a setting.

This page uses the OAuth specifications’ own names for endpoints, fields and documents (such as “authorization server metadata”), and British spelling elsewhere.

  1. Challenge. The client calls POST https://mcp.usenylon.com/mcp without a token and gets 401 with a WWW-Authenticate header that points at the protected resource metadata.

  2. Resource metadata. The client fetches the protected resource metadata, which names https://app.usenylon.com as the authorisation server.

  3. Server metadata. The client fetches https://app.usenylon.com/.well-known/oauth-authorization-server.

  4. Registration. The client sends its redirect URL to POST /oauth/register and gets its pre-assigned client_id.

  5. Sign-in. The client opens /oauth/authorize in the user’s browser with a PKCE S256 challenge. The user signs in to Nylon and chooses Allow access, and Nylon redirects back with a code.

  6. Tokens. The client sends the code, its code_verifier and resource to POST /oauth/token. It gets an access token (1 hour) and a refresh token (30 days).

  7. Calls. The client calls POST /mcp with Authorization: Bearer <access_token>.

A request without a valid token gets a 401 that points at the protected resource metadata (RFC 9728):

HTTP/2 401
www-authenticate: Bearer error="invalid_token", error_description="authentication required", resource_metadata="https://mcp.usenylon.com/.well-known/oauth-protected-resource"
content-type: application/json
{"error":"invalid_token","error_description":"authentication required"}

An expired or invalid token gets the same 401 with a short error_description, such as access token expired. Refresh and retry.

GET https://mcp.usenylon.com/.well-known/oauth-protected-resource (also served at /.well-known/oauth-protected-resource/mcp):

{
"resource": "https://mcp.usenylon.com/mcp",
"authorization_servers": ["https://app.usenylon.com"],
"bearer_methods_supported": ["header"],
"scopes_supported": ["openid", "profile", "email", "offline_access"],
"resource_name": "Nylon MCP",
"resource_documentation": "https://developers.usenylon.com/mcp/"
}

GET https://app.usenylon.com/.well-known/oauth-authorization-server (RFC 8414). For clients that look on the resource’s own origin, the MCP server also serves a copy at https://mcp.usenylon.com/.well-known/oauth-authorization-server.

{
"issuer": "https://app.usenylon.com",
"authorization_endpoint": "https://app.usenylon.com/oauth/authorize",
"token_endpoint": "https://app.usenylon.com/oauth/token",
"registration_endpoint": "https://app.usenylon.com/oauth/register",
"jwks_uri": "https://app.usenylon.com/.well-known/jwks.json",
"userinfo_endpoint": "https://app.usenylon.com/oauth/userinfo",
"scopes_supported": ["openid", "profile", "email", "offline_access"],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none"]
}

Use OAuth authorization server metadata, not OpenID Connect discovery: Nylon doesn’t publish an openid-configuration document. The userinfo_endpoint serves Nylon’s own sign-in integrations and doesn’t accept MCP access tokens.

POST /oauth/register follows RFC 7591, but registration is config-backed. Nylon matches the request’s redirect_uris against the assistants it supports and returns that assistant’s pre-assigned client_id. Nobody types a client ID.

POST /oauth/register HTTP/1.1
Host: app.usenylon.com
Content-Type: application/json
{"client_name":"Claude","redirect_uris":["https://claude.ai/api/mcp/auth_callback"],"grant_types":["authorization_code","refresh_token"]}
HTTP/1.1 201 Created
Cache-Control: no-store
{"client_id":"…","client_id_issued_at":1761004800,"redirect_uris":["…"],"token_endpoint_auth_method":"none","grant_types":["authorization_code","refresh_token"],"response_types":["code"],"client_name":"…","scope":"…"}
  • The response isn’t an echo of your request. client_id, client_name, redirect_uris and scope are the values Nylon holds for that assistant. grant_types and response_types echo your request; if you leave grant_types out, it defaults to ["authorization_code"], so send it.
  • The body must be JSON, 4 kB at most. A larger body gets 413.
  • Redirect URLs must match exactly, with two exceptions. On localhost and 127.0.0.1, Nylon accepts any port when the registered URL has none (RFC 8252); the host itself must still match, so localhost and 127.0.0.1 aren’t interchangeable. IPv6 loopback ([::1]) isn’t supported. The other exception covers the per-connector callbacks that ChatGPT and Copilot Studio generate.
  • A missing or empty redirect_uris returns 400 invalid_redirect_uri. An unknown redirect URL returns 400 invalid_client_metadata; to add a client, see Other MCP clients.
  • Clients are public: there’s no client secret. Nylon ignores any secret a public client sends.

Open the authorization endpoint in the user’s browser:

https://app.usenylon.com/oauth/authorize
?response_type=code
&client_id=<client_id>
&redirect_uri=<registered redirect URL>
&scope=openid%20profile%20email%20offline_access
&state=<random>
&code_challenge=<BASE64URL(SHA256(code_verifier))>
&code_challenge_method=S256
  • Nylon requires PKCE with S256. It rejects plain and requests without a challenge.
  • state is optional, but send it and check it on return. The redirect back carries code and state only; it has no iss parameter (RFC 9207).
  • You may send resource here too. Nylon ignores it at this step and binds the audience at the token endpoint.
  • A user who isn’t signed in signs in first, then returns to the consent screen. The consent step expires after about 10 minutes.
  • The consent screen names the assistant and lists what it can and can’t do. The user chooses Allow access or Cancel.
  • Nylon checks the user’s seat and their organisation’s settings on the server before issuing a code. A user on a Starter seat sees Upgrade to Adviser; if an admin has turned connections off, the user is told to contact them. Either way, the request ends with access_denied, and the user must connect again after the problem is fixed.
  • An unknown client_id or redirect_uri shows an error page and never redirects. Other errors redirect back with error and state (RFC 6749 §4.1.2.1). See Errors.
  • The authorization code is single-use and expires after about 10 minutes.

Send token requests form-encoded:

POST /oauth/token HTTP/1.1
Host: app.usenylon.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=<code>
&redirect_uri=<registered redirect URL>
&client_id=<client_id>
&code_verifier=<code_verifier>
&resource=https%3A%2F%2Fmcp.usenylon.com%2Fmcp
{
"access_token": "eyJ…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "…",
"scope": "openid profile email offline_access"
}

The response has no id_token, even when you request openid.

Send resource=https://mcp.usenylon.com/mcp (RFC 8707) on the token and refresh requests. Nylon binds the access token’s audience to it there, and the MCP server rejects tokens issued for any other audience. A resource that Nylon doesn’t serve returns 400 invalid_target.

Token Lifetime Notes
Access token 1 hour (expires_in: 3600) An RS256-signed JWT. The MCP server checks the signature against the issuer’s JWKS, plus issuer, audience and expiry, on every request. Treat it as opaque.
Refresh token 30 days from issue Issued when the client requests offline_access.
Authorization code About 10 minutes Single use.
POST /oauth/token HTTP/1.1
Host: app.usenylon.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=<refresh_token>&client_id=<client_id>&resource=https%3A%2F%2Fmcp.usenylon.com%2Fmcp
  • Refresh tokens rotate on every use. The response carries a new refresh token with a fresh 30 days. Store it and discard the old one.
  • Nylon detects reuse. If a client presents a refresh token that it has already used, Nylon revokes the whole token family and the user must sign in again. That includes retrying a refresh after a timeout with the same token, so don’t retry a refresh blindly.
  • You can ask for a narrower scope on refresh. It applies to the new access token; the new refresh token keeps the original grant. You can’t widen the scope.
  • Nylon re-checks the user’s seat and their organisation’s settings on every refresh. If access has been removed, the refresh fails with 400 invalid_grant (“MCP access is no longer available for this account”), and Nylon doesn’t consume the refresh token.
  • The token endpoint is rate-limited per IP address. A 429 with temporarily_unavailable is temporary: back off and retry with the same refresh token. It isn’t invalid_grant, so don’t send the user back through sign-in.
Scope Purpose
openid, profile, email Identify the user.
offline_access Get a refresh token, so the user stays connected beyond an hour.

There are no tool-level scopes today: every connected user can call both read-only tools.

Send the access token as a bearer header on every request:

POST /mcp HTTP/1.1
Host: mcp.usenylon.com
Authorization: Bearer <access_token>
Content-Type: application/json
Accept: application/json, text/event-stream

Session handling is in Sessions and limits.