BrandGhost
Authenticate Vercel Eve Calls from ASP.NET Core: Service Access and User Authorization

Authenticate Vercel Eve Calls from ASP.NET Core: Service Access and User Authorization

Vercel Eve authentication involves more than adding a credential to an HTTP request. Your ASP.NET Core application needs to establish who is calling, decide what that caller may access, and then contact an agent using credentials intended for that boundary. Those decisions should remain separate even when the user sees only one chat screen.

Consider a fictional equipment-maintenance assistant. Alice may read the inspection note for one pump, while another team owns a different pump. The application can have permission to contact the agent without Alice having permission to read every inspection. A successful agent request must not silently collapse those two kinds of authority.

I maintain NexusLabs.Eve, the independent .NET client used in these examples. It is not an official Vercel SDK.

The examples target .NET 10 and C# 14 with nullable enabled, using NexusLabs.Eve 0.1.0-alpha-0014, public source tag v0.1.0-alpha.14, and Eve server 0.63.0 (package, compatibility reference). They are source-reviewed illustrations, not newly compiled or executed demonstrations. No sample issues a token or exposes an anonymous production endpoint.

Vercel Eve Authentication Has Several Trust Boundaries

Start by drawing the request path: browser to ASP.NET Core, ASP.NET Core to agent, and agent to any downstream service. Each arrow has a different receiver. Each receiver needs its own reason to trust the request.

ASP.NET Core's JWT bearer handler validates a token and extracts identity claims, while authorization decides whether that identity has the necessary permission, as Microsoft's ASP.NET Core 10.0 JWT bearer guidance explains. Authentication is not proof that the caller owns the equipment identifier they submitted.

The distinction becomes especially important with a server-side agent adapter. The application might use a service credential for every outbound request. That credential represents the application, not automatically the person behind its current HTTP request. Your backend must therefore authorize the requested resource before spending service authority on the caller's behalf.

For the inbound fundamentals, the existing guide to authentication and authorization in ASP.NET Core Web API explains JWT validation and policies without introducing an agent-specific trust model.

In Eve 0.63.0, route authentication gates inbound agent HTTP routes, while tool and connection authentication governs access to external services later in execution (pinned authentication guide). Passing one gate is not evidence that every downstream gate has been satisfied.

A deployment credential answers a narrower question: may this application reach this deployment or its configured route policy? It does not answer whether Alice can read a particular inspection. Likewise, possession of a downstream OAuth grant does not establish that an arbitrary inbound caller owns the current conversation. Keep a separate policy decision at each boundary.

Authorize the Resource Before Calling the Agent

For Vercel Eve authentication, a trusted user identity is the beginning of resource authorization, not the end. Load the equipment record through your backend and evaluate permission using trusted ownership data. Do not accept a request body containing both an equipment identifier and its supposed owner as authoritative.

Microsoft documents resource-based authorization because declarative authorization alone cannot evaluate a resource that has not yet been loaded; the application must perform the resource-specific decision (resource authorization guidance). A general "signed-in user" policy can protect entry, but it cannot substitute for checking the selected record.

This complete EquipmentReadAuthorization.cs file illustrates the policy calculation with a deliberately synthetic record. It needs the ASP.NET Core shared framework. Its claim convention is an example, not a declaration that every identity provider emits sub in this form.

using System.Security.Claims;
using System.Threading.Tasks;

using Microsoft.AspNetCore.Authorization;

namespace EquipmentDemo;

public sealed record EquipmentRecord(string Id, string OwnerSubject);

public sealed class ReadEquipmentRequirement : IAuthorizationRequirement
{
}

public sealed class ReadEquipmentHandler
    : AuthorizationHandler<ReadEquipmentRequirement, EquipmentRecord>
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        ReadEquipmentRequirement requirement,
        EquipmentRecord resource)
    {
        string? subject = context.User.FindFirstValue("sub");

        if (context.User.Identity?.IsAuthenticated == true
            && subject is not null
            && string.Equals(subject, resource.OwnerSubject,
                System.StringComparison.Ordinal))
        {
            context.Succeed(requirement);
        }

        return Task.CompletedTask;
    }
}

