Authentication
Riviera has two authentication questions to answer: how it proves itself to your API when a tool is called, and how an agent proves itself to Riviera. This page covers both, and what your own systems have to support.
Two directions
Riviera to your API. Riviera sends the request to your API for the agent. It does this with a credential you save in Riviera, or with the signed-in user’s own authorization. Agents never see either.
Agent to Riviera. A client connects to your Riviera endpoint with a project access token you can revoke, or through per-user sign-in at your own authorization server.
Riviera to your API
When you import an OpenAPI document, Riviera reads the security scheme each operation declares and asks for the matching setup before it adds the tool.
| Your API uses | What you provide | What Riviera does |
|---|---|---|
| No authentication | Nothing. | Calls the operation as the document declares it. |
| An API key in a header | The key. The header name comes from your document. | Stores the key encrypted and sends it, in that header, only to your API. |
| An HTTP bearer token | A choice: Static service bearer token or Per-user OAuth, and for a static token, the token. | A static token is stored encrypted and sent only to your API. Per-user OAuth is described below. A bearer scheme alone does not tell Riviera which one you mean, so it asks. |
| OAuth client credentials | The token endpoint, confirmed by you, then a client ID and client secret. | Requests an access token from that endpoint with the scopes each operation declares, keeps it in memory until shortly before it expires, and sends it only to your API. |
| OAuth authorization code or OpenID Connect | Your authorization server's setup, under Access. | Runs each call with the signed-in user's own authorization. See per-user OAuth. |
Setting up credentials
- Entered once. A key, token or client secret is encrypted when saved and never shown again. To change it, replace it.
- Bound to its target. A credential belongs to one project, one API address and one kind of authentication, and for a header key, one header name. Riviera won’t send it anywhere else.
- OAuth client credentials. Riviera shows the token endpoint your document declares and asks you to trust it before saving the secret. The default way to send the client secret is HTTP Basic. Choose Request body if your provider needs the secret in the body. Operations that need different token endpoints or scopes need separate credentials.
- Exact scopes. Riviera requests the scopes the operation declares, not every scope the flow offers.
- Tokens and retries. Access tokens are requested when a call needs one and are not kept beyond their expiry. If your API answers 401, Riviera does not repeat the call on its own.
Agents to Riviera
There are two kinds of access to a project’s endpoint, and a tool can be run by only one of them.
| Access | Used for | Limits |
|---|---|---|
| Client access token | Listing tools, and running tools that use a service credential or no authentication. | A token is for one endpoint only and can't authorize another. It is shown once when you create it, and you can revoke it at any time. It can't run a tool that acts as a user. |
| Per-user sign-in | Running tools that act as the signed-in user of your product. | Needs per-user OAuth set up under Access. It can't run a service or no-authentication tool. |
A caller sees the tools its kind of access can run. Neither kind grants permissions in your API: your API still decides what each request may do.
Per-user OAuth
With per-user OAuth, each person signs in through your authorization server, and your API sees who is calling. Riviera is not an identity provider and does not store user accounts, passwords or user refresh tokens. Your authorization server keeps users, consent, client registration, refresh and revocation.
What your authorization server must support
- Authorization code with S256 PKCE, and resource indicators.
- OAuth metadata that clients can discover.
- Token introspection that returns the issuer, the exact audience, the user subject, the client ID, the expiry, a Bearer token type and the granted scopes. Incoming grants can't be of any other type than authorization code or refresh token.
- Token exchange (RFC 8693), so Riviera can swap the incoming token for a separate token for your API. The exchange must keep the user subject and return only the scopes requested.
- Registration of each MCP client you want to use, and of the client Riviera uses for the exchange. Where a client needs a redirect address, register the exact one it gives you.
Check this before you rely on it. Not every authorization server offers introspection and token exchange in this form, and a server without token exchange is not supported. We tested the flow against a self-hosted open-source authorization server and controlled test servers, and with ChatGPT as the client. We have not verified any commercial identity provider. If you aren’t sure yours fits, email hello@riviera.so before you build on it.
How a call runs
- The client signs the user in at your authorization server and receives a token for the Riviera endpoint.
- Riviera checks that the token was issued for that exact endpoint, by your issuer, and is still valid.
- Riviera exchanges it for a token for your API that carries the same user.
- Riviera calls your API with that token and returns the result.
If a tool needs a user and there is none, the call is refused. Riviera never falls back to a service credential, and never forwards the token it received.
Security boundaries
- Agents never see your API credentials. Credentials are encrypted at rest and only sent to the API they were saved for.
- A header that carries a credential can’t be a tool argument. Declare it as a security scheme, so it comes from your saved credential and not from the agent.
- Tokens are tied to one endpoint, and are not reused across endpoints.
- When your API returns an error, the agent is told the call failed and gets its HTTP status. Riviera does not pass on or store the error body.
- Calls are recorded with their tool, version, outcome and duration. Request and response contents are not captured by default.
- Information a client reports about itself during connection, such as its name, is not verified. Riviera shows it only as a hint.
Not supported
- HTTP Basic authentication to your API, and API keys sent in a query string or cookie.
- An operation that accepts several alternative authentication requirements, or one that needs several combined.
- OAuth password and implicit flows.
- Mutual TLS to your API.
- Storing a user’s OAuth tokens in Riviera, or running tools for a user who is not present.
- Authorization servers that can’t offer token introspection and token exchange as described above.
Troubleshooting
| What you see | What to check |
|---|---|
| An imported operation says it needs an API key, a service OAuth credential or authentication to be chosen | Finish the setup for that operation under Import an API. Until then it isn't added. |
| A per-user tool is off after import | It stays off until per-user OAuth is configured for your API’s address and the scopes it needs. Configure it under Access, then turn the tool on. |
| A client is rejected when it connects | Use the exact endpoint address, including its path. A token created for another endpoint won't work. Create a new token if it was revoked. |
| A call is refused for a tool you know exists | The access type can't run that tool, which usually means the client called it by name. Client access tokens run service and no-authentication tools. Per-user sign-in runs per-user tools. Neither lists the other's tools. |
| Sign-in or consent fails at your authorization server | Check the redirect address and client registration, the issuer, the resource the token is requested for, and the scopes. The token must be issued for the exact Riviera endpoint. |
| Your API answers 401 or 403 | The credential may be expired, rotated or too narrow. Replace it, or check the scopes. Riviera doesn't retry a refused call by itself. |
| A call stops before reaching your API | The workspace may be at its monthly tool-call limit, which resets at the start of the next UTC month, or on a plan change. |