| title | Build and deploy an Azure OpenAI (Express.js) chatbot | |||
|---|---|---|---|---|
| description | Learn how to build a Node.js web app that connects to Azure OpenAI and deploy it to Azure App Service using managed identity. | |||
| author | jefmarti | |||
| ms.author | jefmarti | |||
| ms.date | 03/03/2026 | |||
| ms.update-cycle | 180-days | |||
| ms.topic | tutorial | |||
| ms.custom |
|
|||
| ms.collection | ce-skilling-ai-copilot | |||
| ms.service | azure-app-service |
In this tutorial, you build an intelligent AI application by integrating Azure OpenAI with a Node.js web application, and deploy it to Azure App Service.
You create an Express app with a view and a controller that sends chat completion requests to a model in Azure OpenAI. You connect to the app in Azure by using a managed identity.
You learn how to:
[!div class="checklist"]
- Create an Azure OpenAI resource and deploy a language model.
- Build an Express.js application that connects to Azure OpenAI.
- Deploy the application to Azure App Service.
- Implement passwordless secure authentication in the development environment and in Azure.
:::image type="content" source="media/tutorial-ai-openai-chatbot-nodejs/chat-in-browser.png" alt-text="Screenshot showing chatbot running in Azure App Service.":::
- An Azure account with an active subscription
- A GitHub account for using GitHub Codespaces
[!INCLUDE tutorial-ai-openai-chatbot/create-openai-resource]
-
In your codespace terminal, create an Express.js template in the workspace and run it.
npx express-generator . --view ejs npm audit fix --force npm install && npm start
-
You see a notification in GitHub Codespaces that the app is available at a specific port. Select Open in browser to launch the app in a new browser tab.
-
In the codespace terminal, stop the app by pressing Ctrl+C.
-
Install the NPM dependencies for working with Azure OpenAI.
npm install openai @azure/openai @azure/identity
-
In the file tree, open views/index.ejs and replace its contents with the following code for a simple chat interface.
<!DOCTYPE html> <html> <head> <title><%= title %></title> <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"> </head> <body class="bg-light"> <div class="container py-4"> <h1 class="mb-4"><%= title %></h1> <div class="card mb-3"> <div class="card-body" style="min-height: 80px;"> <form action="/chat" method="POST" class="d-flex gap-2 mb-3"> <input type="text" name="message" class="form-control" placeholder="Type your message..." autocomplete="off" required /> <button type="submit" class="btn btn-primary">Send</button> </form> <% if (aiMessage) { %> <div class="mb-2"> <span class="fw-bold text-success">AI:</span> <span class="ms-2"><%= aiMessage %></span> </div> <% } %> </div> </div> </div> </body> </html>
-
Open routes/index.js and replace its content with the following code for a simple chat completion call with Azure OpenAI:
var express = require('express'); var router = express.Router(); const { AzureOpenAI } = require('openai'); const { getBearerTokenProvider, DefaultAzureCredential } = require('@azure/identity'); const endpoint = process.env.AZURE_OPENAI_ENDPOINT; const deployment = 'gpt-4o-mini'; const apiVersion = '2024-10-21'; const credential = new DefaultAzureCredential(); const scope = 'https://cognitiveservices.azure.com/.default'; const azureADTokenProvider = getBearerTokenProvider(credential, scope); // Initialize Azure OpenAI client using Microsoft Entra authentication const openai = new AzureOpenAI({ endpoint, azureADTokenProvider, deployment, apiVersion }); router.get('/', function(req, res, next) { res.render('index', { title: 'Express Chat', aiMessage: null }); }); router.post('/chat', async function(req, res, next) { const userMessage = req.body.message; if (!userMessage) { return res.redirect('/'); } let aiMessage = ''; try { // Call Azure OpenAI chat completion const result = await openai.chat.completions.create({ model: deployment, messages: [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: userMessage } ], }); aiMessage = result.choices[0]?.message?.content || ''; } catch (err) { aiMessage = 'Error: Unable to get response from Azure OpenAI.'; } res.render('index', { title: 'Express Chat', aiMessage }); }); module.exports = router;
-
In the terminal, retrieve your OpenAI endpoint:
az cognitiveservices account show \ --name $OPENAI_SERVICE_NAME \ --resource-group $RESOURCE_GROUP \ --query properties.endpoint \ --output tsv
-
Run the app by adding
AZURE_OPENAI_ENDPOINTwith its value from the preceding CLI output:AZURE_OPENAI_ENDPOINT=<output-from-previous-cli-command> npm start
-
Select Open in browser to launch the app in a new browser tab. Submit a question to see a response message.
Now that your app works locally, deploy it to Azure App Service and set up a service connection to Azure OpenAI using managed identity.
-
First, deploy your app to Azure App Service using the Azure CLI command
az webapp up. This command creates a new web app in the same resource group as your OpenAI resource and deploys your code to it. The command might take a few minutes to complete.az webapp up \ --resource-group $RESOURCE_GROUP \ --location $LOCATION \ --name $APPSERVICE_NAME \ --plan $APPSERVICE_NAME \ --sku B1 \ --os-type Linux \ --track-status false -
After the app is deployed, create a service connection between your web app and the Azure OpenAI resource using managed identity. The following command creates a connection between your web app and the Azure OpenAI resource by:
- Generating system-assigned managed identity for the web app.
- Adding the Cognitive Services OpenAI Contributor role to the managed identity for the Azure OpenAI resource.
- Adding the
AZURE_OPENAI_ENDPOINTapp setting to your web app.
az webapp connection create cognitiveservices \ --resource-group $RESOURCE_GROUP \ --name $APPSERVICE_NAME \ --target-resource-group $RESOURCE_GROUP \ --account $OPENAI_SERVICE_NAME \ --connection azure_openai \ --system-identity -
Find the URL of your deployed app in the terminal output from the
az webapp upcommand, and navigate to the app in your web browser.az webapp browse -
In your web app, enter a message in the textbox and select Send. Give the app a few seconds to reply with the message from Azure OpenAI.
:::image type="content" source="media/tutorial-ai-openai-chatbot-nodejs/chat-in-browser.png" alt-text="Screenshot showing chatbot running in Azure App Service.":::
Your app is now deployed and connected to Azure OpenAI with managed identity.
- How can I connect to OpenAI instead of Azure OpenAI?
- Can I connect to Azure OpenAI with an API key instead of managed identity?
- How does the DefaultAzureCredential work?
To connect to OpenAI instead of Azure OpenAI, use the following code:
const { OpenAI } = require('openai');
const client = new OpenAI({
apiKey: "<openai-api-key>",
});For more information, see OpenAI API authentication.
Important
When working with connection secrets like API keys in App Service, you should use Azure Key Vault references instead of storing secrets directly in your code. This practice ensures that sensitive information remains secure and is managed centrally.
Yes, you can connect to Azure OpenAI using an API key instead of managed identity. For more information, see Use the Azure OpenAI Responses API.
Important
When working with connection secrets like API keys in App Service, you should use Key Vault references instead of storing secrets directly in your code. This practice ensures that sensitive information remains secure and is managed centrally.
The DefaultAzureCredential simplifies authentication by automatically selecting the best available authentication method.
- During local development, after you run
az login, theDefaultAzureCredentialuses your local Azure CLI credentials. - For Azure App Service deployments, the
DefaultAzureCredentialuses the app's managed identity for secure, passwordless authentication.
This approach lets your code run securely and seamlessly in both local and cloud environments without modification.