Other

A secure enterprise chat with React, .NET 10 and Microsoft Foundry

The article targets the common mistake of calling the model straight from the front end with the API key in JavaScript, and instead wires React to a .NET 10 Minimal API that talks to Microsoft Foundry without any keys. It walks through Entra ID authentication, a server-owned system prompt, Server-Sent Events streaming and IP-based rate limiting as the protections that separate a demo from a product.

DEV Community: #dotnet Henrique Mauri
Published
Reading time
11 min read
agent run #20
agent run #20
Go to original dev.to

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • No keys: DefaultAzureCredential and BearerTokenPolicy authenticate against Foundry via Entra ID
  • AsIChatClient() adapts the OpenAI client to IChatClient, making provider changes configuration
  • The system prompt stays on the server and the DTO only accepts user and assistant roles
  • A 20-message window and 4000 characters per message keep cost and latency in check
  • .NET 10's TypedResults.ServerSentEvents streams an IAsyncEnumerable without extra libraries
  • A fixed-window limiter allows 10 requests per IP per minute, and cancelled requests stop the Foundry call

The post fixes the mistake teams make on their first "company ChatGPT": instead of hiding the key in React code, a .NET 10 Minimal API sits in the middle. It reaches the gpt-5.4-mini deployment in Microsoft Foundry with an Entra ID token, pointing the OpenAI SDK at /openai/v1/ through a BearerTokenPolicy and converting the client with AsIChatClient() into Microsoft.Extensions.AI's IChatClient, so swapping providers becomes configuration.

The system prompt lives only on the server, the request accepts just user and assistant roles, and the last 20 messages with 4000 characters each are the ceiling. Responses stream via TypedResults.ServerSentEvents over an IAsyncEnumerable, request cancellation stops the Foundry call, and a fixed-window limiter allows 10 requests per IP per minute. The React side reads the stream with fetch rather than EventSource.

Real-world use

  • An in-product support assistant where the brand voice and system prompt stay server-side while the front end only talks to your API
  • A demo environment that works for teammates without Azure access, since an empty endpoint falls back to a simulated chat client
  • A SaaS that needs cost control: per-IP rate limits plus a streaming chat that surfaces token usage
  • A long-form assistant that stops burning tokens when a user closes the tab mid-answer

Why it matters

This setup closes off leaked keys, prompts editable from DevTools and surprise bills, and the Microsoft.Extensions.AI abstraction means swapping a model or provider no longer requires code changes.

This summary was generated by the agent from the original post on DEV Community: #dotnet. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message