The handler does not fetch data or invent identities. Its input must be a record loaded from a trusted repository after the inbound authentication middleware has validated the caller. Register it with your authorization services, invoke resource authorization, and require success before the agent adapter runs. Real ownership policy may include tenant membership and delegated permissions rather than this simple equality.

The important boundary is outside the model. An instruction saying "only answer questions about the user's pump" is useful behavior guidance, but it is not a permission check. A typed backend operation should select authorized records before returning data to a tool. The model should not retrieve everything and then decide which rows to hide.

Apply the same discipline to session identifiers. Store the association between your authenticated subject, tenant, equipment, and agent session on the server. Before continuation or another attachment, load that association and reauthorize it. A session identifier supplied by the browser is a lookup key, not an access grant.

Vercel Eve Authentication: Keep Credential Acquisition Narrow

The pinned C# client's EveBearerAuthentication accepts a callback returning ValueTask<string>, allowing the application to supply a credential before each request (v0.1.0-alpha.14 source). The SDK transports the credential; your identity infrastructure determines how it is acquired.

Avoid making the callback a general-purpose "give me any token" function. A narrow provider should represent one approved downstream audience and one credential purpose. It should not accept a user-controlled URL or a copied inbound header collection.

This complete EveServiceCredentialProvider.cs file defines that boundary and a fail-closed local demonstration implementation. The implementation is explicitly unusable in production: it never returns a credential. It makes missing identity integration visible instead of supplying a pretend JWT.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace EquipmentDemo;

public abstract class EveServiceCredentialProvider
{
    public abstract ValueTask<string> GetAgentServiceTokenAsync(
        CancellationToken cancellationToken);
}

public sealed class UnconfiguredDemoCredentialProvider
    : EveServiceCredentialProvider
{
    public override ValueTask<string> GetAgentServiceTokenAsync(
        CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();

        throw new InvalidOperationException(
            "Local illustration only: no agent credential provider is configured.");
    }
}

A production implementation belongs in your server's identity integration and should acquire a token intended for the configured agent receiver. Microsoft's guidance distinguishes application tokens from delegated user tokens and recommends standardized OAuth or OIDC acquisition rather than inventing access tokens (token guidance).

Service credentials simplify the adapter's transport identity, but require your backend to preserve user authorization independently. Delegated credentials can express a user's downstream authority, but require an acquisition flow and receiver policy appropriate to that audience. Neither choice eliminates equipment ownership checks.

The abstract boundary intentionally does not include token issuance, secret storage, refresh implementation, or a browser login flow. Those concerns depend on the identity system. Omitting a homemade issuer is safer than giving readers a short, misleading recipe that appears to solve all four.

Use Caller-Owned Transport and Per-Request Credentials

NexusLabs.Eve v0.1.0-alpha.14 uses a caller-managed HttpClient or HttpMessageInvoker, and its getting-started guide recommends IHttpClientFactory for dependency-injected applications (pinned transport guide). Transport ownership remains with your application.

This complete EquipmentAgentClientFactory.cs file builds a client around that caller-owned transport and the previous provider. It requires the pinned NexusLabs.Eve package. The fixed example.com address is illustrative and is not an operational agent.

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

using NexusLabs.Eve;

namespace EquipmentDemo;

public sealed class EquipmentAgentClientFactory(
    EveServiceCredentialProvider credentials)
{
    public EveClient Create(HttpClient callerOwnedTransport)
    {
        ArgumentNullException.ThrowIfNull(callerOwnedTransport);

        return new EveClient(
            callerOwnedTransport,
            new EveClientOptions("https://agent.example.com")
            {
                Authentication = new EveBearerAuthentication(
                    GetRequiredTokenAsync),
            });
    }

    private async ValueTask<string> GetRequiredTokenAsync(
        CancellationToken cancellationToken)
    {
        string token = await credentials.GetAgentServiceTokenAsync(
            cancellationToken);

        if (string.IsNullOrWhiteSpace(token))
        {
            throw new InvalidOperationException(
                "The configured agent credential provider returned no token.");
        }

        return token;
    }
}

