Skip to main content
The Microsoft 365 provider supports authentication using Azure DevOps Pipelines’ OpenID Connect (OIDC) tokens. This approach allows Terraform to authenticate to Microsoft 365 services directly from Azure DevOps pipelines without storing long-lived credentials as pipeline variables or service connections.

How Azure DevOps OIDC Works

1

Token Generation

Azure DevOps Pipelines generates a short-lived OIDC token for each pipeline run
2

Token Request

The Microsoft 365 provider requests this token during Terraform execution
3

Present Token

The provider presents the token to Microsoft Entra ID
4

Trust Relationship

Based on a pre-configured trust relationship, Entra ID issues a Microsoft Graph access token
5

API Calls

The provider uses this token to authenticate API requests

Prerequisites

  • An Azure DevOps organization and project
  • Permissions to create and configure app registrations in Microsoft Entra ID
  • Ability to modify Azure DevOps pipelines
  • Permissions to create service connections in Azure DevOps

Setup

1

Create App Registration

# Set variables
TENANT_ID="00000000-0000-0000-0000-000000000000"
APP_NAME="terraform-m365-provider"

# Create app registration
APP_ID=$(az ad app create --display-name $APP_NAME --query appId -o tsv)

# Create service principal
az ad sp create --id $APP_ID

# Grant API permissions
az ad app permission add \
  --id $APP_ID \
  --api 00000003-0000-0000-c000-000000000000 \
  --api-permissions 9241abd9-d0e6-425a-bd4f-47ba86e767a4=Role

# Grant admin consent
az ad app permission admin-consent --id $APP_ID
2

Create Service Connection

In your Azure DevOps project:
  1. Go to Project settings > Service connections
  2. Click New service connection > Azure Resource Manager
  3. Select Workload Identity federation (manual)
  4. Fill in:
    • Service connection name: e.g., “M365Provider”
    • Subscription ID: Your Azure subscription ID
    • Tenant ID: Your Microsoft Entra ID tenant ID
    • Service principal client ID: The app registration client ID
    • Issuer: Your Azure DevOps org URL
    • Subject: Service connection identifier
3

Configure Federated Credential

# Set variables
ADO_ORG="your-azure-devops-org"
ADO_PROJECT="your-azure-devops-project"
SERVICE_CONNECTION_NAME="M365Provider"

# Create federated credential
az ad app federated-credential create \
  --id $APP_ID \
  --parameters "{\"name\":\"ado-federated-credential\",\"issuer\":\"https://vstoken.dev.azure.com/${ADO_ORG}\",\"subject\":\"sc://${ADO_ORG}/${ADO_PROJECT}/${SERVICE_CONNECTION_NAME}\",\"audiences\":[\"api://AzureADTokenExchange\"]}"

Azure DevOps Pipeline Configuration

trigger:
- main

pool:
  vmImage: ubuntu-latest

variables:
  serviceConnectionId: 'M365Provider'
  
steps:
- task: TerraformInstaller@0
  inputs:
    terraformVersion: 'latest'

- task: TerraformTaskV3@3
  displayName: 'Terraform init'
  inputs:
    provider: 'azurerm'
    command: 'init'
    backendServiceArm: '$(serviceConnectionId)'
    backendAzureRmResourceGroupName: 'your-resource-group'
    backendAzureRmStorageAccountName: 'your-storage-account'
    backendAzureRmContainerName: 'tfstate'
    backendAzureRmKey: 'terraform.tfstate'

- task: TerraformTaskV3@3
  displayName: 'Terraform apply'
  inputs:
    provider: 'azurerm'
    command: 'apply'
    environmentServiceNameAzureRM: '$(serviceConnectionId)'
  env:
    M365_TENANT_ID: '$(tenantId)'
    M365_AUTH_METHOD: 'oidc_azure_devops'
    M365_CLIENT_ID: '$(clientId)'
    M365_ADO_SERVICE_CONNECTION_ID: '$(serviceConnectionId)'

Provider Configuration

Required Pipeline Environment Variables

Azure DevOps automatically sets the following environment variables required for OIDC authentication:
  • SYSTEM_ACCESSTOKEN: Token used to authenticate to Azure DevOps services
  • SYSTEM_OIDCREQUESTURI: URI to request OIDC tokens
These variables are automatically available to your Terraform commands in most tasks.

Security Best Practices

Pipeline Conditions

Restrict which branches or paths can trigger the pipeline

Approval Gates

Use environments with approval gates for sensitive operations

Conditional Access

Configure additional conditions in Microsoft Entra ID

Least Privilege

Grant only minimum required API permissions

Troubleshooting

Verify the federated credential is configured correctly in Entra ID with matching issuer and subject values.
Check the service connection configuration in Azure DevOps. Ensure it’s properly configured for workload identity federation.
Ensure you’ve granted admin consent for the required Microsoft Graph permissions in your app registration.
Verify that SYSTEM_ACCESSTOKEN and SYSTEM_OIDCREQUESTURI are set and accessible in your pipeline. Some custom tasks may not pass these through automatically.
Double-check that the subject and issuer values match between Azure DevOps and the federated credential in Entra ID.

Build docs developers (and LLMs) love