Authentication

Two ways in, both reaching exactly the same catalogue with the same quota. They differ in who holds the credential and what happens when it leaks.

OAuth 2.1 for connectors

Claude, ChatGPT, Cursor and OpenCode sign in with OAuth 2.1. Point the connector at https://port.harborgovcon.com/mcp and it discovers everything else from the 401 response. This gateway is a self-hosted authorization server, so there is no third-party identity provider involved and no separate account to create.

POST https://port.harborgovcon.com/mcp          # no credentials
401 WWW-Authenticate: Bearer error="invalid_token", error_description="…",
  scope="read server:harbor-meta server:usaspending … server:gao-bid-protests",
  resource_metadata="https://port.harborgovcon.com/.well-known/oauth-protected-resource/mcp"

GET  https://port.harborgovcon.com/.well-known/oauth-protected-resource/mcp
GET  https://port.harborgovcon.com/.well-known/oauth-authorization-server
POST https://port.harborgovcon.com/register     # Dynamic Client Registration
GET  https://port.harborgovcon.com/authorize    # sign in and approve
POST https://port.harborgovcon.com/token        # PKCE code exchange

Authorization codes last 60 seconds and are single use. PKCE S256 is required. Access tokens last an hour and refresh tokens rotate; a replayed refresh token revokes the whole authorization. Revoke a connector at any time from Connectors.

API keys for scripts

A static bearer key in the Authorization header. Send it as a header, never in the query string: the MCP authorization specification prohibits access tokens in the URI, and a token in a URL ends up in access logs, in browser history and in any Referer.

Authorization: Bearer YOUR_API_KEY

A missing, malformed, revoked, expired or unknown credential returns 401. Going over your rolling 24 hour quota returns a tool error naming the limit, and nothing is charged as overage.

Create one key per machine rather than one key for everything. A key scoped to a laptop that gets stolen is one revocation; a key shared across four environments is an afternoon. Test keys are available on the same page and never count against plan quota, which is what makes them safe to use while wiring a client up.

Scopes and what they reach

An OAuth authorization is granted a set of scopes. Every source has its own server:<slug> scope, so a connector can be limited to the datasets it actually needs, and the consent screen states exactly what is being requested rather than assuming a generic read.

The authorization server publishes the full scope list at https://port.harborgovcon.com/.well-known/oauth-authorization-server, including one scope per source. A connector granted only server:usaspending cannot call a SAM.gov tool, even though both are on the same endpoint.

Revoking access

Rotating a key issues a replacement and shows it once. The old key keeps working until you finish the rotation, so a rotation does not need a maintenance window.