Learn how to authenticate requests to Microsoft Graph using Azure.Identity and TokenCredential
Authentication is required for all Microsoft Graph API requests. The SDK v5+ uses Azure.Identity’s TokenCredential implementations, providing secure and flexible authentication options.
The Microsoft Graph .NET SDK doesn’t implement authentication directly. Instead, it accepts any TokenCredential from the Azure.Identity library, which handles token acquisition and management.
The SDK v5 uses Azure.Identity’s TokenCredential directly. You no longer need a separate authentication library like the deprecated Microsoft.Graph.Auth package.
Ideal for devices without a web browser or input constraints (IoT devices, CLI tools).
using Azure.Identity;using Microsoft.Graph;string[] scopes = { "User.Read" };string clientId = "YOUR_CLIENT_ID";string tenantId = "YOUR_TENANT_ID";var options = new DeviceCodeCredentialOptions{ ClientId = clientId, TenantId = tenantId, DeviceCodeCallback = (code, cancellation) => { Console.WriteLine(code.Message); return Task.CompletedTask; }};var credential = new DeviceCodeCredential(options);var graphClient = new GraphServiceClient(credential, scopes);var user = await graphClient.Me.GetAsync();
The device code flow displays a code and URL for users to authenticate on another device. Perfect for scenarios where direct browser interaction isn’t possible.
For server-side applications that run without user interaction.
using Azure.Identity;using Microsoft.Graph;string[] scopes = { "https://graph.microsoft.com/.default" };string tenantId = "YOUR_TENANT_ID";string clientId = "YOUR_CLIENT_ID";string clientSecret = "YOUR_CLIENT_SECRET";var credential = new ClientSecretCredential( tenantId, clientId, clientSecret);var graphClient = new GraphServiceClient(credential, scopes);// Application permissions - access specific users, not /mevar user = await graphClient.Users["user-id"].GetAsync();
Application Permissions Required: Client credential flows use application permissions (not delegated). You must request admin consent and use the .default scope. You cannot access /me endpoint - use specific user IDs instead.
Only use when other flows are not possible. Does not support MFA.
using Azure.Identity;using Microsoft.Graph;string[] scopes = { "User.Read" };string tenantId = "YOUR_TENANT_ID";string clientId = "YOUR_CLIENT_ID";string username = "[email protected]";string password = "password";var credential = new UsernamePasswordCredential( username, password, tenantId, clientId);var graphClient = new GraphServiceClient(credential, scopes);var user = await graphClient.Me.GetAsync();
The Resource Owner Password Credential (ROPC) flow is not recommended. It doesn’t support MFA, conditional access, or consent. Use only as a last resort for legacy scenarios.
Try multiple authentication methods in sequence until one succeeds.
using Azure.Identity;using Microsoft.Graph;string[] scopes = { "User.Read" };string clientId = "YOUR_CLIENT_ID";// Try environment variables first, then interactive browservar credential = new ChainedTokenCredential( new EnvironmentCredential(), new InteractiveBrowserCredential(new InteractiveBrowserCredentialOptions { ClientId = clientId }));var graphClient = new GraphServiceClient(credential, scopes);var user = await graphClient.Me.GetAsync();
Chained credentials are excellent for development scenarios: use developer credentials locally and managed identity in production, all with the same code.
// Error: AADSTS70011: Invalid scope// Cause: Scope not configured in app registration// Solution: Ensure scope is added in Azure AD app registrationstring[] scopes = { "User.Read" }; // Must be configured in portal
// Error: Insufficient privileges to complete the operation// Cause: Application doesn't have required permissions or admin consent// Solution: // 1. Add permission in Azure AD app registration// 2. Grant admin consent// 3. Use correct permission type (delegated vs application)