Skip to content

Authentication

Michael Zanatta edited this page Aug 19, 2026 · 4 revisions

Authentication Guide

AzureDevOpsDscNative supports multiple authentication methods for connecting to Azure DevOps. Authentication is configured by calling New-AzDoAuthenticationProvider before running any DSC resources. This guide covers all available options.

Prerequisites

AZDODSC_CACHE_DIRECTORY Environment Variable

This environment variable must be set before calling New-AzDoAuthenticationProvider. The function throws immediately if it is absent:

$ENV:AZDODSC_CACHE_DIRECTORY = 'C:\ProgramData\AzureDevOpsDsc'  # Windows
$ENV:AZDODSC_CACHE_DIRECTORY = '/var/lib/azuredevopsdsc'         # Linux / macOS

This directory is used to persist the module's credential cache (ModuleSettings.clixml) and security descriptor cache (SecurityDescriptors.clixml). The directory must already exist and be writable by the account running the DSC configuration.

When using the Dsc.PipelineRunner companion project, Invoke-DscPipelineRunner reads this variable and configures it automatically — see Pipeline Runner Configuration for details.


Supported Authentication Methods

  1. Personal Access Token (PAT) — Most common and flexible
  2. Managed Identity — Best for Azure-hosted resources
  3. Service Principal (Client Secret) — For service-to-service authentication
  4. Service Principal (Certificate) — More secure alternative to client secrets
  5. Azure CLI Token — Use an existing az login session
  6. Workload Identity Federation — Keyless authentication for CI/CD pipelines

Personal Access Token (PAT)

Personal Access Tokens are scoped credentials tied to a specific Azure DevOps user account.

Creating a PAT

  1. In Azure DevOps, click your profile icon (top right)
  2. Select Personal access tokens
  3. Click New Token
  4. Configure:
    • Name: Give the token a meaningful name
    • Organization: Select your organisation
    • Expiration: Set an expiration (30, 60, or 90 days, or custom)
    • Scopes: Select the required scopes (typically "Full access" for DSC operations)
  5. Click Create and copy the token immediately — you will not see it again

Configuring PAT Authentication

# Plain-text PAT (suitable for interactive or test scripts)
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -PersonalAccessToken 'my-pat-token-here'

# SecureString PAT (preferred for production — avoids storing the plain-text value in memory)
$SecureStringPAT = Read-Host -Prompt 'Enter your PAT' -AsSecureString
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -SecureStringPersonalAccessToken $SecureStringPAT

# Skip the initial connectivity verification check (useful in CI environments)
# Note: -NoVerify is only available with -PersonalAccessToken, not -SecureStringPersonalAccessToken
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -PersonalAccessToken 'my-pat-token-here' -NoVerify

Note: The -NoVerify switch is not available when using -SecureStringPersonalAccessToken. The SecureString PAT path always skips connectivity verification.

Best Practices for PAT

  • Store the PAT in a secure location (Azure Key Vault, Windows Credential Manager, PowerShell SecretStore)
  • Use the minimum required scopes
  • Set a reasonable expiration date (30–90 days) and rotate regularly
  • Never commit a PAT to version control or hardcode it in a script

Managed Identity

Managed Identity is the recommended approach when running DSC configurations on Azure resources (Virtual Machines, Azure Arc-enabled servers, Azure Automation, etc.). No credentials or secrets need to be stored — the identity is provided by the Azure platform.

Prerequisites

  • The hosting resource must have a System-assigned or User-assigned Managed Identity enabled
  • The Managed Identity must be added to the Azure DevOps organisation with appropriate permissions

Configuring Managed Identity Authentication

# Authenticate using the Managed Identity assigned to the current Azure resource
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useManagedIdentity

# Skip the initial connectivity verification check
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useManagedIdentity -NoVerify

Best Practices for Managed Identity

  • Prefer System-assigned identity when only one resource needs access
  • Apply the principle of least privilege — grant the minimum permissions required
  • No token rotation is needed; tokens are issued and refreshed by the Azure platform
  • Audit identity access regularly

