Securing your Model Context Protocol (MCP) server is as important as locking the front door of your house.
Leaving your MCP server open exposes your tools and data to unauthorized access, which can lead to security breaches.
Microsoft Entra ID provides a robust cloud-based identity and access management solution, helping ensure that only authorized users and applications can interact with your MCP server.
In this section, you’ll learn how to protect your AI workflows using Entra ID authentication.
By the end of this section, you will be able to:
Just as you wouldn't leave the front door of your house unlocked, you shouldn't leave your MCP server open for anyone to access.
Securing your AI workflows is essential for building robust, trustworthy, and safe applications.
This chapter will introduce you to using Microsoft Entra ID to secure your MCP servers, ensuring that only authorized users and applications can interact with your tools and data.
Imagine your MCP server has a tool that can send emails or access a customer database. An unsecured server would mean anyone could potentially use that tool, leading to unauthorized data access, spam, or other malicious activities.
By implementing authentication, you ensure that every request to your server is verified, confirming the identity of the user or application making the request. This is the first and most critical step in securing your AI workflows.
By using Entra ID, you can:
For MCP servers, Entra ID provides a robust and widely-trusted solution to manage who can access your server's capabilities.
---
Entra ID uses open standards like OAuth 2.0 to handle authentication. While the details can be complex, the core concept is simple and can be understood with an analogy.
Think of OAuth 2.0 like a valet service for your car.
When you arrive at a restaurant, you don't give the valet your master key.
Instead, you provide a valet key that has limited permissions—it can start the car and lock the doors, but it can't open the trunk or the glove compartment.
In this analogy:
The access token is a secure string of text that the MCP client receives from Entra ID after you sign in.
The client then presents this token to the MCP server with every request.
The server can verify the token to ensure the request is legitimate and that the client has the necessary permissions, all without ever needing to handle your actual credentials (like your password).
Here’s how the process works in practice:
sequenceDiagram
actor User as 👤 User
participant Client as 🖥️ MCP Client
participant Entra as 🔐 Microsoft Entra ID
participant Server as 🔧 MCP Server
Client->>+User: Please sign in to continue.
User->>+Entra: Enters credentials (username/password).
Entra-->>Client: Here is your access token.
User-->>-Client: (Returns to the application)
Client->>+Server: I need to use a tool. Here is my access token.
Server->>+Entra: Is this access token valid?
Entra-->>-Server: Yes, it is.
Server-->>-Client: Token is valid. Here is the result of the tool.
Before we dive into the code, it's important to introduce a key component you'll see in the examples: the Microsoft Authentication Library (MSAL).
MSAL is a library developed by Microsoft that makes it much easier for developers to handle authentication.
Instead of you having to write all the complex code to handle security tokens, manage sign-ins, and refresh sessions, MSAL takes care of the heavy lifting.
Using a library like MSAL is highly recommended because:
MSAL supports a wide variety of languages and application frameworks, including .NET, JavaScript/TypeScript, Python, Java, Go, and mobile platforms like iOS and Android.
This means you can use the same consistent authentication patterns across your entire technology stack.
To learn more about MSAL, you can check out the official MSAL overview documentation.
---
Now, let's walk through how to secure a local MCP server (one that communicates over stdio) using Entra ID.
This example uses a public client, which is suitable for applications running on a user's machine, like a desktop app or a local development server.
In this scenario, we'll look at an MCP server that runs locally, communicates over stdio, and uses Entra ID to authenticate the user before allowing access to its tools.
The server will have a single tool that fetches the user's profile information from the Microsoft Graph API.
Before writing any code, you need to register your application in Microsoft Entra ID. This tells Entra ID about your application and grants it permission to use the authentication service.
1. Navigate to the Microsoft Entra portal.
2. Go to App registrations and click New registration.
3. Give your application a name (e.g., "My Local MCP Server").
4. For Supported account types, select Accounts in this organizational directory only.
5. You can leave the Redirect URI blank for this example.
6. Click Register.
Once registered, take note of the Application (client) ID and Directory (tenant) ID. You'll need these in your code.
Let's look at the key parts of the code that handle authentication.
The full code for this example is available in the Entra ID - Local - WAM folder of the mcp-auth-servers GitHub repository.
AuthenticationService.cs
This class is responsible for handling the interaction with Entra ID.
CreateAsync: This method initializes the PublicClientApplication from the MSAL (Microsoft Authentication Library). It's configured with your application's clientId and tenantId.WithBroker: This enables the use of a broker (like the Windows Web Account Manager), which provides a more secure and seamless single sign-on experience.AcquireTokenAsync: This is the core method. It first tries to get a token silently (meaning the user won't have to sign in again if they already have a valid session). If a silent token can't be acquired, it will prompt the user to sign in interactively.
// Simplified for clarity
public static async Task<AuthenticationService> CreateAsync(ILogger<AuthenticationService> logger)
{
var msalClient = PublicClientApplicationBuilder
.Create(_clientId) // Your Application (client) ID
.WithAuthority(AadAuthorityAudience.AzureAdMyOrg)
.WithTenantId(_tenantId) // Your Directory (tenant) ID
.WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows))
.Build();
// ... cache registration ...
return new AuthenticationService(logger, msalClient);
}
public async Task<string> AcquireTokenAsync()
{
try
{
// Try silent authentication first
var accounts = await _msalClient.GetAccountsAsync();
var account = accounts.FirstOrDefault();
AuthenticationResult? result = null;
if (account != null)
{
result = await _msalClient.AcquireTokenSilent(_scopes, account).ExecuteAsync();
}
else
{
// If no account, or silent fails, go interactive
result = await _msalClient.AcquireTokenInteractive(_scopes).ExecuteAsync();
}
return result.AccessToken;
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while acquiring the token.");
throw; // Optionally rethrow the exception for higher-level handling
}
}
Program.cs
This is where the MCP server is set up and the authentication service is integrated.
AddSingleton: This registers the AuthenticationService with the dependency injection container, so it can be used by other parts of the application (like our tool).GetUserDetailsFromGraph tool: This tool requires an instance of AuthenticationService. Before it does anything, it calls authService.AcquireTokenAsync() to get a valid access token. If authentication is successful, it uses the token to call the Microsoft Graph API and fetch the user's details.
// Simplified for clarity
[McpServerTool(Name = "GetUserDetailsFromGraph")]
public static async Task<string> GetUserDetailsFromGraph(
AuthenticationService authService)
{
try
{
// This will trigger the authentication flow
var accessToken = await authService.AcquireTokenAsync();
// Use the token to create a GraphServiceClient
var graphClient = new GraphServiceClient(
new BaseBearerTokenAuthenticationProvider(new TokenProvider(authService)));
var user = await graphClient.Me.GetAsync();
return System.Text.Json.JsonSerializer.Serialize(user);
}
catch (Exception ex)
{
return $"Error: {ex.Message}";
}
}
1.
When the MCP client tries to use the GetUserDetailsFromGraph tool, the tool first calls AcquireTokenAsync.
2. AcquireTokenAsync triggers the MSAL library to check for a valid token.
3. If no token is found, MSAL, through the broker, will prompt the user to sign in with their Entra ID account.
4. Once the user signs in, Entra ID issues an access token.
5. The tool receives the token and uses it to make a secure call to the Microsoft Graph API.
6. The user's details are returned to the MCP client.
This process ensures that only authenticated users can use the tool, effectively securing your local MCP server.
When your MCP server is running on a remote machine (like a cloud server) and communicates over a protocol like HTTP Streaming, the security requirements are different.
In this case, you should use a confidential client and the Authorization Code Flow.
This is a more secure method because the application's secrets are never exposed to the browser.
This example uses a TypeScript-based MCP server that uses Express.js to handle HTTP requests.
The setup in Entra ID is similar to the public client, but with one key difference: you need to create a client secret.
1. Navigate to the Microsoft Entra portal.
2. In your app registration, go to the Certificates & secrets tab.
3. Click New client secret, give it a description, and click Add.
4. Important: Copy the secret value immediately. You will not be able to see it again.
5.
You also need to configure a Redirect URI.
Go to the Authentication tab, click Add a platform, select Web, and enter the redirect URI for your application (e.g., http://localhost:3001/auth/callback).
> ⚠️ Important Security Note: For production applications, Microsoft strongly recommends using secretless authentication methods such as Managed Identity or Workload Identity Federation instead of client secrets.
Client secrets pose security risks as they can be exposed or compromised.
Managed identities provide a more secure approach by eliminating the need to store credentials in your code or configuration.
>
> For more information about managed identities and how to implement them, see the Managed identities for Azure resources overview.
This example uses a session-based approach.
When the user authenticates, the server stores the access token and refresh token in a session and gives the user a session token.
This session token is then used for subsequent requests.
The full code for this example is available in the Entra ID - Confidential client folder of the mcp-auth-servers GitHub repository.
Server.ts
This file sets up the Express server and the MCP transport layer.
requireBearerAuth: This is middleware that protects the /sse and /message endpoints. It checks for a valid bearer token in the Authorization header of the request.EntraIdServerAuthProvider: This is a custom class that implements the McpServerAuthorizationProvider interface. It's responsible for handling the OAuth 2.0 flow./auth/callback: This endpoint handles the redirect from Entra ID after the user has authenticated. It exchanges the authorization code for an access token and a refresh token.
// Simplified for clarity
const app = express();
const { server } = createServer();
const provider = new EntraIdServerAuthProvider();
// Protect the SSE endpoint
app.get("/sse", requireBearerAuth({
provider,
requiredScopes: ["User.Read"]
}), async (req, res) => {
// ... connect to the transport ...
});
// Protect the message endpoint
app.post("/message", requireBearerAuth({
provider,
requiredScopes: ["User.Read"]
}), async (req, res) => {
// ... handle the message ...
});
// Handle the OAuth 2.0 callback
app.get("/auth/callback", (req, res) => {
provider.handleCallback(req.query.code, req.query.state)
.then(result => {
// ... handle success or failure ...
});
});
Tools.ts
This file defines the tools that the MCP server provides.
The getUserDetails tool is similar to the one in the previous example, but it gets the access token from the session.
// Simplified for clarity
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name } = request.params;
const context = request.params?.context as { token?: string } | undefined;
const sessionToken = context?.token;
if (name === ToolName.GET_USER_DETAILS) {
if (!sessionToken) {
throw new AuthenticationError("Authentication token is missing or invalid. Ensure the token is provided in the request context.");
}
// Get the Entra ID token from the session store
const tokenData = tokenStore.getToken(sessionToken);
const entraIdToken = tokenData.accessToken;
const graphClient = Client.init({
authProvider: (done) => {
done(null, entraIdToken);
}
});
const user = await graphClient.api('/me').get();
// ... return user details ...
}
});
auth/EntraIdServerAuthProvider.ts
This class handles the logic for:
tokenStore.1.
When a user first tries to connect to the MCP server, the requireBearerAuth middleware will see that they don't have a valid session and will redirect them to the Entra ID sign-in page.
2. The user signs in with their Entra ID account.
3. Entra ID redirects the user back to the /auth/callback endpoint with an authorization code.
4. The server exchanges the code for an access token and a refresh token, stores them, and creates a session token which is sent to the client.
5. The client can now use this session token in the Authorization header for all future requests to the MCP server.
6.
When the getUserDetails tool is called, it uses the session token to look up the Entra ID access token and then uses that to call the Microsoft Graph API.
This flow is more complex than the public client flow, but is required for internet-facing endpoints.
Since remote MCP servers are accessible over the public internet, they need stronger security measures to protect against unauthorized access and potential attacks.
1. Think about an MCP server you might build. Would it be a local server or a remote server?
2. Based on your answer, would you use a public or confidential client?
3. What permission would your MCP server request for performing actions against Microsoft Graph?
Navigate to the Microsoft Entra portal.
Register a new application for your MCP server.
Record the Application (client) ID and Directory (tenant) ID.
1. MSAL Overview Documentation
Learn how the Microsoft Authentication Library (MSAL) enables secure token acquisition across platforms:
MSAL Overview on Microsoft Learn
2. Azure-Samples/mcp-auth-servers GitHub Repository
Reference implementations of MCP servers demonstrating authentication flows:
Azure-Samples/mcp-auth-servers on GitHub
3. Managed Identities for Azure Resources Overview
Understand how to eliminate secrets by using system- or user-assigned managed identities:
Managed Identities Overview on Microsoft Learn
4. Azure API Management: Your Auth Gateway for MCP Servers
A deep dive into using APIM as a secure OAuth2 gateway for MCP servers:
Azure API Management Your Auth Gateway For MCP Servers
5. Microsoft Graph Permissions Reference
Comprehensive list of delegated and application permissions for Microsoft Graph:
Microsoft Graph Permissions Reference
After completing this section, you will be able to:
모델 컨텍스트 프로토콜(MCP) 서버를 보호하는 것은 집의 현관문을 잠그는 것만큼 중요합니다.
MCP 서버를 열어두면 도구와 데이터가 무단 접근에 노출되어 보안 사고로 이어질 수 있습니다.
Microsoft Entra ID는 강력한 클라우드 기반 아이덴티티 및 접근 관리 솔루션을 제공하여, 권한이 있는 사용자와 애플리케이션만 MCP 서버와 상호작용할 수 있도록 도와줍니다.
이 섹션에서는 Entra ID 인증을 사용해 AI 워크플로우를 보호하는 방법을 배웁니다.
이 섹션을 마치면 다음을 할 수 있습니다:
집의 현관문을 잠그지 않고 두지 않는 것처럼, MCP 서버도 누구나 접근할 수 있도록 열어두면 안 됩니다. AI 워크플로우를 안전하게 보호하는 것은 견고하고 신뢰할 수 있으며 안전한 애플리케이션을 만드는 데 필수적입니다. 이 장에서는 Microsoft Entra ID를 사용해 MCP 서버를 보호하는 방법을 소개하며, 권한이 있는 사용자와 애플리케이션만 도구와 데이터에 접근할 수 있도록 합니다.
MCP 서버에 이메일을 보내거나 고객 데이터베이스에 접근할 수 있는 도구가 있다고 가정해 보세요. 보안이 취약한 서버라면 누구나 그 도구를 사용할 수 있어 무단 데이터 접근, 스팸 발송, 기타 악의적 행위가 발생할 수 있습니다.
인증을 구현하면 서버에 대한 모든 요청이 검증되어 요청을 하는 사용자나 애플리케이션의 신원을 확인할 수 있습니다. 이는 AI 워크플로우 보안의 첫 번째이자 가장 중요한 단계입니다.
Entra ID를 사용하면 다음이 가능합니다:
MCP 서버의 경우, Entra ID는 서버 기능에 접근할 수 있는 사용자를 관리하는 강력하고 신뢰받는 솔루션을 제공합니다.
---
Entra ID는 OAuth 2.0 같은 오픈 표준을 사용해 인증을 처리합니다. 세부 사항은 복잡할 수 있지만, 핵심 개념은 비유를 통해 쉽게 이해할 수 있습니다.
OAuth 2.0을 자동차 발렛 서비스에 비유해 보세요. 식당에 도착했을 때, 마스터 키를 발렛에게 주지 않고 제한된 권한만 가진 발렛 키를 줍니다. 이 키는 차를 시동 걸고 문을 잠글 수 있지만, 트렁크나 글러브 박스는 열 수 없습니다.
이 비유에서:
액세스 토큰은 사용자가 로그인한 후 MCP 클라이언트가 Entra ID로부터 받는 안전한 문자열입니다. 클라이언트는 이 토큰을 매 요청 시 MCP 서버에 제시하며, 서버는 토큰을 검증해 요청이 합법적이고 필요한 권한이 있는지 확인합니다. 이 과정에서 실제 사용자 자격 증명(예: 비밀번호)을 다룰 필요가 없습니다.
실제 과정은 다음과 같습니다:
sequenceDiagram
actor User as 👤 User
participant Client as 🖥️ MCP Client
participant Entra as 🔐 Microsoft Entra ID
participant Server as 🔧 MCP Server
Client->>+User: Please sign in to continue.
User->>+Entra: Enters credentials (username/password).
Entra-->>Client: Here is your access token.
User-->>-Client: (Returns to the application)
Client->>+Server: I need to use a tool. Here is my access token.
Server->>+Entra: Is this access token valid?
Entra-->>-Server: Yes, it is.
Server-->>-Client: Token is valid. Here is the result of the tool.
코드 예제를 살펴보기 전에 중요한 구성 요소인 Microsoft 인증 라이브러리(MSAL)를 소개합니다.
MSAL은 개발자가 인증을 쉽게 처리할 수 있도록 Microsoft에서 만든 라이브러리입니다. 복잡한 보안 토큰 관리, 로그인 처리, 세션 갱신 코드를 직접 작성할 필요 없이 MSAL이 이를 대신 처리합니다.
MSAL 사용을 권장하는 이유는:
MSAL은 .NET, JavaScript/TypeScript, Python, Java, Go, iOS, Android 등 다양한 언어와 프레임워크를 지원해 전체 기술 스택에서 일관된 인증 패턴을 사용할 수 있습니다.
MSAL에 대해 더 알고 싶다면 공식 MSAL 개요 문서를 참고하세요.
---
이제 Entra ID를 사용해 로컬 MCP 서버(stdio 통신)를 보호하는 방법을 살펴보겠습니다. 이 예제는 사용자의 컴퓨터에서 실행되는 데스크톱 앱이나 로컬 개발 서버에 적합한 공개 클라이언트를 사용합니다.
이 시나리오에서는 로컬에서 실행되고 stdio로 통신하는 MCP 서버가 Entra ID로 사용자를 인증한 후 도구 접근을 허용하는 과정을 다룹니다. 서버에는 Microsoft Graph API에서 사용자 프로필 정보를 가져오는 단일 도구가 있습니다.
코드를 작성하기 전에 Microsoft Entra ID에 애플리케이션을 등록해야 합니다. 이는 Entra ID에 애플리케이션 정보를 알려 인증 서비스를 사용할 권한을 부여하는 과정입니다.
1. Microsoft Entra 포털에 접속합니다.
2. 앱 등록(App registrations)으로 이동해 새 등록(New registration)을 클릭합니다.
3. 애플리케이션 이름(예: "My Local MCP Server")을 입력합니다.
4. 지원되는 계정 유형(Supported account types)에서 이 조직 디렉터리의 계정만(Accounts in this organizational directory only)을 선택합니다.
5. 이 예제에서는 리디렉션 URI(Redirect URI)를 비워둡니다.
6. 등록(Register)을 클릭합니다.
등록 후 애플리케이션(클라이언트) ID와 디렉터리(테넌트) ID를 기록해 두세요. 코드에서 필요합니다.
인증을 처리하는 핵심 코드를 살펴보겠습니다.
전체 코드는 mcp-auth-servers GitHub 저장소의 Entra ID - Local - WAM 폴더에서 확인할 수 있습니다.
AuthenticationService.cs
이 클래스는 Entra ID와의 상호작용을 담당합니다.
CreateAsync: MSAL의 PublicClientApplication을 초기화합니다. 애플리케이션의 clientId와 tenantId로 구성됩니다.WithBroker: Windows Web Account Manager 같은 브로커 사용을 활성화해 더 안전하고 원활한 싱글 사인온 경험을 제공합니다.AcquireTokenAsync: 핵심 메서드로, 먼저 조용히 토큰을 얻으려 시도합니다(이미 유효한 세션이 있으면 로그인 과정 없이 토큰 획득). 실패하면 사용자에게 로그인 창을 띄워 인증을 진행합니다.
// Simplified for clarity
public static async Task<AuthenticationService> CreateAsync(ILogger<AuthenticationService> logger)
{
var msalClient = PublicClientApplicationBuilder
.Create(_clientId) // Your Application (client) ID
.WithAuthority(AadAuthorityAudience.AzureAdMyOrg)
.WithTenantId(_tenantId) // Your Directory (tenant) ID
.WithBroker(new BrokerOptions(BrokerOptions.OperatingSystems.Windows))
.Build();
// ... cache registration ...
return new AuthenticationService(logger, msalClient);
}
public async Task<string> AcquireTokenAsync()
{
try
{
// Try silent authentication first
var accounts = await _msalClient.GetAccountsAsync();
var account = accounts.FirstOrDefault();
AuthenticationResult? result = null;
if (account != null)
{
result = await _msalClient.AcquireTokenSilent(_scopes, account).ExecuteAsync();
}
else
{
// If no account, or silent fails, go interactive
result = await _msalClient.AcquireTokenInteractive(_scopes).ExecuteAsync();
}
return result.AccessToken;
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while acquiring the token.");
throw; // Optionally rethrow the exception for higher-level handling
}
}
Program.cs
MCP 서버를 설정하고 인증 서비스를 통합하는 부분입니다.
AddSingleton: AuthenticationService를 의존성 주입 컨테이너에 등록해 다른 부분(예: 도구)에서 사용할 수 있게 합니다.GetUserDetailsFromGraph 도구: 이 도구는 AuthenticationService 인스턴스를 필요로 합니다. 실행 전에 authService.AcquireTokenAsync()를 호출해 유효한 액세스 토큰을 얻습니다. 인증에 성공하면 토큰을 사용해 Microsoft Graph API를 호출해 사용자 정보를 가져옵니다.
// Simplified for clarity
[McpServerTool(Name = "GetUserDetailsFromGraph")]
public static async Task<string> GetUserDetailsFromGraph(
AuthenticationService authService)
{
try
{
// This will trigger the authentication flow
var accessToken = await authService.AcquireTokenAsync();
// Use the token to create a GraphServiceClient
var graphClient = new GraphServiceClient(
new BaseBearerTokenAuthenticationProvider(new TokenProvider(authService)));
var user = await graphClient.Me.GetAsync();
return System.Text.Json.JsonSerializer.Serialize(user);
}
catch (Exception ex)
{
return $"Error: {ex.Message}";
}
}
1.
MCP 클라이언트가 GetUserDetailsFromGraph 도구를 사용하려 할 때, 도구는 먼저 AcquireTokenAsync를 호출합니다.
2. AcquireTokenAsync는 MSAL 라이브러리를 통해 유효한 토큰이 있는지 확인합니다.
3. 토큰이 없으면 MSAL이 브로커를 통해 사용자에게 Entra ID 계정으로 로그인하라는 창을 띄웁니다.
4. 사용자가 로그인하면 Entra ID가 액세스 토큰을 발급합니다.
5. 도구는 토큰을 받아 Microsoft Graph API에 안전하게 요청을 보냅니다.
6. 사용자 정보가 MCP 클라이언트에 반환됩니다.
이 과정으로 인증된 사용자만 도구를 사용할 수 있어 로컬 MCP 서버가 안전하게 보호됩니다.
MCP 서버가 원격 머신(예: 클라우드 서버)에서 실행되고 HTTP 스트리밍 같은 프로토콜로 통신할 때는 보안 요구사항이 다릅니다. 이 경우 기밀 클라이언트와 Authorization Code Flow를 사용해야 합니다. 이 방법은 애플리케이션 비밀이 브라우저에 노출되지 않아 더 안전합니다.
이 예제는 Express.js를 사용해 HTTP 요청을 처리하는 TypeScript 기반 MCP 서버를 다룹니다.
설정은 공개 클라이언트와 비슷하지만, 클라이언트 비밀(client secret)을 생성해야 한다는 점이 다릅니다.
1. Microsoft Entra 포털에 접속합니다.
2. 앱 등록에서 인증서 및 비밀(Certificates & secrets) 탭으로 이동합니다.
3. 새 클라이언트 비밀(New client secret)을 클릭하고 설명을 입력한 후 추가(Add)를 클릭합니다.
4. 중요: 생성된 비밀 값을 즉시 복사하세요. 다시 볼 수 없습니다.
5. 리디렉션 URI도 설정해야 합니다. 인증(Authentication) 탭에서 플랫폼 추가(Add a platform)를 클릭하고 웹(Web)을 선택한 뒤 애플리케이션의 리디렉션 URI(예: http://localhost:3001/auth/callback)를 입력합니다.
> ⚠️ 중요한 보안 참고: 운영 환경에서는 클라이언트 비밀 대신 Managed Identity나 Workload Identity Federation 같은 비밀 없는 인증 방식을 사용하는 것을 Microsoft가 강력히 권장합니다.
클라이언트 비밀은 노출되거나 탈취될 위험이 있습니다.
관리형 아이덴티티는 코드나 설정에 자격 증명을 저장할 필요가 없어 더 안전합니다.
>
> 관리형 아이덴티티에 대한 자세한 내용과 구현 방법은 Azure 리소스용 관리형 아이덴티티 개요를 참고하세요.
이 예제는 세션 기반 방식을 사용합니다.
사용자가 인증하면 서버가 액세스 토큰과 갱신 토큰을 세션에 저장하고, 사용자에게 세션 토큰을 제공합니다.
이후 요청에 이 세션 토큰을 사용합니다.
전체 코드는 mcp-auth-servers GitHub 저장소의 Entra ID - Confidential client 폴더에서 확인할 수 있습니다.
Server.ts
Express 서버와 MCP 전송 계층을 설정합니다.
requireBearerAuth: /sse와 /message 엔드포인트를 보호하는 미들웨어입니다. 요청의 Authorization 헤더에 유효한 베어러 토큰이 있는지 확인합니다.EntraIdServerAuthProvider: McpServerAuthorizationProvider 인터페이스를 구현한 커스텀 클래스입니다. OAuth 2.0 흐름을 처리합니다./auth/callback: 사용자가 인증 후 Entra ID에서 리디렉션될 때 호출되는 엔드포인트입니다. 권한 코드를 액세스 토큰과 갱신 토큰으로 교환합니다.
// Simplified for clarity
const app = express();
const { server } = createServer();
const provider = new EntraIdServerAuthProvider();
// Protect the SSE endpoint
app.get("/sse", requireBearerAuth({
provider,
requiredScopes: ["User.Read"]
}), async (req, res) => {
// ... connect to the transport ...
});
// Protect the message endpoint
app.post("/message", requireBearerAuth({
provider,
requiredScopes: ["User.Read"]
}), async (req, res) => {
// ... handle the message ...
});
// Handle the OAuth 2.0 callback
app.get("/auth/callback", (req, res) => {
provider.handleCallback(req.query.code, req.query.state)
.then(result => {
// ... handle success or failure ...
});
});
Tools.ts
MCP 서버가 제공하는 도구들을 정의합니다. getUserDetails 도구는 이전 예제와 비슷하지만, 액세스 토큰을 세션에서 가져옵니다.
// Simplified for clarity
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name } = request.params;
const context = request.params?.context as { token?: string } | undefined;
const sessionToken = context?.token;
if (name === ToolName.GET_USER_DETAILS) {
if (!sessionToken) {
throw new AuthenticationError("Authentication token is missing or invalid. Ensure the token is provided in the request context.");
}
// Get the Entra ID token from the session store
const tokenData = tokenStore.getToken(sessionToken);
const entraIdToken = tokenData.accessToken;
const graphClient = Client.init({
authProvider: (done) => {
done(null, entraIdToken);
}
});
const user = await graphClient.api('/me').get();
// ... return user details ...
}
});
auth/EntraIdServerAuthProvider.ts
이 클래스는 다음 로직을 처리합니다:
tokenStore에 저장1. 사용자가 처음 MCP 서버에 연결하려 하면, requireBearerAuth 미들웨어가 유효한 세션이 없음을 감지하고 Entra ID 로그인 페이지로 리디렉션합니다.
2. 사용자가 Entra ID 계정으로 로그인합니다.
3. Entra ID가 권한 코드를 포함해 사용자를 /auth/callback 엔드포인트로 리디렉션합니다.
4. 서버는 코드를 액세스 토큰과 리프레시 토큰으로 교환하여 저장하고, 세션 토큰을 생성하여 클라이언트에 전송합니다.
5. 클라이언트는 이제 이 세션 토큰을 Authorization 헤더에 포함시켜 MCP 서버에 대한 모든 향후 요청에 사용할 수 있습니다.
6. getUserDetails 도구가 호출되면 세션 토큰을 사용해 Entra ID 액세스 토큰을 조회하고, 이를 이용해 Microsoft Graph API를 호출합니다.
이 흐름은 공개 클라이언트 흐름보다 복잡하지만, 인터넷에 노출된 엔드포인트에는 필수적입니다. 원격 MCP 서버는 공용 인터넷을 통해 접근 가능하므로, 무단 접근과 잠재적 공격으로부터 보호하기 위해 더 강력한 보안 조치가 필요합니다.
1. 여러분이 구축할 MCP 서버는 로컬 서버인가요, 원격 서버인가요?
2. 답변에 따라 공개 클라이언트 또는 비밀 클라이언트를 사용하시겠습니까?
3. Microsoft Graph에 대해 작업을 수행하기 위해 MCP 서버가 요청할 권한은 무엇인가요?
Microsoft Entra 포털로 이동하세요.
MCP 서버용 새 애플리케이션을 등록하세요.
애플리케이션(클라이언트) ID와 디렉터리(테넌트) ID를 기록하세요.
1. MSAL 개요 문서
Microsoft Authentication Library(MSAL)가 플랫폼 전반에서 안전한 토큰 획득을 어떻게 지원하는지 알아보세요:
MSAL Overview on Microsoft Learn
2. Azure-Samples/mcp-auth-servers GitHub 저장소
인증 흐름을 보여주는 MCP 서버 참조 구현 예제:
Azure-Samples/mcp-auth-servers on GitHub
3. Azure 리소스용 관리 ID 개요
시스템 또는 사용자 할당 관리 ID를 사용해 비밀 정보를 제거하는 방법을 이해하세요:
Managed Identities Overview on Microsoft Learn
4. Azure API Management: MCP 서버용 인증 게이트웨이
MCP 서버를 위한 안전한 OAuth2 게이트웨이로 APIM을 사용하는 방법 심층 분석:
Azure API Management Your Auth Gateway For MCP Servers
5. Microsoft Graph 권한 참조
Microsoft Graph에 대한 위임 및 애플리케이션 권한의 포괄적 목록:
Microsoft Graph Permissions Reference
이 섹션을 완료하면 다음을 할 수 있습니다:
면책 조항:
이 문서는 AI 번역 서비스 Co-op Translator를 사용하여 번역되었습니다.
정확성을 위해 최선을 다하고 있으나, 자동 번역에는 오류나 부정확한 부분이 있을 수 있음을 유의하시기 바랍니다.
원문은 해당 언어의 원본 문서가 권위 있는 출처로 간주되어야 합니다.
중요한 정보의 경우 전문적인 인간 번역을 권장합니다.
본 번역 사용으로 인해 발생하는 오해나 잘못된 해석에 대해 당사는 책임을 지지 않습니다.