All methods use the Microsoft.Graph PowerShell SDK (Install-Module Microsoft.Graph). Check what you're connected as with Get-MgContext; end the session with Disconnect-MgGraph.
When to use what
| Method | Identity type | Permissions used | Secrets to manage | Typical use |
|---|---|---|---|---|
| Interactive (browser) | Delegated (you) | Delegated scopes, limited by your role | None | Ad-hoc admin work at the console |
| Device code | Delegated (you) | Delegated scopes | None | Headless/remote sessions, no local browser |
| Client secret | Application | Application permissions (admin-consented) | Secret string — expires, can leak | Scripts/services where certificates aren't feasible yet |
| Certificate | Application | Application permissions (admin-consented) | Certificate + private key | Unattended automation on servers, scheduled tasks |
| Managed identity | Application | Application permissions (granted via Graph) | None | Anything running in Azure: Automation, Functions, VMs |
Rule of thumb: interactive for humans, managed identity for anything hosted in Azure, certificate for unattended automation outside Azure, client secret only when the platform can't hold a certificate. Device code is interactive auth for terminals that can't pop a browser.
1. Delegated interactive
Connect-MgGraph -Scopes "User.Read.All","Group.ReadWrite.All"
Opens a browser sign-in. You get the intersection of the requested scopes and what your account/role is allowed. Request only the scopes the task needs — they're cached in the token for the session.
2. Device code
Connect-MgGraph -Scopes "User.Read.All" -UseDeviceCode
Prints a code and https://microsoft.com/devicelogin URL; complete sign-in on any other device. Same delegated permissions as interactive.
3. Client secret (app registration)
Requires an app registration with application permissions granted and admin-consented.
$clientId = "00000000-0000-0000-0000-000000000000"
$tenantId = "contoso.onmicrosoft.com"
$clientSecret = ConvertTo-SecureString "<secret-value>" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($clientId, $clientSecret)
Connect-MgGraph -TenantId $tenantId -ClientSecretCredential $credential
Never hardcode the secret — pull it from Key Vault or an environment variable at runtime. Secrets expire (max 2 years); track the rotation date.
4. Certificate-based (app registration)
Upload the certificate's public key to the app registration, keep the private key in the machine's certificate store.
# By thumbprint (cert in CurrentUser\My or LocalMachine\My)
Connect-MgGraph -ClientId $clientId -TenantId $tenantId -CertificateThumbprint "A1B2C3D4E5F6..."
# Or by subject name
Connect-MgGraph -ClientId $clientId -TenantId $tenantId -CertificateSubjectName "CN=graph-automation"
Create a self-signed certificate for this purpose with:
New-SelfSignedCertificate -Subject "CN=graph-automation" -CertStoreLocation "Cert:\CurrentUser\My" `
-KeyExportPolicy NonExportable -KeySpec Signature -KeyLength 2048
Preferred over client secrets: the private key never appears in code or config, and it can be made non-exportable.
5. Managed identity (Azure-hosted only)
# System-assigned managed identity
Connect-MgGraph -Identity
# User-assigned managed identity
Connect-MgGraph -Identity -ClientId "<client-id-of-the-user-assigned-identity>"
Works inside Azure Automation, Functions, App Service, VMs and anywhere else a managed identity is available. No credential exists to rotate or leak. Graph application permissions must be assigned to the identity's service principal first — there is no portal UI for this; grant the app role via Graph itself (for example New-MgServicePrincipalAppRoleAssignment).
Handy follow-ups
Get-MgContext # who am I, which scopes, which auth type
Find-MgGraphCommand -Command Get-MgUser # which permissions does a cmdlet need
Find-MgGraphPermission user.read # search permission names
Disconnect-MgGraph