Service Principal (Client Secret)

Service Principals are ideal for non-Azure environments, CI/CD pipelines, and cross-tenant scenarios where Managed Identity is not available.

Prerequisites

  • An Azure AD App Registration with a Client Secret
  • The Service Principal (Enterprise Application) must be added to the Azure DevOps organisation with appropriate permissions via Access Control

Configuring Service Principal Authentication

# Plain-text client secret
New-AzDoAuthenticationProvider `
    -OrganizationName 'my-organization' `
    -TenantId         '00000000-0000-0000-0000-000000000000' `
    -ClientId         'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -ClientSecret     'my-client-secret-value'

# SecureString client secret (preferred for production)
$SecureSecret = Read-Host -Prompt 'Enter client secret' -AsSecureString
New-AzDoAuthenticationProvider `
    -OrganizationName           'my-organization' `
    -TenantId                   '00000000-0000-0000-0000-000000000000' `
    -ClientId                   'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -SecureStringClientSecret   $SecureSecret

# Skip the initial connectivity verification check
New-AzDoAuthenticationProvider `
    -OrganizationName 'my-organization' `
    -TenantId         '00000000-0000-0000-0000-000000000000' `
    -ClientId         'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -ClientSecret     'my-client-secret-value' `
    -NoVerify

Best Practices for Service Principal

  • Store client secrets in Azure Key Vault or PowerShell SecretStore — never in code or config files
  • Rotate secrets regularly
  • Prefer certificate-based authentication (see below) for higher-security scenarios
  • Grant minimal required permissions

Service Principal (Certificate)

Certificate-based authentication is more secure than client secrets because private keys never leave the machine and certificates can be stored in the Windows Certificate Store or as PFX files.

Prerequisites

  • An Azure AD App Registration with an uploaded certificate (public key)
  • The private key must be available on the machine running DSC (certificate store or PFX file)
  • The Service Principal must be added to the Azure DevOps organisation with appropriate permissions

Configuring Certificate Authentication

# ── Windows certificate store (thumbprint) ──────────────────────────────────
# The certificate must be present in the local machine or current user certificate store.
New-AzDoAuthenticationProvider `
    -OrganizationName        'my-organization' `
    -TenantId                '00000000-0000-0000-0000-000000000000' `
    -ClientId                'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -CertificateThumbprint   'AABBCCDDEEFF00112233445566778899AABBCCDD'

# ── PFX file (cross-platform — Linux, macOS, and Windows) ───────────────────
$CertPassword = Read-Host -Prompt 'Enter PFX password' -AsSecureString

New-AzDoAuthenticationProvider `
    -OrganizationName    'my-organization' `
    -TenantId            '00000000-0000-0000-0000-000000000000' `
    -ClientId            'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -CertificatePath     '/etc/azdo-dsc/auth.pfx' `
    -CertificatePassword $CertPassword

# Skip the initial connectivity verification check (either mode)
New-AzDoAuthenticationProvider `
    -OrganizationName        'my-organization' `
    -TenantId                '00000000-0000-0000-0000-000000000000' `
    -ClientId                'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -CertificateThumbprint   'AABBCCDDEEFF00112233445566778899AABBCCDD' `
    -NoVerify

Best Practices for Certificates

  • Store the private key securely — Windows Certificate Store (LocalMachine\My) or a protected PFX file
  • Monitor certificate expiration and rotate before it expires
  • Use a unique certificate per environment (Dev/Staging/Production)
  • Do not share certificates across service principals

Azure CLI Token

Acquires a Bearer token from an existing az login session without requiring any additional credentials. Particularly useful for local development and interactive sessions.

Prerequisites

  • The Azure CLI must be installed and available in PATH
  • You must be signed in: run az login (or az login --use-device-code in headless environments)
  • The signed-in account must have access to the Azure DevOps organisation
  • Run az account show to verify the active context; use az account set --subscription <id> to switch

