Identity, Permissions, Tokens, and Automation for Infrastructure Administrators
This course is designed for infrastructure and security administrators who manage Microsoft cloud environments. The focus is on architecture, capabilities, and controls - with enough developer context (token structure, OAuth flows, REST APIs) to reason about security without requiring a development background.
Participants leave with an understanding of how service principals and permissions work under the hood, how to write or evaluate automation using modern credential-free patterns, and practical deployable tools for their own environments.
For the hands-on labs, the attendee machine should have the following tools installed in advance:
azd)Either of the following approaches is acceptable:
Microsoft.Graph moduleMicrosoft.Graph.Authentication, Microsoft.Graph.Users, Microsoft.Graph.Applications, Microsoft.Graph.Identity.SignIns, and Microsoft.Graph.ReportsAz.AccountsAz.KeyVault| Environment | Access Provided | Recommended For |
|---|---|---|
| Provided training environment | Application Administrator in shared Entra training tenant; Contributor on a dedicated Azure resource group; Global Administrator available for consent approvals | Most participants - quickest setup, no risk to personal resources |
| Personal dev/test tenant | Self-managed, M365 Developer Program, or Entra ID P2 Trial tenant with an Azure trial subscription | Participants who want to retain lab artifacts after class; must use a non-production tenant |
No specific Microsoft 365 license tier is required. Features requiring premium licensing - Workload Identities Premium, Entra ID Governance, and Defender for Cloud Apps App Governance - are clearly noted inline where they appear throughout the course.
Build a modern foundation for service identity, permissions, and token-based authentication in Microsoft cloud environments. Understand what goes wrong with legacy patterns - and how to fix it.
Microsoft Entra Applications, Managed Identities, and Workload Authentication
Organizations built around Active Directory typically used ordinary user accounts for service identities - with static passwords, no MFA support, and broad group memberships accumulated over time. Real-world examples still common in enterprise environments: SQL Server service accounts, IIS application pool identities, scheduled tasks, DFS replication, backup agents (Veeam, Commvault), and vulnerability scanners (Tenable, Qualys).
Managed Service Accounts are introduced as the bridge concept: they reduce password management on-premises, but the larger transition is toward workload identities that avoid stored credentials entirely.
Service Principals are the cloud-native equivalent of service accounts in Microsoft Entra. They are not subject to MFA or Conditional Access by default - but they offer authentication methods that are fundamentally stronger than any password-based account.
The section compares the main authentication patterns for service principals: client secrets, certificates, workload identity federation, and managed identities. The emphasis is simple: managed identity is preferred for Azure workloads, workload identity federation is preferred for CI/CD, certificates are situational, and secrets are the weakest option.
When a credential cannot be eliminated, the guidance stays high level: store it in Key Vault, retrieve it at runtime, and treat sign-in logs, credential rotation, and compromise response as separate governance tasks.
The App Registration / Enterprise Application split is a persistent source of confusion - and the wrong ID in a Graph query is a common bug.
| Concept | Where It Lives | What It Controls | Common Use |
|---|---|---|---|
| App Registration | Home tenant only | App identity, redirect URIs, credentials, exposed APIs, app roles | Developer/admin who owns the application |
| Enterprise Application (Service Principal) |
Every consuming tenant | Local consent grants, sign-in logs, Conditional Access targeting, ownership, provisioning | Admin revoking permissions, reviewing sign-ins |
| Application (Client) ID | Shared across both objects | Identifies the app globally | Use in authentication flows; same value in both App Reg and EA |
| Object ID | Different for each object | Identifies a specific tenant object | Use when targeting a specific object in Graph API queries |
Service Principals receive access tokens only - no refresh tokens. Access tokens last approximately 1 hour. This limits token theft blast radius but means automations must cache tokens and handle expiry. Never authenticate on every API call - cache the token and refresh only when it approaches expiry.
Application Administrator can add new credentials to any existing service principal in the tenant - including SPs that already hold permissions granted by a Global Administrator. An App Administrator who adds a credential to an SP holding RoleManagement.ReadWrite.Directory gains effective Global Admin-equivalent access. Treat Application Administrator as a highly privileged role, assign only via PIM with JIT activation, and monitor credential additions in Entra audit logs.
OAuth Permissions, Admin Consent, and Security Attacks
The distinction maps to a familiar concept: delegated permissions are like Kerberos constrained delegation - the app acts on behalf of a signed-in user and cannot exceed what that user is allowed to do. Application permissions are like an unconstrained service account - the app acts as itself with no user context, accessing data across the entire tenant.
| Attribute | Delegated (OAuth2 Scopes) | Application (App Roles) |
|---|---|---|
| User context | Always - limited by signed-in user's access | None - app acts independently |
| Admin consent required? | Depends on scope sensitivity | Always |
| Blast radius | Scoped to user's permissions | Tenant-wide - all data the scope covers |
| Graph object | OAuth2PermissionGrant | appRoleAssignment |
| Least-privilege example | Mail.Read (user's mail only) | Mail.Read reads all tenant mailboxes |
| Example high-risk scope | Files.ReadWrite.All | Directory.ReadWrite.All |
Figure 3 - OAuth 2.0 authorization code flow with admin consent
An attacker registers a malicious multi-tenant app and tricks a user into consenting to it - granting persistent, MFA-bypassing access without stealing a password. Unlike credential theft, revoking access requires explicitly revoking the consent grant.
Defenses: Restrict user consent to verified publishers and low-risk permissions only (or disable entirely). Enable the admin consent workflow. Deploy App Governance anomaly detection in Defender for Cloud Apps.
The attacker initiates a device code authentication request and sends the resulting code to the victim. When the victim enters it at microsoft.com/devicelogin, the attacker receives valid tokens without needing the victim's password or MFA. Microsoft Threat Intelligence has tracked active campaigns (Storm-2372) using this technique since 2024.
If your tenant's Conditional Access policies do not explicitly block device code flow, every user is potentially targetable with no password or MFA required. Block device code flow via Conditional Access authentication flow restrictions for all users except specific named scenarios (e.g., conference room devices on a specific network).
The most dangerous example: the Azure Service Management API (https://management.azure.com/) - the user_impersonation delegated scope grants an application the same Azure subscription management rights as the signed-in user, including RBAC modification, Key Vault secret access, and compute creation. Most permission reviews focus on Graph and miss this entirely.
An application with Azure Service Management / user_impersonation consent from a Global Administrator can manage the organization's entire Azure environment on behalf of that admin. This permission is rarely audited because most tooling focuses on Graph.
A representative attack chain ties the section together: a forgotten application with excessive permissions, a leaked credential, weak ownership, and poor monitoring. The section uses that scenario to show how silent access happens, why Application Administrator is a serious escalation path, and which controls break the chain early.
Get-MgServicePrincipalAppRoleAssignment and Get-MgOauth2PermissionGrant in PowerShell; Microsoft Defender for Cloud Apps App Governance dashboard for a visual inventoryRemove-MgOauth2PermissionGrant; revoking a permission does not revoke existing valid tokensToken Acquisition, IMDS, Microsoft Graph, and Azure Resource Manager
@odata.nextLinkThis section walks through token acquisition with managed identities, including the IMDS endpoint used on Azure compute. The focus is practical troubleshooting: request the right token for the right resource, understand the IMDS protections that matter for SSRF, and use token claims to explain why an API call succeeds or fails.
When automation fails with a 403, inspect the token before anything else. The two critical claims:
roles - lists application permissions granted to the managed identity; if empty, the identity hasn't been granted the app rolescp - lists delegated scopes; only present in delegated tokens, not app-onlyaud - confirms which service the token is scoped to; a Graph token won't work against ARMexp - expiry time; cache tokens and refresh before this time rather than re-authenticating on every callThe outline also briefly distinguishes supported APIs from internal browser-discovered endpoints: Graph, ARM, and supported service tooling are the production surfaces, while undocumented endpoints are useful for investigation but not for durable automation.
Graph is the unified REST API for Microsoft 365 and Entra. Key operational concepts:
/v1.0 for stable features; /beta for capabilities not yet in /v1.0, but Microsoft states the beta version is not supported for production use. See beta version support policy.$filter, $select, $top, $expand - always use $select to request only needed fields@odata.nextLink; automation must loop until this key is absent - a common bug produces silently incomplete compliance reportsRetry-After header; honor the returned delay, and use exponential backoff when a retry interval is not provided| Microsoft Graph | Azure Resource Manager | |
|---|---|---|
| Base URL | https://graph.microsoft.com/ | https://management.azure.com/ |
| Governs | Microsoft 365, Entra, Teams, SharePoint | Azure infrastructure resources |
| Access control | OAuth consent (delegated + application) | Azure RBAC (role assignments) |
| Entra SPs interact via | App role assignments + consent grants | RBAC role assignments at subscription/RG/resource scope |
Apply the identity and permission foundation from Part 1 to real automation workloads - choosing the right platform, writing maintainable code, and deploying solutions as reproducible packages.
Automation Accounts, Logic Apps, Function Apps, and CI/CD
Azure automation platform comparison - choosing the right tool
| Platform | Best For | Auth Pattern | Code Required? | On-Prem Support? | Event-Driven? |
|---|---|---|---|---|---|
| Automation Accounts | Scheduled/on-demand PowerShell & Python runbooks; hybrid on-prem automation | Managed Identity Preferred | Yes - PS/Python | Yes - Hybrid Worker | Webhook only |
| Logic Apps | Low-code orchestration across managed connectors; alert/webhook triggers | Managed Identity Preferred | Optional | Standard tier only | Yes - hundreds of triggers |
| Function Apps | Custom code logic, complex data transformation, high-frequency events | Managed Identity Preferred | Yes - C#/Python/JS/PS | No | Yes |
| Azure DevOps Pipelines | CI/CD for code and infrastructure deployments | WIF Now Default | YAML required | Self-hosted agents | Code events only |
| GitHub Actions | CI/CD and automation workflows; broad trigger support | WIF OIDC Preferred | YAML required | Self-hosted runners | Yes - push/PR/schedule/webhook |
The legacy Automation Account Run As Account (certificate-based service principal) was retired September 30, 2023. Any remaining automation using Run As accounts must be migrated to managed identities immediately. Use system-assigned managed identity for single-account scenarios; user-assigned managed identity where the identity is shared across runbooks or accounts.
WIF is presented as the preferred CI/CD authentication pattern: no stored secrets, a federated trust to GitHub Actions or Azure DevOps, and tightly scoped subject claims so only expected repositories and branches can exchange tokens. The section also calls out Logic App connection objects as credentials to govern and vNet integration plus Private Endpoints as the main network controls for private-resource scenarios.
| Trigger Type | Best Platforms | Common Use Cases |
|---|---|---|
| Scheduled | Automation Accounts, Logic Apps, Function Apps, GitHub Actions | Regular reports, compliance scans, cleanup jobs, daily sync operations |
| Alert & Incident | Logic Apps (Sentinel playbooks), Automation webhooks | Security response automation; Sentinel NRT analytics rules → playbooks within minutes |
| Event-Driven | Logic Apps, Function Apps (Event Grid / Service Bus) | Key Vault expiry notifications, Entra audit events, storage blob created |
| CI/CD Pipeline | Azure DevOps, GitHub Actions | Deploy runbooks, Bicep templates, and policy configurations on code merge |
| HTTP / Webhook | Logic Apps, Function Apps | ITSM integrations, external ticketing systems, consent workflow callbacks |
Source Control, Observability, AI-Assisted Development, and Service Principal Hygiene
All runbooks, Logic App definitions, Function App code, and pipeline YAML should live in a Git repository. Never edit runbooks directly in the Azure portal for production systems - treat the portal as read-only for production code.
The point is straightforward: source control and CI/CD are treated as security requirements, not convenience features, because portal-only edits remove review, testing, and history.
AI-assisted development is covered from a review perspective: remove hardcoded secrets, reduce scopes, add error handling, avoid logging tokens, and request only the Graph fields you actually need.
This section explicitly adds monitoring and alerting so failed jobs, broken permissions, and automation drift surface quickly through Log Analytics, Azure Monitor, and platform-native telemetry.
It closes with service principal hygiene: naming conventions, owners, credential expiry tracking, orphan detection, and inactivity review so automation remains understandable and supportable over time.
ARM Templates, Bicep, and the Azure Developer CLI
azure.yaml, /infra, and /srcazd up commandAzure portal, Azure CLI, Az PowerShell, Bicep, and ARM templates all rely on Azure Resource Manager for management and deployment operations. Understanding ARM as the underlying control plane explains why tokens scoped to management.azure.com are needed for infrastructure automation, and why Azure RBAC (not OAuth consent) governs Azure resource access.
| ARM JSON | Bicep | |
|---|---|---|
| Syntax | Verbose JSON with nested resourceId() functions | Clean DSL with symbolic names, no resourceId() needed |
| Line count (typical) | ~80 lines for a simple Automation Account + MI + role | ~25 lines for the same |
| IDE support | Basic JSON completion | Full IntelliSense, type-safe property completion in VS Code |
| Modules | Linked templates (complex) | First-class module keyword |
| Compilation | Is the wire format | az bicep build compiles to ARM JSON |
| Default for azd | No | Yes |
The comparison stays at the authoring level: ARM JSON is the deployment format, while Bicep is the easier authoring layer that compiles to it and is the default fit for azd-based solutions.
azd bundles infrastructure-as-code (Bicep), application code, and CI/CD pipeline configuration into a single deployable, shareable template. For IT and security professionals, community-built security tools can be deployed with a single command rather than manual resource creation and permission assignment steps.
The template structure is part of the overview: azure.yaml defines the solution, /infra holds the Bicep deployment layer, /src holds application code, and core commands such as azd up, azd pipeline config, and azd down cover deployment, pipeline setup, and teardown.
Representative examples include break-glass Conditional Access exclusion automation, azd-maester as a ready-to-deploy security testing solution, and a Key Vault-backed passkey pattern that reinforces that the vault must be treated as the effective credential store.
Additional lab examples show the same packaging model applied to identity governance, endpoint telemetry, notification workflows, and audit monitoring.
Securing Applications and Automation - Course Outline · Content validated May 2026