A React + TypeScript Single Page Application (SPA) that connects directly to Azure AI Foundry Agents API using Entra ID authentication. No backend required.
Live Demo: https://mdspinali.github.io/Azure-AI-Foundry-Agent-Service-Entra-Test-Chat/
(Replace with your GitHub Pages URL once deployed)
┌─────────────────────┐
│ React SPA │
│ (Browser) │
│ │
│ ┌──────────────┐ │
│ │ MSAL.js │ │──┐
│ │ (Entra Auth) │ │ │
│ └──────────────┘ │ │
│ │ │ 1. Get Entra Token
│ ┌──────────────┐ │ │ (audience: https://ai.azure.com)
│ │ OpenAI SDK │ │ │
│ │ (for Azure) │ │◄─┘
│ └──────────────┘ │
└─────────┬───────────┘
│
│ 2. HTTPS + Bearer Token
│
▼
┌─────────┐
│ APIM │ (Optional)
│ Gateway │
└────┬────┘
│
│ 3. Proxy to Azure AI Foundry
│
▼
┌─────────────────────┐
│ Azure AI Foundry │
│ Agents API │
│ │
│ - /threads │
│ - /runs │
│ - /messages │
└─────────────────────┘
Note: APIM Gateway is optional. Without it, the SPA
connects directly to Azure AI Foundry.
- ConfigProvider: Manages Azure endpoint, Entra client ID, and settings with localStorage persistence
- AuthProvider: Handles Entra ID authentication using MSAL redirect flow
- ChatProvider: Integrates OpenAI SDK configured for Azure AI Foundry
- ChatInterface: Clean, modern chat UI
- No Backend Required - Direct browser-to-Azure calls
- Entra ID Authentication - Token-based auth, no API keys exposed
- Configurable UI - All settings adjustable and persisted
- Assistants API - Full support for Azure AI Foundry Agents
- Persistent Config - Settings survive page refresh
- Clean UI - Minimal, modern interface
You must use an Azure AI Foundry project (not hub-based projects):
- Create an AI Foundry project in Azure Portal
- Deploy or create an Agent
- Note your Project Endpoint - It follows this format:
Example:
https://YOUR-RESOURCE-NAME.services.ai.azure.com/api/projects/YOUR-PROJECT-NAMEhttps://my-ai-resource.services.ai.azure.com/api/projects/my-project - Note your Agent ID (format:
asst_...)
Create an app registration in Azure Portal:
- Go to Azure Portal → Entra ID → App registrations → New registration
- Name:
Azure AI Chat SPA(or your choice) - Supported account types: Single tenant (or as needed)
- Redirect URI:
- Platform: Single-page application (SPA)
- URI:
http://localhost:5173(for development) and your production URL. IMPORTANT If you plan to use this test page you MUST include thehttps://mdspinali.github.io/Azure-AI-Foundry-Agent-Service-Entra-Test-Chatas a redirect URI
- Click Register
- Copy and save the following from the Overview page:
- Application (client) ID - You will need this for configuration
- Directory (tenant) ID - You will need this for configuration
- Go to API permissions tab
- Click Add a permission → APIs my organization uses
- Search for: Azure Machine Learning Services
- Select Delegated permissions
- Check: user_impersonation
- Click Add permissions
- Click Grant admin consent (if you have admin rights)
Important: The scope
https://ai.azure.com/.defaultrequires the "Azure Machine Learning Services" API permission.
- Authentication tab → Single-page application section
- Ensure redirect URIs are listed
- Implicit grant and hybrid flows: Leave unchecked (not needed for MSAL.js 2.x)
- Go to your AI Foundry Project in Azure Portal
- Access Control (IAM) → Add role assignment
- Role: Azure AI Developer or Azure AI User
- Assign to: Your user account or group
- Save
git clone <your-repo>
cd entra_test_client
npm installStart the dev server:
npm run devOpen http://localhost:5173 (or the port shown in terminal) and click the Settings button (gear icon in top-right).
Enter your configuration:
- Azure AI Foundry Endpoint: Your project endpoint from Azure Portal
- Format:
https://YOUR-RESOURCE.services.ai.azure.com/api/projects/YOUR-PROJECT - Example:
https://my-ai-resource.services.ai.azure.com/api/projects/my-project
- Format:
- Entra ID Client ID: The Application (client) ID you copied earlier
- Tenant ID: The Directory (tenant) ID you copied earlier
- Scopes:
https://ai.azure.com/.default(leave as default) - Agent ID: Your AI agent ID from Azure AI Foundry (format:
asst_abc123)
Click Save - your settings will be stored in browser localStorage.
- Open the application in your browser
- Click the Settings button (gear icon in top-right corner)
- Enter all required configuration values (see Configuration section above)
- Click Save
- Click Sign In
- You will be redirected to Microsoft login page
- Sign in with your Azure account
- After successful authentication, you'll return to the chat interface
- Once signed in, you'll see the chat interface
- Type your message in the input box at the bottom
- Press Enter or click Send
- The agent will process your message and respond
- Your conversation history is maintained in the current thread
- Click the Settings button anytime to modify configuration
- Your settings persist across browser sessions (stored in localStorage)
- Click Reset to Defaults to clear all settings
- After changing settings, you may need to sign in again
Click the Sign Out button in the top-right corner to end your session.
| Setting | Description | Example |
|---|---|---|
| Azure Endpoint | AI Foundry project API endpoint (full path including /api/projects/) | https://resource.services.ai.azure.com/api/projects/project-name |
| Client ID | Entra app registration Application (client) ID | 12345678-1234-1234-1234-123456789abc |
| Tenant ID | Azure AD Directory (tenant) ID | 87654321-4321-4321-4321-cba987654321 |
| Scopes | OAuth scope for AI services | https://ai.azure.com/.default |
| Agent ID | Your AI agent identifier from Azure AI Foundry | asst_abc123xyz |
The scope https://ai.azure.com/.default tells MSAL:
- Resource:
https://ai.azure.com(this becomes theaudclaim in the token) - Permissions:
/.defaultrequests all delegated permissions granted to the app
This matches Azure AI Foundry's expected token audience.
If you want to use Azure API Management as a proxy (for rate limiting, analytics, etc.), you can configure APIM to sit between your SPA and Azure AI Foundry.
- Create APIM instance in Azure Portal
- Import API:
- Create a new API in APIM
- Use the OpenAPI spec from
/APIM/openai-spec.yamlif available, or manually define endpoints
- Configure Policy:
- Go to your API → All operations → Policies
- Edit the inbound policy using
/APIM/api_policies.xmlas a template
The policy template at /APIM/api_policies.xml contains placeholders you need to replace:
Placeholders to replace:
WEB_APP_URL- Replace with your SPA's URL (e.g.,https://mdspinali.github.io/Azure-AI-Foundry-Agent-Service-Entra-Test-Chat/orhttp://localhost:5173)TENANT_ID- Replace with your Azure AD tenant ID<Azure AI Foundry project endpoint>- Replace with your full project endpoint:https://YOUR-RESOURCE.services.ai.azure.com/api/projects/YOUR-PROJECT
Example:
<origin>WEB_APP_URL</origin>Replace with:
<origin>https://mdspinali.github.io/Azure-AI-Foundry-Agent-Service-Entra-Test-Chat/</origin>If using APIM, update your application's Azure Endpoint setting to point to your APIM gateway instead of directly to Azure AI Foundry:
https://your-apim-name.azure-api.net/your-api-path
The APIM policy will then forward requests to Azure AI Foundry with proper authentication.
# Install dependencies
npm install
# Start dev server
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview- React 19 with TypeScript
- Vite for fast development and building
- @azure/msal-react & @azure/msal-browser for Entra ID authentication
- openai SDK (v4+) configured for Azure
- Pure CSS (no UI framework dependencies)
- No API keys in code - Uses Entra ID tokens
- Token-based authentication - Tokens auto-refresh
- No backend required - Direct secure calls to Azure
- RBAC controlled - Access managed via Azure IAM
- HTTPS only - All communication encrypted
Solution:
- Verify you added Azure Machine Learning Services API permission
- Ensure scope is
https://ai.azure.com/.default - Check you have RBAC role on AI Foundry project
- Try signing out and back in to get a fresh token
Solution: Configure your Agent ID in Settings. Get it from AI Foundry portal under your agent details.
Solution:
- Verify redirect URI in Entra app registration matches your app URL exactly
- Check browser console for MSAL errors
- Clear localStorage and try again
Solution: Azure AI Foundry supports CORS by default. If using APIM, ensure CORS policy is configured.
- Build the app:
npm run build - Deploy
dist/folder to your hosting (Azure Static Web Apps, etc.) - Update Entra redirect URI to production URL
- Update settings in the app UI with production values
# Install Azure SWA CLI
npm install -g @azure/static-web-apps-cli
# Deploy
swa deployMIT License - See LICENSE file for details.
This project is provided "AS IS" without warranty of any kind, express or implied. This is an independent implementation and is NOT affiliated with, endorsed by, supported by, or in any way officially connected with Microsoft Corporation or any of its subsidiaries or affiliates.
The use of Microsoft Azure services, Azure AI Foundry, and Microsoft Entra ID through this application is subject to Microsoft's terms of service and policies. Users are solely responsible for:
- Compliance with all applicable Microsoft service agreements
- All costs associated with Azure resource usage
- Security and proper configuration of their Azure resources
- Obtaining appropriate licenses and permissions for Microsoft services
Microsoft, Azure, Azure AI Foundry, and Microsoft Entra ID are trademarks of Microsoft Corporation.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
NO SUPPORT: This project is provided without any support, maintenance, or service level agreements. Use at your own risk.
Issues and PRs welcome!