Authenticate Backend Calls and Use Elicitation
Backend authentication controls the proxy-to-backend boundary. It is independent from the API key or OAuth policy that protects an MCP endpoint.
Use this guide to choose a backend Secret, attach it to a Configuration Plan, and verify a non-destructive Tool call. The main procedure uses a local environment reference so that the credential value does not enter control-plane storage.
See token elicitation with GitHub GraphQL, OAuth URL elicitation with Keycloak, and separate endpoint and backend OAuth flows. Use this guide for the verified configuration and security boundaries.
Prerequisites​
You need:
- the reShapr
1.1.0CLI, authenticated withreshapr login; - an imported Service for a protected test backend;
- a Gateway Group and a proxy instance whose runtime configuration you control;
- a read-only backend operation and its expected successful response;
curlandjq;- the backend credential stored in a secret manager rather than shell history.
Set the non-sensitive inputs:
export SERVICE_ID='<service-id>'
export BACKEND_ENDPOINT='https://api.example.com'
export GATEWAY_GROUP_ID='<gateway-group-id>'
Choose a backend authentication mode​
| Backend | Secret fields | Proxy behavior |
|---|---|---|
| REST or GraphQL with bearer token | token | Sends Authorization: Bearer <token> |
| REST or GraphQL with API key | token and tokenHeader | Sends the token through the named HTTP header |
| REST or GraphQL with Basic authentication | username and password | Sends HTTP Basic credentials |
| gRPC with token | token, optionally tokenHeader | Adds per-call gRPC metadata |
| gRPC with a private CA | certPem | Uses the PEM certificate as a custom TLS trust anchor |
| REST, GraphQL, or gRPC with OAuth Client Credentials | authMethod: OAUTH2_CLIENT_CREDENTIALS and an OAuth client configuration | Obtains and caches a machine-to-machine access token |
| REST, GraphQL, or gRPC with elicitation | useElicitation and a header or OAuth client configuration | Requests a credential for the current MCP session or authenticated user |
In release 1.1.0, username/password is not applied as gRPC Basic authentication, and certPem is not used by the HTTP proxy. The certificate field configures gRPC server trust; it is not a client certificate.
Create a locally resolved Secret​
Secret references explains why the control plane stores a placeholder while the target proxy resolves the credential locally.
Read the backend token into the shell environment without echoing it:
read -r -s -p 'Backend API token: ' BACKEND_API_TOKEN
export BACKEND_API_TOKEN
printf '\n'
Create a backend Secret containing a reference, not the token value. Keep the single quotes so the shell does not expand the placeholder:
export BACKEND_SECRET_ID="$(
reshapr secret create hybrid-backend-token \
--backend \
--token '${env:BACKEND_API_TOKEN}' \
--description 'Resolved by the target proxy' \
--output json \
| jq -er '.id'
)"
For a backend API key carried by a custom header, add --tokenHeader '<header-name>'. For HTTP Basic authentication, replace the token option with:
--username '${env:BACKEND_USERNAME}' \
--password '${env:BACKEND_PASSWORD}'
The proxy resolves each placeholder when preparing a backend call. Release 1.1.0 provides the env scheme; an unknown scheme or missing value fails the call.
Make the value available to the proxy​
Inject the variable through the workload's secret mechanism. For the Docker command in Deploy a Hybrid reShapr Proxy, add this option when creating the container:
--env BACKEND_API_TOKEN
This form passes the value from the current environment without placing it in the docker run arguments. For Kubernetes, map a Secret key to an environment variable in the proxy container instead of committing the value to a manifest.
Check the proxy logs after startup. A missing variable is reported when the first matching backend call tries to resolve it.
Attach the Secret to a Configuration Plan​
Create a Configuration Plan for the protected backend:
export RESHAPR_CONFIG_ID="$(
reshapr config create 'local-backend-auth' \
--serviceId "${SERVICE_ID}" \
--backendEndpoint "${BACKEND_ENDPOINT}" \
--backendSecret "${BACKEND_SECRET_ID}" \
--output json \
| jq -er '.id'
)"
Endpoint access defaults to no authentication in this example. Protect it with an API key or OAuth 2.0 before allowing untrusted clients to reach it.
Create and inspect a named Exposition:
export EXPOSITION_ID="$(
reshapr expo create \
--configuration "${RESHAPR_CONFIG_ID}" \
--gateway-group "${GATEWAY_GROUP_ID}" \
--name backend-auth-check \
--output json \
| jq -er '.id'
)"
reshapr expo get "${EXPOSITION_ID}"
Verify the backend call​
Set the exact endpoint returned by reshapr expo get and select a read-only Tool:
export MCP_URL='https://<gateway-host>/mcp/<organization>/backend-auth-check'
export TOOL_NAME='<read-only-tool-name>'
export TOOL_ARGUMENTS='{}'
Call the Tool:
jq -n \
--arg name "${TOOL_NAME}" \
--argjson arguments "${TOOL_ARGUMENTS}" \
'{jsonrpc:"2.0",id:1,method:"tools/call",params:{name:$name,arguments:$arguments,_meta:{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{name:"reshapr-backend-auth-check",version:"0.2.3"},"io.modelcontextprotocol/clientCapabilities":{}}}}' | \
curl --silent --show-error \
--header 'Content-Type: application/json' \
--header 'Accept: application/json, text/event-stream' \
--header 'MCP-Protocol-Version: 2026-07-28' \
--header 'Mcp-Method: tools/call' \
--header "Mcp-Name: ${TOOL_NAME}" \
--data @- \
"${MCP_URL}" | jq '.result'
An expected backend response confirms that the proxy resolved the reference and applied the credential. A backend 401 usually means the value is missing, expired, or sent through the wrong header.
Rotate a local value​
reShapr does not cache the resolved Secret value between backend calls. Whether a changed value becomes visible without replacing the proxy depends on the configuration source.
Environment variables of an existing Docker container cannot be changed in place. To rotate this example:
- replace
BACKEND_API_TOKENin the secret manager or deployment environment; - recreate the proxy container with the same Gateway ID, labels, and
--env BACKEND_API_TOKENoption; - wait for readiness and registration;
- repeat the read-only Tool call and confirm that the backend accepts the new value;
- revoke the previous backend token.
The Secret stored by the control plane remains ${env:BACKEND_API_TOKEN} throughout this rotation. Kubernetes workloads likewise need a rollout when a Secret is consumed as an environment variable.
Use direct credential elicitation​
Use elicitation when each MCP user must provide a backend credential instead of sharing one provisioned for the proxy. Stateless elicitation with MCP 2026-07-28 requires an OAuth-protected Exposition because reShapr associates the elicited value with the bearer token's iss and sub claims.
Create an elicitation Secret whose --token option names the backend header that will receive the user-provided value:
export ELICITATION_SECRET_ID="$(
reshapr secret create-elicitation user-backend-key \
--token 'X-API-Key' \
--description 'Request one backend API key per MCP user' \
--output json \
| jq -er '.id'
)"
Create an OAuth-protected Configuration Plan as described in Protect an MCP Endpoint with OAuth 2.0 and add:
--backendSecret "${ELICITATION_SECRET_ID}"
Create an Exposition from that plan. Call a Tool with a valid endpoint bearer token before providing the backend credential. The JSON-RPC result has this shape:
{
"result": {
"resultType": "input_required",
"inputRequests": {
"<elicitation-id>": {
"method": "elicitation/create",
"params": {
"mode": "url",
"elicitationId": "<elicitation-id>",
"url": "https://<gateway-host>/elicitation/form?elicitationId=<elicitation-id>"
}
}
},
"requestState": "<opaque-value>"
}
}
Open the supplied URL over a trusted TLS connection, enter the backend credential, and let the MCP client resume the Tool call while preserving the opaque requestState. A successful backend response confirms completion. If the backend later returns 401, the Gateway evicts the elicited value so that the user can provide a replacement.
Clients using a protocol before 2026-07-28 receive a URL_ELICITATION_REQUIRED JSON-RPC error instead. The elicited value is then associated with the MCP session rather than the authenticated iss and sub identity.
Use OAuth elicitation for the backend​
An elicitation Secret can redirect the user through a backend Authorization Server instead of displaying a token form:
reshapr secret create-elicitation backend-oauth \
--oauth2ClientID '<client-id>' \
--oauth2ClientSecret '${env:BACKEND_OAUTH_CLIENT_SECRET}' \
--oauth2AuthorizationEndpoint 'https://idp.example.com/authorize?scope=backend.read' \
--oauth2TokenEndpoint 'https://idp.example.com/token'
Register https://<gateway-host>/elicitation/callback as an allowed redirect base with the backend Authorization Server. The proxy adds the elicitation identifier, client_id, redirect_uri, response_type=code, and stateless state parameters. It resolves the optional client-secret reference locally before exchanging the authorization code.
This flow cannot be validated without a real Authorization Server, a compatible MCP client, and a callback URL reachable through the proxy. Test it in an isolated identity-provider tenant before production use.
Use OAuth Client Credentials​
Use this mode when the proxy must authenticate as a workload rather than as the MCP user. Use OAuth Client Credentials for Backend Calls covers the proxy-local client secret, token request, cache behavior, backend verification, rotation, and recovery procedure.
Roll back​
Delete resources in dependency order:
reshapr expo delete "${EXPOSITION_ID}"
reshapr config delete "${RESHAPR_CONFIG_ID}"
reshapr secret delete "${BACKEND_SECRET_ID}"
Delete any additional elicitation Secrets and their Configuration Plans after removing the Expositions that use them. Revoke test credentials and OAuth clients in their owning systems.
Result​
The proxy authenticates a read-only backend call with a locally resolved credential. You can distinguish that shared runtime credential from a user-specific elicited credential and from the independent policy protecting the MCP endpoint.
Limits​
- Release
1.1.0provides only theenvlocal-reference scheme. It does not integrate directly with a general external secret-provider API. - Client Credentials is a shared machine identity, not user delegation. Refresh tokens returned by an Authorization Server are ignored; the proxy requests a new access token when needed.
- Environment-variable rotation requires the workload platform to make the new value visible. Docker and Kubernetes environment variables require container or pod replacement.
- HTTP Basic credentials are not applied to gRPC calls. Custom CA certificates are applied to gRPC TLS, not HTTP backends, and are not client certificates.
- Elicited credentials are runtime values associated with a session or authenticated user. They are not a substitute for MCP endpoint authentication or authorization.
- Elicitation requires a compatible client. OAuth elicitation additionally requires an Authorization Server and a reachable callback route.
Next step​
- Security Capabilities and Limits compares the controls and their boundaries.
- Deploy a Hybrid reShapr Proxy shows where to inject proxy-local environment variables.
- Test an MCP Endpoint covers stateless and session-based MCP requests.