# NeverApply authentication

Service-specific OAuth guide. Reviewed against [WorkOS auth.md v0.6.0](https://github.com/workos/auth.md/blob/b53c9edfbfeea679b617727ebca9ba436bade794/AUTH.md), reference commit `b53c9edfbfeea679b617727ebca9ba436bade794`.
The reference publishes no field-schema version. NeverApply does not implement its agent-registration or user-claimed protocol. Follow the hosted OAuth flow below.

## Discover

- Protected resource metadata: [RFC 9728 document](https://neverapply.co/.well-known/oauth-protected-resource/mcp). Read its `resource` as the canonical audience.
- Authorization server metadata: [OAuth endpoints and capabilities](https://neverapply.co/.well-known/oauth-authorization-server).
- MCP endpoint: `POST https://neverapply.co/mcp` using Streamable HTTP.
- Setup and tool reference: [connector guide](https://neverapply.co/features/mcp#connector-guide).

An unauthenticated MCP POST returns HTTP 401 with `WWW-Authenticate` and its `resource_metadata` URL. No anonymous tools, API keys or personal access tokens are accepted.

## Register a client

Use a public OAuth client with `token_endpoint_auth_method: none` and PKCE S256. Choose either:

- CIMD: use your public HTTPS client metadata document URL as `client_id`. Include a nonempty `client_name`; its `client_id` must match that URL and its `redirect_uris` must include the exact callback.
- DCR: send JSON with `client_name`, `redirect_uris` and `token_endpoint_auth_method: none` to `POST https://neverapply.co/oauth/register`. Retain the returned `client_id`.

Client registration does not create a member or authorize access. Any HTTPS callback with a host is accepted, as are loopback and reverse-domain native callbacks. The consent page names the callback host and warns the user when NeverApply has not verified it.

## Hosted authorization

Open `https://neverapply.co/oauth/authorize` in the user's browser with `response_type=code`, `client_id`, the exact `redirect_uri`, a fresh unpredictable `state`, requested `scope`, `code_challenge_method=S256`, the derived `code_challenge`, and `resource` from discovery. Keep the PKCE verifier private in the client.

The person signs in or selects **Create account**, verifies their email on the hosted page and accepts the requested access. New accounts also accept the published terms; marketing is optional and initially unchecked. Configured ChatGPT clients require an existing account. Never ask for an email verification code in chat, automate consent or treat an email address as proof of account ownership. The user may cancel.

Validate the callback's `state` and `iss` against your saved state and the discovered issuer before using its authorization code.

## Scopes

- `mcp:read`: Read your NeverApply jobs, applications, resumes, and preferences.
- `mcp:write`: Update your profile and saved answers, upload resumes, and prepare documents and interviews.
- `mcp:apply`: Apply to approved jobs, select saved screening answers, and decide held applications.

Request only the access needed, including `mcp:read` for the MCP connection. Scopes do not override tool entitlements or application permission. Applying requires the member's job approval; sending also requires the hosted client grant or an explicit held-application approval.

## Exchange and refresh

Send a form-encoded request to `POST https://neverapply.co/oauth/token` with `grant_type=authorization_code`, `client_id`, `redirect_uri`, `code_verifier`, `code` and the discovered `resource`. There is no client secret for these public clients.

Store returned tokens securely. Refresh at the same endpoint using `grant_type=refresh_token`, `client_id`, `refresh_token` and the same `resource`; replace stored tokens with the returned values. Read `expires_in` from the response. An invalid or revoked refresh grant requires a new hosted authorization flow.

## Use the access token

Send `Authorization: Bearer <access_token>` to the MCP endpoint. Use `server/discover` for MCP 2026-07-28 or `initialize` for a supported legacy version, then `tools/list` before calling tools. For a new member, use `get_profile`, then `upload_resume` (call it again with the returned `cv_upload_id` until `status` is `parsed`) and `update_profile` following their missing-fact guidance; poll `get_matches` when matching is pending. Account creation and verification stay on the website.

## Limits

Configured MCP usage budgets are currently **monitor-only**. Minute and daily budgets are per member and OAuth client; daily budgets reset at midnight in `UTC`. Concurrent-request budgets are per access token. Authentication endpoints have separate throttles.

| Budget | Free | Full access |
| --- | ---: | ---: |
| Requests per minute | 60 | 300 |
| Read calls per day | 50 | 2000 |
| Search rows per day | 500 | 10000 |
| Application sends per day | 3 | 30 |
| Concurrent requests per access token | 2 | 5 |

## Errors

On HTTP 401, inspect discovery and refresh an expired token once; if refresh fails, reconnect through hosted authorization. On `invalid_request`, `invalid_client` or `invalid_grant`, fix the request or restart authorization instead of repeating an unchanged payload. Respect HTTP 429 `Retry-After` and MCP limit errors' reset/retry fields. A tool can return `isError: true` inside HTTP 200. Retry safe reads with bounded backoff on transient failures; never blindly repeat an application action.

## Revocation

The member disconnects the client in [Connected AI clients](https://neverapply.co/app/settings/mcp). This revokes their tokens and pending codes for that client, including refreshed credentials. Do not silently reconnect after revocation; obtain a new user authorization.

WorkOS `service_auth`, anonymous registration, ID-JAG, JWT-bearer assertion exchange, claim-token polling and Security Event Token delivery are not supported. No RFC 7009 revocation endpoint is advertised; use the hosted disconnect control.

## Support

Contact [hello@neverapply.co](mailto:hello@neverapply.co) with the correlation ID when a response provides one. Never include access tokens, refresh tokens, authorization codes or resume content in a support request.