Configuring Azure CLI Authentication

# Authenticate using the active Azure CLI session
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useAzureCLI

# Skip the initial connectivity verification check
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -useAzureCLI -NoVerify

Best Practices for Azure CLI

  • Suitable for local development and interactive sessions
  • Token is automatically refreshed by the CLI; no manual credential management required
  • Not recommended for automated/unattended scenarios — use a Service Principal or Managed Identity instead
  • Only works on machines with the Azure CLI installed

Workload Identity Federation

Keyless authentication for GitHub Actions, Kubernetes/AKS, Azure DevOps Pipelines, and any OIDC-compliant system. A short-lived JWT issued by the external identity provider is exchanged for an Azure AD access token — no client secret or certificate is required on the App Registration.

Three token sources are supported:

Mode Description
File-based Token is read from a projected file path (Kubernetes/AKS Workload Identity)
GitHub Actions OIDC Token is requested from the GitHub Actions runtime endpoint automatically
Manual token Caller supplies a federated JWT obtained from another OIDC source

Prerequisites

  • An Azure AD App Registration with a Federated Identity Credential configured for the appropriate issuer and subject
  • The Service Principal must be added to the Azure DevOps organisation with required permissions

Configuring Workload Identity Federation

# ── 1. File-based token (Kubernetes / AKS Workload Identity) ─────────────────
# AKS projects the service-account token at the path in AZURE_FEDERATED_TOKEN_FILE.
New-AzDoAuthenticationProvider `
    -OrganizationName    'my-organization' `
    -TenantId            '00000000-0000-0000-0000-000000000000' `
    -ClientId            'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -FederatedTokenFile  $ENV:AZURE_FEDERATED_TOKEN_FILE

# Hard-coded file path variant
New-AzDoAuthenticationProvider `
    -OrganizationName    'my-organization' `
    -TenantId            '00000000-0000-0000-0000-000000000000' `
    -ClientId            'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -FederatedTokenFile  '/var/run/secrets/azure/tokens/azure-identity-token'

# ── 2. GitHub Actions OIDC ────────────────────────────────────────────────────
# The workflow must grant `id-token: write` permission.
# ACTIONS_ID_TOKEN_REQUEST_URL and ACTIONS_ID_TOKEN_REQUEST_TOKEN are injected
# automatically by GitHub Actions when that permission is present.
#
# GitHub Actions workflow snippet:
#   permissions:
#     id-token: write
#     contents: read
New-AzDoAuthenticationProvider `
    -OrganizationName       'my-organization' `
    -TenantId               '00000000-0000-0000-0000-000000000000' `
    -ClientId               'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -useGitHubActionsOIDC

# Custom audience (must match the federated identity credential audience in Azure AD)
New-AzDoAuthenticationProvider `
    -OrganizationName       'my-organization' `
    -TenantId               '00000000-0000-0000-0000-000000000000' `
    -ClientId               'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -useGitHubActionsOIDC `
    -GitHubActionsAudience  'api://AzureADTokenExchange'

# ── 3. Manually-supplied federated token ─────────────────────────────────────
# Use when the OIDC token has already been acquired externally (e.g. Azure DevOps
# Pipelines OIDC service connection) and is available as a variable.
$FederatedJWT = $ENV:SYSTEM_OIDCTOKEN | ConvertTo-SecureString -AsPlainText -Force

New-AzDoAuthenticationProvider `
    -OrganizationName  'my-organization' `
    -TenantId          '00000000-0000-0000-0000-000000000000' `
    -ClientId          'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -FederatedToken    $FederatedJWT

# ── Skip connectivity verification (any mode) ─────────────────────────────────
New-AzDoAuthenticationProvider `
    -OrganizationName    'my-organization' `
    -TenantId            '00000000-0000-0000-0000-000000000000' `
    -ClientId            'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' `
    -FederatedTokenFile  '/var/run/secrets/azure/tokens/azure-identity-token' `
    -NoVerify

