Authenticate Backend Calls and Use Elicitation
Backend authentication controls the Gateway-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.
Prerequisites​
You need:
- the reShapr
0.2.3CLI, authenticated withreshapr login; - an imported Service for a protected test backend;
- a Gateway Group and a Gateway 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 | Gateway 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 elicitation | useElicitation and a header or OAuth client configuration | Requests a credential for the current MCP session or authenticated user |
In release 0.2.3, 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​
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 Gateway' \
--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 Gateway resolves each placeholder when preparing a backend call. Release 0.2.3 provides the env scheme; an unknown scheme or missing value fails the call.
Make the value available to the Gateway​
Inject the variable through the workload's secret mechanism. For the Docker command in Deploy a Hybrid Gateway, 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 Gateway container instead of committing the value to a manifest.
Check the Gateway 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 Gateway 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 Gateway 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 Gateway 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 Gateway. 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 Gateway 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 Gateway. Test it in an isolated identity-provider tenant before production use.
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 Gateway 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
0.2.3provides only theenvlocal-reference scheme. It does not integrate directly with a general external secret-provider API. - 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 Gateway shows where to inject Gateway-local environment variables.
- Test an MCP Endpoint covers stateless and session-based MCP requests.