Skip to main content
Intune Commander uses Azure.Identity for authentication across all supported cloud environments. The authentication layer supports interactive browser, device code, and client secret flows.

IAuthenticationProvider

The core authentication abstraction returns an Azure TokenCredential for a given tenant profile.

Interface

public interface IAuthenticationProvider
{
    Task<TokenCredential> GetCredentialAsync(
        TenantProfile profile,
        Func<DeviceCodeInfo, CancellationToken, Task>? deviceCodeCallback = null,
        CancellationToken cancellationToken = default);
}
profile
TenantProfile
required
Tenant configuration including auth method, client ID, tenant ID, and cloud environment
deviceCodeCallback
Func<DeviceCodeInfo, CancellationToken, Task>
Callback to display device code when using AuthMethod.DeviceCode
cancellationToken
CancellationToken
Cancellation token
return
Task<TokenCredential>
Azure Identity credential instance (InteractiveBrowserCredential, DeviceCodeCredential, or ClientSecretCredential)
See IAuthenticationProvider.cs:9 for the interface definition.

InteractiveBrowserAuthProvider

The default implementation creates credentials based on the TenantProfile.AuthMethod.

Authentication Methods

Default flow for desktop applications. Opens the system browser for interactive sign-in.
var profile = new TenantProfile
{
    Name = "Production Tenant",
    TenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    ClientId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    Cloud = CloudEnvironment.Commercial,
    AuthMethod = AuthMethod.Interactive
};

var credential = await authProvider.GetCredentialAsync(profile);
Uses InteractiveBrowserCredential with:
  • Redirect URI: http://localhost:45132 (high port for macOS compatibility)
  • Token cache persisted per tenant profile ID
  • Unencrypted cache allowed on Linux where secure storage may be unavailable
See InteractiveBrowserAuthProvider.cs:45 for implementation.

IntuneGraphClientFactory

Creates authenticated GraphServiceClient instances configured for the correct cloud environment.

CreateClientAsync

Simplified method that returns just the Graph client.
public async Task<GraphServiceClient> CreateClientAsync(
    TenantProfile profile,
    Func<DeviceCodeInfo, CancellationToken, Task>? deviceCodeCallback = null,
    CancellationToken cancellationToken = default)
profile
TenantProfile
required
Tenant configuration
deviceCodeCallback
Func<DeviceCodeInfo, CancellationToken, Task>
Device code callback (only used if profile.AuthMethod is DeviceCode)
return
Task<GraphServiceClient>
Authenticated Microsoft Graph Beta client configured for the tenant’s cloud endpoint
Example:
var factory = new IntuneGraphClientFactory(authProvider);
var client = await factory.CreateClientAsync(profile);

// Use the client directly
var devices = await client.DeviceManagement.ManagedDevices.GetAsync();
See IntuneGraphClientFactory.cs:17 for implementation.

CreateClientWithCredentialAsync

Extended method that returns the Graph client, credential, and scopes for advanced scenarios.
public async Task<(GraphServiceClient Client, TokenCredential Credential, string[] Scopes)> 
    CreateClientWithCredentialAsync(
        TenantProfile profile,
        Func<DeviceCodeInfo, CancellationToken, Task>? deviceCodeCallback = null,
        CancellationToken cancellationToken = default)
Client
GraphServiceClient
Authenticated Graph client
Credential
TokenCredential
Underlying Azure Identity credential (can be used independently for permission checks)
Scopes
string[]
OAuth scopes used for the client (e.g., ["https://graph.microsoft.com/.default"])
Use Case: Permission checking before API calls
var (client, credential, scopes) = await factory.CreateClientWithCredentialAsync(profile);

// Acquire token to check permissions
var token = await credential.GetTokenAsync(
    new TokenRequestContext(scopes), 
    cancellationToken);

// Decode JWT to inspect claims/roles
var handler = new JwtSecurityTokenHandler();
var jwt = handler.ReadJwtToken(token.Token);
var roles = jwt.Claims.Where(c => c.Type == "roles").Select(c => c.Value);
See IntuneGraphClientFactory.cs:31 for implementation.

TenantProfile Model

Configuration object for a single tenant connection.
public class TenantProfile
{
    public string Id { get; set; } // Auto-generated GUID
    public required string Name { get; set; }
    public required string TenantId { get; set; }
    public required string ClientId { get; set; }
    public CloudEnvironment Cloud { get; set; } = CloudEnvironment.Commercial;
    public AuthMethod AuthMethod { get; set; } = AuthMethod.Interactive;
    public string? ClientSecret { get; set; }
    public DateTime? LastUsed { get; set; }
}
Id
string
Unique identifier for the profile (auto-generated GUID). Used for token cache isolation.
Name
string
required
Display name for the profile (e.g., “Production”, “Dev Tenant”)
TenantId
string
required
Azure AD tenant ID (GUID)
ClientId
string
required
Azure AD app registration client ID. Must have appropriate Graph API permissions.
Cloud
CloudEnvironment
Target cloud environment. Defaults to CloudEnvironment.Commercial.
AuthMethod
AuthMethod
Authentication method. Defaults to AuthMethod.Interactive.
ClientSecret
string
Client secret (only required when AuthMethod is ClientSecret)
LastUsed
DateTime?
Timestamp of last successful authentication (updated by ProfileService)
See TenantProfile.cs:5 for the model definition.

Cloud Environments

public enum CloudEnvironment
{
    Commercial,  // Public Azure + Microsoft 365 GCC
    GCC,         // Alias for Commercial (same endpoints)
    GCCHigh,     // Microsoft 365 GCC High
    DoD          // Department of Defense
}
Endpoint mapping via CloudEndpoints.GetEndpoints():
CloudGraph Base URLAuthority Host
Commercialhttps://graph.microsoft.com/betahttps://login.microsoftonline.com
GCChttps://graph.microsoft.com/betahttps://login.microsoftonline.com
GCCHighhttps://graph.microsoft.us/betahttps://login.microsoftonline.us
DoDhttps://dod-graph.microsoft.us/betahttps://login.microsoftonline.us
Scopes are derived from the base URL: ["{rootUrl}/.default"] See CloudEndpoints.cs:7 for endpoint resolution logic.

Token Caching

Token caches are persisted per profile ID to support multiple tenant connections:
var tokenCacheOptions = new TokenCachePersistenceOptions
{
    Name = $"IntuneCommander-{profile.Id}",
    UnsafeAllowUnencryptedStorage = OperatingSystem.IsLinux()
};
  • Windows/macOS: Tokens stored in OS credential store (encrypted)
  • Linux: Plaintext cache allowed (secure storage often unavailable)
  • Cache path: Platform-dependent (MSAL default locations)
See InteractiveBrowserAuthProvider.cs:17 for cache configuration.

Required Permissions

The app registration must have delegated or application permissions depending on auth method:

Delegated Permissions (Interactive, DeviceCode)

  • DeviceManagementConfiguration.ReadWrite.All
  • DeviceManagementApps.ReadWrite.All
  • DeviceManagementManagedDevices.ReadWrite.All
  • DeviceManagementServiceConfig.ReadWrite.All
  • Directory.Read.All
  • Group.Read.All
  • Policy.Read.All (for Conditional Access read-only)

Application Permissions (ClientSecret)

  • Same as delegated, but with .All suffix
  • Requires admin consent
See docs/GRAPH-PERMISSIONS.md for the complete list and setup script.

Next Steps

Graph Services

Use authenticated clients with Intune services

Cache Service

Cache Graph data to reduce API calls

Build docs developers (and LLMs) love