Authentication¶
Credentials are resolved immediately before every HTTP request, including stream reconnects.
Bearer authentication¶
Authentication = new EveBearerAuthentication(
cancellationToken => GetAccessTokenAsync(cancellationToken));
HTTP Basic authentication¶
Authentication = new EveBasicAuthentication(
"agent-client",
cancellationToken => GetPasswordAsync(cancellationToken));
Vercel OIDC¶
Authentication = new EveVercelOidcAuthentication(
cancellationToken => GetVercelOidcTokenAsync(cancellationToken));
Vercel OIDC emits both Authorization: Bearer ... and
x-vercel-trusted-oidc-idp-token.
Dynamic headers¶
HeadersProvider = async cancellationToken => new Dictionary<string, string>
{
["x-vercel-protection-bypass"] =
await GetProtectionBypassAsync(cancellationToken),
};
Use RequestHeadersProvider when a dynamic header belongs to one HTTP operation.
The immutable context exposes a stable EveRequestKind, so bootstrap credentials can
be limited to session creation without relying on provider invocation order:
RequestHeadersProvider = (context, cancellationToken) =>
ValueTask.FromResult<IReadOnlyDictionary<string, string>>(
context.Kind == EveRequestKind.CreateSession
? new Dictionary<string, string>
{
["x-session-bootstrap"] = encryptedBootstrapCredential,
}
: new Dictionary<string, string>());
ProtectedHeaderNames = ["x-session-bootstrap"];
Both dynamic providers are resolved before every applicable HTTP call, including
stream reconnects. EveRequestKind may gain members as the upstream client adds
routes, so exhaustive switches should include a default arm.
Header resolution is:
- Static client headers.
- Dynamic client headers.
- Request-aware dynamic headers.
- Authentication headers.
- Generic per-request headers for names that are not protected.
- Explicit protected-header overrides allowed by client policy.
Per-request headers are EveTurnOptions.Headers and the caller-owned request and
content headers of an HttpRequestMessage passed to EveClient.SendRawAsync. They
replace same-named non-protected client-level values case-insensitively.
Every name declared by IEveAuthentication.AuthenticationHeaderNames, every header
emitted by the authentication provider, and every name in
EveClientOptions.ProtectedHeaderNames is protected. Generic per-request values with
those names are ignored.
RequestHeadersProvider remains client-level. A same-named value returned there is
still overridden by the configured IEveAuthentication. Credentials supplied through
that provider should also be listed in ProtectedHeaderNames.
Explicitly forwarding an application identity¶
EveClientOptions options = new("https://agent.example.com")
{
Authentication = new EveVercelOidcAuthentication(GetDeploymentTokenAsync),
AllowedProtectedHeaderOverrides = ["authorization"],
};
EveTurnOptions turnOptions = new()
{
ProtectedHeaderOverrides = new Dictionary<string, string>
{
["authorization"] = audienceRestrictedForwardedIdentityToken,
},
};
EveMessageResponse response = await session.SendAsync(
EveMessageContent.FromText("Summarize my invoices."),
turnOptions,
cancellationToken);
Both conditions are required: the client must allow the header name, and the individual
turn must use ProtectedHeaderOverrides. EveTurnOptions.Headers can never replace
a protected credential.
The override is used for the turn POST and every stream connection and reconnect of that
turn. It does not flow to CancelAsync, ResetAsync, or a separate StreamAsync
attachment. It also does not leak into later turns.
When EveVercelOidcAuthentication is configured, overriding Authorization does not
remove x-vercel-trusted-oidc-idp-token. That deployment credential remains protected
unless its exact name is independently allowlisted and explicitly overridden.
Do not forward a bearer token minted for an unrelated API audience. Prefer a distinct, short-lived token intended for the eve agent, and require the agent to validate that forwarded identity independently. A protected-header override is not itself an authorization boundary.
Raw request overrides¶
using HttpResponseMessage response = await client.SendRawAsync(
request,
new EveRawRequestOptions
{
ProtectedHeaderOverrides = new Dictionary<string, string>
{
["authorization"] = audienceRestrictedForwardedIdentityToken,
},
},
cancellationToken);
Headers placed on HttpContent.Headers are always generic. They cannot replace protected
credentials, even when that name is allowlisted.
Migration¶
Existing consumers keep authentication-authoritative behavior by default. To opt into the upstream eve identity-forwarding use case:
- Identify the exact protected header that must be replaceable.
- Add only that name to
AllowedProtectedHeaderOverrides. - Move the trusted value from
EveTurnOptions.Headersor raw request headers into the dedicatedProtectedHeaderOverridesproperty. - Never copy an inbound request-header collection into the protected override dictionary.
- List credentials supplied outside
IEveAuthenticationinProtectedHeaderNames. - Add integration tests for POST, stream reconnect, later-turn, and cancellation behavior.
Content-specific headers are applied only to requests with content. They are omitted from health, info, stream, and other bodiless requests.
Configure credential-bearing transports not to follow cross-origin redirects.