Streamlining Azure CLI & PowerShell Authentication on Windows 11
Set up a secure and convenient Azure authentication workflow on a Windows 11 machine using Windows Credential Manager and PowerShell profiles.
I recently cleaned up my Windows 11 work machines and did a fresh install, OneDrive and winget made installing tools and pulling down configurations easy, I wanted to clean up how I authenticate with Azure when using the Az CLI and Azure PowerShell. I wanted something that was both secure and convenient for daily use and switching between accounts.
After some experimentation, I landed on a solution that uses Windows Credential Manager with PowerShell profiles to enable seamless authentication for both Az CLI and Azure PowerShell.
The Problem
When working with Azure daily, you need:
- Quick, seamless authentication
- Support for both Az CLI and Azure PowerShell
- Ability to manage multiple service principals
- Security (no plain text secrets lying around)
The Solution: Windows Credential Manager + PowerShell Profile
Instead doing an interactive sign-in or storing secrets in environment variables, I’m using Windows Credential Manager to encrypt and store service principal credentials, then loading them automatically through my PowerShell profile.
Prerequisites: Creating a Service Principal
Before we set up authentication, you’ll need a service principal. Here’s how to create one with contributor permissions:
Using Azure Portal
- Navigate to Azure Active Directory > App registrations > New registration
- Give it a name (e.g., “My-DevOps-SP”) and click Register
- Note the Application (client) ID and Directory (tenant) ID
- Go to Certificates & secrets > New client secret
- Add a description and expiration period, then click Add
- Copy the secret value immediately (you won’t see it again!)
Using Az CLI
1
2
3
4
5
6
7
8
9
10
# Create service principal with Contributor role at subscription level
az ad sp create-for-rbac --name "My-DevOps-SP" --role Contributor --scopes /subscriptions/YOUR_SUBSCRIPTION_ID
# Output will show:
# {
# "appId": "your-client-id",
# "displayName": "My-DevOps-SP",
# "password": "your-client-secret",
# "tenant": "your-tenant-id"
# }
Assigning Permissions
For basic Azure operations, assign the service principal to your subscription:
1
2
3
4
5
# Contributor role (can create/manage resources)
az role assignment create --assignee YOUR_CLIENT_ID --role Contributor --scope /subscriptions/YOUR_SUBSCRIPTION_ID
# Or Reader role (read-only access)
az role assignment create --assignee YOUR_CLIENT_ID --role Reader --scope /subscriptions/YOUR_SUBSCRIPTION_ID
You can also assign roles through the Azure Portal:
- Go to your Subscription > Access control (IAM) > Add role assignment
- Select a role (e.g., Contributor or Reader)
- Search for your service principal name and assign it
Now you have the three values needed: Tenant ID, Client ID, and Client Secret.
Step 1: Store Your Service Principal Credentials
First, let’s create a helper function to securely store service principal profiles. Add this to your PowerShell session by copying and pasting it in:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
function Add-AzureServicePrincipalProfile {
param(
[Parameter(Mandatory)]
[string]$ProfileName,
[Parameter(Mandatory)]
[string]$TenantId,
[Parameter(Mandatory)]
[string]$ClientId,
[Parameter(Mandatory)]
[string]$ClientSecret
)
$azureDir = "$env:USERPROFILE\.azure"
if (-not (Test-Path $azureDir)) {
New-Item -ItemType Directory -Path $azureDir | Out-Null
}
$secureSecret = ConvertTo-SecureString $ClientSecret -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential($ClientId, $secureSecret)
$credPath = "$azureDir\sp-$ProfileName-credential.xml"
$tenantPath = "$azureDir\sp-$ProfileName-tenant.txt"
$credential | Export-Clixml -Path $credPath
Set-Content -Path $tenantPath -Value $TenantId
Write-Host "✓ Profile '$ProfileName' saved successfully" -ForegroundColor Green
}
Now store your service principal(s):
1
2
3
4
5
6
7
8
9
10
11
12
13
# Store your default service principal
Add-AzureServicePrincipalProfile `
-ProfileName "default" `
-TenantId "your-tenant-id" `
-ClientId "your-client-id" `
-ClientSecret "your-client-secret"
# Optional: Store additional profiles for different environments
Add-AzureServicePrincipalProfile `
-ProfileName "production" `
-TenantId "prod-tenant-id" `
-ClientId "prod-client-id" `
-ClientSecret "prod-client-secret"
The credentials are now stored encrypted in ~/.azure/ and can only be accessed by your Windows user account.
Step 2: Configure Your PowerShell Profile
Edit your PowerShell profile, make sure to update the -ProfileName parameter if you used a different name than “default”:
1
notepad $PROFILE
Add the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# ============================================
# Azure Authentication Management
# ============================================
function Connect-AzureServicePrincipal {
param(
[string]$ProfileName = "default"
)
$credPath = "$env:USERPROFILE\.azure\sp-$ProfileName-credential.xml"
$tenantPath = "$env:USERPROFILE\.azure\sp-$ProfileName-tenant.txt"
if ((Test-Path $credPath) -and (Test-Path $tenantPath)) {
$credential = Import-Clixml -Path $credPath
$tenantId = Get-Content -Path $tenantPath
# For Azure PowerShell
Connect-AzAccount -ServicePrincipal -Credential $credential -Tenant $tenantId -WarningAction SilentlyContinue | Out-Null
# For Az CLI
$clientSecret = $credential.GetNetworkCredential().Password
az login --service-principal -u $credential.UserName -p $clientSecret --tenant $tenantId --output none
Write-Host "✓ Connected to Azure as Service Principal ($ProfileName)" -ForegroundColor Green
} else {
Write-Host "✗ Profile '$ProfileName' not found" -ForegroundColor Red
}
}
function Connect-AzureInteractive {
# Sign in with your personal account interactively
Connect-AzAccount -WarningAction SilentlyContinue
az login
Write-Host "✓ Connected to Azure interactively" -ForegroundColor Green
}
function Show-AzureAccounts {
Write-Host "`n=== Azure PowerShell Context ===" -ForegroundColor Cyan
Get-AzContext | Format-List Name, Account, Subscription, Tenant
Write-Host "`n=== Az CLI Account ===" -ForegroundColor Cyan
az account show -o table
}
function Disconnect-Azure {
Disconnect-AzAccount -WarningAction SilentlyContinue | Out-Null
az logout 2>$null
Write-Host "✓ Disconnected from Azure" -ForegroundColor Yellow
}
# Convenient aliases
Set-Alias -Name azsp -Value Connect-AzureServicePrincipal
Set-Alias -Name azint -Value Connect-AzureInteractive
Set-Alias -Name azshow -Value Show-AzureAccounts
Set-Alias -Name azlogout -Value Disconnect-Azure
# Auto-connect with default profile on startup (optional)
Connect-AzureServicePrincipal -ProfileName "default"
Save and close the file, then reload your profile:
1
. $PROFILE
How to Use It
Automatic Sign-In
If you leave the last line uncommented, when you launch PowerShell, you’re automatically authenticated to Azure with your default service principal. Both Az CLI and Azure PowerShell are ready to go.
Manual Sign-In with Different Profiles
1
2
3
4
5
# Use default profile
azsp
# Use specific profile
azsp -ProfileName "production"
Switch to Interactive Login
Need to use your personal account instead?
1
2
3
4
5
# Sign out from service principal
azlogout
# Sign in interactively
azint
Check Current Account
1
azshow
Switch Subscriptions
1
2
3
4
5
# Azure PowerShell
Set-AzContext -Subscription "subscription-name"
# Az CLI
az account set --subscription "subscription-name"
Why This Approach?
Security: Credentials are encrypted by Windows and only accessible to your user account. No plain text secrets in files or environment variables.
Convenience: Automatic authentication on PowerShell startup means you’re always ready to work.
Flexibility: Easy switching between multiple service principals or interactive login.
One Solution: Works seamlessly with both Az CLI and Azure PowerShell Module.
Quick Command Reference
| Command | Description |
|---|---|
azsp | Connect with default service principal |
azsp -ProfileName "prod" | Connect with specific profile |
azint | Interactive login (personal account) |
azshow | Show current account info |
azlogout | Sign out completely |
Wrapping Up
Setting up a new machine is always an opportunity to improve your workflows. This authentication setup has made my daily Azure work much smoother.
If you’re setting up Azure authentication on Windows, give this approach a try. Your future self (and your security team) will thank you.
Have questions or suggestions? Feel free to reach out or leave a comment below!