@@ -28,63 +28,134 @@ Pass your authentication token via the `headers` prop:
2828
2929## Backend Setup
3030
31- Configure JWT bearer authentication in your AG-UI server:
31+ Configure authentication in your AG-UI server:
3232
33- ``` csharp title="Program.cs"
34- using Microsoft .Agents .AI ;
35- using Microsoft .Agents .AI .Hosting .AGUI .AspNetCore ;
36- using Microsoft .AspNetCore .Authentication .JwtBearer ;
37- using OpenAI ;
33+ <Tabs groupId = " language" items = { [' .NET' , ' Python' ]} >
34+ <Tab value = " .NET" >
35+ ``` csharp title="Program.cs"
36+ using Microsoft .Agents .AI ;
37+ using Microsoft .Agents .AI .Hosting .AGUI .AspNetCore ;
38+ using Microsoft .AspNetCore .Authentication .JwtBearer ;
39+ using OpenAI ;
3840
39- var builder = WebApplication .CreateBuilder (args );
41+ var builder = WebApplication .CreateBuilder (args );
4042
41- // Configure JWT authentication
42- builder .Services .AddAuthentication (JwtBearerDefaults .AuthenticationScheme )
43- .AddJwtBearer (options =>
44- {
45- options .Authority = builder .Configuration [" JwtAuthority" ];
46- options .Audience = builder .Configuration [" JwtAudience" ];
47- options .TokenValidationParameters = new Microsoft .IdentityModel .Tokens .TokenValidationParameters
43+ // Configure JWT authentication
44+ builder .Services .AddAuthentication (JwtBearerDefaults .AuthenticationScheme )
45+ .AddJwtBearer (options =>
4846 {
49- ValidateIssuer = true ,
50- ValidateAudience = true ,
51- ValidateLifetime = true ,
52- ValidateIssuerSigningKey = true
53- };
54- });
55-
56- builder .Services .AddAuthorization ();
57-
58- var app = builder .Build ();
59-
60- app .UseAuthentication ();
61- app .UseAuthorization ();
62-
63- // Create and map your agent
64- string githubToken = builder .Configuration [" GitHubToken" ]! ;
65- var openAI = new OpenAIClient (
66- new System .ClientModel .ApiKeyCredential (githubToken ),
67- new OpenAIClientOptions { Endpoint = new Uri (" https://models.inference.ai.azure.com" ) }
68- );
69- var agent = openAI .GetChatClient (" gpt-4o-mini" )
70- .CreateAIAgent (name : " AGUIAssistant" , instructions : " You are a helpful assistant." );
71-
72- app .MapAGUI (" /" , agent ).RequireAuthorization ();
73-
74- await app .RunAsync ();
75- ```
47+ options .Authority = builder .Configuration [" JwtAuthority" ];
48+ options .Audience = builder .Configuration [" JwtAudience" ];
49+ options .TokenValidationParameters = new Microsoft .IdentityModel .Tokens .TokenValidationParameters
50+ {
51+ ValidateIssuer = true ,
52+ ValidateAudience = true ,
53+ ValidateLifetime = true ,
54+ ValidateIssuerSigningKey = true
55+ };
56+ });
57+
58+ builder .Services .AddAuthorization ();
59+
60+ var app = builder .Build ();
61+
62+ app .UseAuthentication ();
63+ app .UseAuthorization ();
64+
65+ // Create and map your agent
66+ string githubToken = builder .Configuration [" GitHubToken" ]! ;
67+ var openAI = new OpenAIClient (
68+ new System .ClientModel .ApiKeyCredential (githubToken ),
69+ new OpenAIClientOptions { Endpoint = new Uri (" https://models.inference.ai.azure.com" ) }
70+ );
71+ var agent = openAI .GetChatClient (" gpt-4o-mini" )
72+ .CreateAIAgent (name : " AGUIAssistant" , instructions : " You are a helpful assistant." );
73+
74+ app .MapAGUI (" /" , agent ).RequireAuthorization ();
75+
76+ await app .RunAsync ();
77+ ```
78+ </Tab >
79+ <Tab value = " Python" >
80+ ``` python title="agent/src/main.py (excerpt)"
81+ from __future__ import annotations
82+ import os
83+ from fastapi import FastAPI, HTTPException, Request, status
84+ from fastapi.middleware.cors import CORSMiddleware
85+ from agent_framework import ChatClientProtocol
86+ from agent_framework.azure import AzureOpenAIChatClient
87+ from agent_framework.openai import OpenAIChatClient
88+ from azure.identity import DefaultAzureCredential
89+ from agent_framework.ag_ui import add_agent_framework_fastapi_endpoint
90+ from agent import create_agent
91+
92+ app = FastAPI(title = " CopilotKit + Microsoft Agent Framework (Python)" )
93+ app.add_middleware(
94+ CORSMiddleware,
95+ allow_origins = [" *" ],
96+ allow_credentials = True ,
97+ allow_methods = [" *" ],
98+ allow_headers = [" *" ],
99+ )
100+
101+ REQUIRED_BEARER_TOKEN = os.getenv(" AUTH_BEARER_TOKEN" )
102+
103+ @app.middleware (" http" )
104+ async def auth_middleware (request : Request, call_next ):
105+ # Protect the AG-UI endpoint if a token is configured
106+ if REQUIRED_BEARER_TOKEN and request.url.path == " /" :
107+ auth_header = request.headers.get(" Authorization" , " " )
108+ if not auth_header.startswith(" Bearer " ):
109+ raise HTTPException(status_code = status.HTTP_401_UNAUTHORIZED , detail = " Missing bearer token" )
110+ token = auth_header.split(" " , 1 )[1 ].strip()
111+ if token != REQUIRED_BEARER_TOKEN :
112+ raise HTTPException(status_code = status.HTTP_401_UNAUTHORIZED , detail = " Invalid token" )
113+ return await call_next(request)
114+
115+ # Build a chat client (same pattern as the Quickstart)
116+ def _build_chat_client () -> ChatClientProtocol:
117+ if bool (os.getenv(" AZURE_OPENAI_ENDPOINT" )):
118+ deployment_name = os.getenv(" AZURE_OPENAI_CHAT_DEPLOYMENT_NAME" , " gpt-4o-mini" )
119+ return AzureOpenAIChatClient(
120+ credential = DefaultAzureCredential(),
121+ deployment_name = deployment_name,
122+ endpoint = os.getenv(" AZURE_OPENAI_ENDPOINT" ),
123+ )
124+ if bool (os.getenv(" OPENAI_API_KEY" )):
125+ return OpenAIChatClient(
126+ model_id = os.getenv(" OPENAI_CHAT_MODEL_ID" , " gpt-4o-mini" ),
127+ api_key = os.getenv(" OPENAI_API_KEY" ),
128+ )
129+ raise RuntimeError (" Set AZURE_OPENAI_* or OPENAI_API_KEY in agent/.env" )
130+
131+ chat_client = _build_chat_client()
132+ my_agent = create_agent(chat_client)
133+ add_agent_framework_fastapi_endpoint(app = app, agent = my_agent, path = " /" )
134+ ```
135+ </Tab >
136+ </Tabs >
76137
77138### Configuration
78139
79- Add JWT settings to your ` appsettings.json ` :
140+ Add settings to your server configuration :
80141
81- ``` json title="appsettings.json"
82- {
83- "JwtAuthority" : " https://login.microsoftonline.com/{your-tenant-id}/v2.0" ,
84- "JwtAudience" : " api://{your-client-id}" ,
85- "GitHubToken" : " your-github-token-here"
86- }
87- ```
142+ <Tabs groupId = " language" items = { [' .NET' , ' Python' ]} >
143+ <Tab value = " .NET" >
144+ ``` json title="appsettings.json"
145+ {
146+ "JwtAuthority" : " https://login.microsoftonline.com/{your-tenant-id}/v2.0" ,
147+ "JwtAudience" : " api://{your-client-id}" ,
148+ "GitHubToken" : " your-github-token-here"
149+ }
150+ ```
151+ </Tab >
152+ <Tab value = " Python" >
153+ ``` bash title="agent/.env"
154+ # Simple shared-secret example for demo purposes
155+ AUTH_BEARER_TOKEN=super-secret-demo-token
156+ ```
157+ </Tab >
158+ </Tabs >
88159
89160### CORS (if needed)
90161
@@ -116,6 +187,13 @@ app.UseAuthorization();
116187- Implement role-based access control in your agents
117188- Use HTTPS in production
118189
190+ <Callout type = " warning" title = " Avoid shared-secret bearer tokens in production" >
191+ Examples that validate a bearer token against a single shared secret (e.g., an environment variable) are for local demos only.
192+ For production, use proper authentication:
193+ - .NET: Validate JWTs with ` Microsoft.AspNetCore.Authentication.JwtBearer ` (as shown above), backed by your IdP (e.g., Entra ID).
194+ - Python: Use OAuth 2.0 / OpenID Connect JWT validation or an API gateway that validates tokens before requests reach your AG‑UI server.
195+ </Callout >
196+
119197## Troubleshooting
120198
121199** Token not reaching server** : Verify the ` Authorization ` header is set in ` <CopilotKit> ` and forwarded through any proxies.
0 commit comments