There are no implicit inbound header reads. The factory cannot turn a caller's arbitrary Authorization value into trusted service access. Using the demonstration provider causes a visible configuration failure when a credential is requested; it does not produce a success-shaped anonymous fallback.

The pinned client's authentication callback runs before every HTTP request, including stream reconnects (authentication reference). A callback invocation is an opportunity to obtain a valid credential, not a guarantee that the credential has been refreshed or that its scope is correct.

Your provider can use a secure server-side cache and refresh according to the identity system's rules. Preserve cancellation and propagate acquisition errors. Do not let concurrent requests overwrite a shared "current user token" field: transport reuse and per-user credential state are different lifetimes.

For the mechanics of named transports and dependency injection, see IHttpClientFactory in .NET. Keep the caller-owned transport alive for the entire response consumption, as the pinned getting-started reference requires.

Redirect Policy Is Part of Credential Policy

A credential should be sent only to the receiver for which the application acquired it. Configure the credential-bearing transport with automatic redirects disabled. Resolve an unexpected redirect as a deployment or routing issue instead of quietly following it to an unreviewed destination.

Microsoft documents that HttpClientHandler.AllowAutoRedirect defaults to true, clears Authorization during automatic redirects, and does not clear other headers (redirect behavior). Consequently, "the bearer header is stripped" is not a sufficient policy for a request that also carries a credential in a custom header.

Set AllowAutoRedirect = false on the handler configured for the named agent client. This conservative choice sacrifices automatic handling of legitimate redirects, but makes the intended credential destination explicit. Configure the canonical agent endpoint server-side and do not allow a chat request to choose its own host.

The HttpClient guide for .NET developers provides broader transport context. Here, the security requirement is narrower: a handler must not silently extend your trust boundary.

Agent Route Authentication Is Not Tool Connection Authentication

For a Vercel-to-Vercel deployment path, the pinned client's EveVercelOidcAuthentication emits both an authorization credential and x-vercel-trusted-oidc-idp-token, according to its authentication reference). Merely running ASP.NET Core does not establish that your host can acquire an appropriate Vercel OIDC token.

On the receiving agent, the following complete agent/channels/eve.ts file illustrates a service-only route policy using the pinned Eve 0.63.0 eveChannel and vercelOidc helpers (route policy guide).

import { eveChannel } from "eve/channels/eve";
import { vercelOidc } from "eve/channels/auth";

export default eveChannel({
  auth: [vercelOidc()],
});

This is a channel file inside an already configured Eve project, not a standalone server or an end-user authorization implementation. It deliberately includes neither anonymous acceptance nor a synthetic local principal. Deployment identity configuration still determines which callers are accepted.

Eve 0.63.0 protects session creation, continuation, control, and streaming routes through route auth, while its default channel health route is public (protected route groups). Therefore a successful health probe does not prove that your service can start an authenticated session.

The same pinned guide explicitly states that route auth does not enforce session ownership and that user-scoped connection authentication needs an active user principal (ownership and connection boundaries). A service principal is not automatically suitable for a tool that needs the person's OAuth grant.

For our maintenance assistant, the backend should still authorize the requested equipment before exposing its inspection data. If a tool contacts an external system, that system must enforce its own resource permissions. Model instructions can describe the policy, but the typed backend must enforce it.

Forwarded Identity Must Be Explicit and Audience-Restricted

Vercel Eve authentication sometimes needs both deployment access and a separately verified application identity. Do not implement that by copying the browser's authorization header. A token accepted by your Web API may be intended only for that API.

Microsoft's ASP.NET Core 10.0 JWT guidance requires validation of signature, issuer, audience, and expiration by the receiving API (validation requirements). Acquire an audience-restricted downstream token through trusted server-side identity infrastructure and require the agent receiver to validate it independently.

At client tag v0.1.0-alpha.14, overriding a protected header requires both AllowedProtectedHeaderOverrides on client options and ProtectedHeaderOverrides on the individual turn; generic EveTurnOptions.Headers cannot replace protected credentials (override contract). Keep the allowlist limited to the exact header your reviewed identity design requires.