Best Practices for Workload Identity

  • No secrets stored in CI/CD — tokens are short-lived and issued on demand
  • Recommended for modern CI/CD systems (GitHub Actions, Azure DevOps Pipelines, AKS)
  • Manually-supplied tokens are not automatically refreshed; call New-AzDoAuthenticationProvider again with a fresh token when the current one expires

Storing Credentials Securely

Before passing credentials to New-AzDoAuthenticationProvider, retrieve them from a secure store rather than hardcoding them.

Option 1: Azure Key Vault

# Retrieve PAT from Key Vault
$token = (Get-AzKeyVaultSecret -VaultName 'MyKeyVault' -Name 'AzureDevOpsPAT').SecretValue
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -SecureStringPersonalAccessToken $token

Option 2: PowerShell SecretStore

# Install SecretStore module
Install-Module Microsoft.PowerShell.SecretStore

# Store credential (one-time setup)
Set-Secret -Name AzureDevOpsPAT -Secret 'your-pat-token' -Vault SecretStore

# Retrieve in script
$token = Get-Secret -Name AzureDevOpsPAT -AsPlainText
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -PersonalAccessToken $token

Option 3: Windows Credential Manager (Windows only)

# Store PAT in Credential Manager (one-time setup)
$cred = New-Object System.Management.Automation.PSCredential(
    'AzureDevOpsDsc',
    (ConvertTo-SecureString 'your-pat-token' -AsPlainText -Force)
)
$cred | Export-Clixml -Path "$env:APPDATA\AzureDevOpsDsc\cred.xml"

# Retrieve in script
$cred = Import-Clixml -Path "$env:APPDATA\AzureDevOpsDsc\cred.xml"
New-AzDoAuthenticationProvider -OrganizationName 'my-organization' -SecureStringPersonalAccessToken $cred.Password

Choosing the Right Authentication Method

Method Best For Pros Cons
PAT Local dev, general use Simple, no Azure AD required Requires token management and rotation
Managed Identity Azure VMs, Arc, Automation No credentials to manage, secure Azure-hosted resources only
Service Principal (secret) CI/CD, on-premises automation Works anywhere Secret management required
Service Principal (cert) High-security scenarios More secure than secrets More complex certificate lifecycle
Azure CLI Local development Automatic, uses existing login Not suitable for automation
Workload Identity GitHub Actions, AKS, ADO Pipelines Keyless, short-lived tokens Requires OIDC federation setup

Troubleshooting Authentication

"Authentication Failed"

Verify the token or credentials are correct and have not expired. For PAT, check that the token still exists in Azure DevOps and has the required scopes.

"Insufficient Permissions"

The authenticated identity lacks the necessary permissions in Azure DevOps:

  • Check group memberships and permission assignments for the identity
  • For PAT, review the token scopes (Full access or specific scopes required)

"Token Expired"

  • PAT: Create a new token in Azure DevOps
  • Service Principal secret: Rotate the secret in Azure AD
  • Azure CLI: Re-run az login
  • Workload Identity (manual): Acquire a fresh federated token

Module or Resource Not Found

# Verify the module is installed
Get-Module -ListAvailable | Where-Object Name -eq AzureDevOpsDscNative

# Import explicitly if needed
Import-Module -Name AzureDevOpsDscNative

Security Checklist

  • Use the minimum required permissions for the authenticated identity
  • Store all credentials in a secure vault — never in code or config files
  • Set expiration dates on PATs and rotate them regularly
  • Rotate service principal secrets before they expire
  • Monitor authentication logs and audit access regularly
  • Revoke unused credentials and service principals
  • Use MFA for personal accounts (PAT is tied to the user account)
  • Prefer Managed Identity or Workload Identity over long-lived secrets where possible

Commands

Resources

Clone this wiki locally