The dedicated override applies to that turn's POST and stream reconnects, not later turns, cancellation, reset, or a separately attached stream, at the pinned client version (override lifetime). An authorization override with Vercel OIDC does not automatically remove the separate protected deployment header, according to the same pinned reference).

This explains why credential lifetime and operation lifetime need deliberate review. The normal provider is resolved again on reconnect, while a per-turn override is the turn's supplied identity value (pinned authentication contract). Do not assume a newly acquired service credential refreshes an expiring forwarded user credential. Handle expiry by your receiver's policy, without falling back to broader service authority.

Check the Boundary Without Logging Credentials

Review the integration as a permission system, not just a successful request. An unauthenticated caller must not reach protected application operations. An authenticated caller must not read another owner's equipment or resume their session. An unavailable credential provider must fail visibly before privileged work starts.

Use a recording handler to inspect synthetic requests and verify the intended destination, header protection, and reconnect behavior. The existing Mock HttpClient C# guide explains that transport seam. Use dummy marker strings in tests, never captured production credentials.

Separately exercise middleware and resource authorization through the real application pipeline. Testing ASP.NET Core Web API covers the integration-test surface. A callback unit test cannot prove that the endpoint actually invokes authorization before calling the adapter.

Record operation type, outcome, and safe correlation identifiers rather than complete headers. Treat logs as another data boundary. A denial can be observable without exposing the credential that produced it. None of these checks is claimed to have been executed for the illustrative files above.

Frequently Asked Questions

Does Vercel Eve authentication replace ASP.NET Core authentication?

No. Your application still establishes the inbound identity and applies its own resource policy. Agent route authentication is a separate receiver's decision. Keeping both checks prevents a service credential from becoming an accidental authorization grant for every browser caller.

Can I forward the browser's Authorization header?

Not as trusted identity merely because it exists. Validate inbound identity, authorize the operation, and acquire a downstream credential for the intended audience. Header forwarding is not token exchange and does not establish that the agent should trust that token.

Does a service token prove the user owns the session?

No. Maintain server-side ownership associations and check them for each requested operation. An authenticated transport identifies a caller at one boundary; a conversation identifier still needs application-level access policy.

Why use a callback instead of storing one token at startup?

The callback gives credential infrastructure a chance to return a valid credential for each operation. It does not create refresh logic by itself. A static token is simpler but can outlive its validity during a long-running conversation.

Does route authentication authorize an agent's external tools?

No. The incoming caller and the external service have different trust boundaries. A read-only equipment tool should still enforce ownership in its typed backend, and an external connection needs credentials appropriate to its receiver.

Is a local synthetic identity a production authentication strategy?

No. A synthetic identity is useful only in an explicitly isolated demonstration. These examples expose no anonymous endpoint and supply no fake token. The demonstration provider deliberately throws so missing production integration cannot look like successful authentication.

Keep the User Decision Separate from Service Access

The useful mental model for Vercel Eve authentication is a sequence of explicit decisions: establish inbound identity, authorize the requested resource, acquire an appropriate downstream credential, and let the receiving service verify it. Reconnects and redirects must preserve that design rather than silently changing who acts or where credentials travel.

For the maintenance assistant, the successful outcome is not simply an agent response. It is a response produced through the authority the caller actually has. Keeping permission checks in typed backend code makes that boundary understandable even when conversation and model behavior vary.

Vercel Eve Tutorial for C# Developers: Build an ASP.NET Core Agent Client

Follow this Vercel Eve tutorial to connect ASP.NET Core to a pinned agent, manage transport ownership, and read equipment summaries with explicit failures.

Vercel Eve Sessions and Streaming in C#: Recover a Disconnected Client

Learn how Vercel Eve sessions recover disconnected C# clients with persisted cursors, bounded streaming, replay boundaries, and explicit cancellation choices.

Vercel Eve Explained: Durable AI Agents and C# Integration

Understand Vercel Eve's durable agent runtime, filesystem-first design, replay boundaries, and how C# applications connect through a version-pinned HTTP client.

An error has occurred. This application may no longer respond until reloaded. Reload