Skip to content
AccessLens

Security Tips

Conditional Access for AI Agents: Securing the Next Identity Surface

Microsoft has extended Conditional Access to AI agent identities in Entra ID. Here's what it actually controls, how to set up a block-by-default posture, and how to monitor agent activity without additional tools.

Stephen Devlin · · 7 min read

For years, Conditional Access has been about controlling how people sign in. Users, groups, devices, locations, risk levels. The model has been entirely human-centric, because humans were the only things authenticating.

That's changing. Microsoft has introduced Conditional Access for AI agent identities in Entra ID, currently in public preview. It extends the same policy framework to cover autonomous agents, the kind that authenticate with client credentials, call Graph APIs, process data, and take actions without a human in the loop.

If you've been watching the rapid adoption of Microsoft 365 Copilot, Security Copilot, and custom agents built on Azure AI, you'll understand why this matters. Every one of those agents is a workload identity. And until now, most organisations had no Conditional Access coverage for them at all.

Why This Exists

The problem isn't theoretical. I've seen tenants where dozens of app registrations have been created for various AI integrations, each with different permission scopes, and none of them subject to any Conditional Access policy. They authenticate via client credentials, which means they bypass every policy scoped to "All users". No MFA prompt. No device compliance check. No location restriction. Nothing.

This is the "shadow AI" problem that Microsoft has been talking about. Agents get created by dev teams, connected to third-party platforms, granted API permissions, and left running. Nobody owns them. Nobody reviews their access. And when one gets compromised, there's no policy standing between the attacker and whatever data that agent can reach.

Entra Agent ID introduces a new identity type specifically for AI agents. These sit alongside users and workload identities in the Entra directory, but they're distinct. They have their own sign-in logs, their own risk signals, and now their own Conditional Access targeting.

The Three Identity Types

Microsoft has introduced three new object types under the Agent ID umbrella:

Runtime
Agent Identity
Authenticates, acquires tokens, accesses resources. The service principal equivalent for agents.
Template
Agent Blueprint
Defines permissions and configuration. Similar to app registrations vs service principals.
User Context
Agent User
Nonhuman user identity for agent workflows that need to act within a user's context.

The distinction matters because Conditional Access policies can target agent identities and agent users, but not agent blueprints. Blueprints are design-time objects. They don't authenticate.

What You Can Actually Control

Here's where expectations need to be managed. The current preview supports one grant control: Block.

That's it. No MFA. No device compliance. No approved client app requirements. No session controls. No location conditions.

This makes sense if you think about it. Agents authenticate through client credential flows or federated identity credentials. There's no interactive session. Nobody is sitting at a keyboard to complete an MFA challenge or accept Terms of Use. The traditional Conditional Access controls simply don't apply to nonhuman authentication flows.

What you can do:

  • Block specific agents from accessing specific resources
  • Block all unapproved agents by default and only allow explicitly approved ones
  • Block high-risk agents based on Entra ID Protection risk signals
  • Use report-only mode to evaluate what would happen before enforcing
  • Use custom security attributes to categorise agents and build policies around those categories

The block-by-default pattern is the most operationally useful approach right now. Create a policy that blocks all agent identities, then exclude the ones you've vetted and approved. Anything that shows up in your tenant without going through your approval process gets blocked automatically.

Setting It Up

The setup involves two steps: categorising your agents with custom security attributes, then building policies that reference those attributes.

Step 1: Create Security Attributes

Navigate to Entra admin centre > Protection > Custom security attributes and create an attribute set for agent governance.

A practical setup looks like this:

Recommended Security Attributes
AgentApprovalStatus String: New, In_Review, Approved, Rejected
AgentOwner String: Free text (team or individual responsible)
AgentDataClassification String: Public, Internal, Confidential

Assign the Approved status to any agent identity that has been through your review process. Leave new or unreviewed agents as New.

Step 2: Create the Block-by-Default Policy

Block-by-Default Policy Configuration
Applies to Agents (Preview)
Include All agent identities (Preview)
Exclude Agent identities where AgentApprovalStatus equals Approved
Target resources All resources
Grant Block
State Report-only (validate before enforcing)

This gives you a default-deny posture for agents. Any new agent identity that gets created in your tenant is automatically blocked until someone reviews it and sets its approval status.

Step 3: Block High-Risk Agents

Create a second policy for agents that were previously approved but have been flagged by ID Protection:

High-Risk Agent Block Policy
Applies to Agents (Preview)
Include All agent identities (Preview)
Conditions Agent risk (Preview): High
Grant Block
State Report-only (validate before enforcing)

This catches scenarios where an approved agent's credentials are compromised or its behaviour triggers risk detections.

Monitoring Without Additional Tools

You don't need a SIEM or third-party tool to monitor agent activity. Entra provides the data natively.

Sign-in Logs

Agent sign-ins appear in the Service principal sign-in logs, filtered by agentType. Navigate to Entra admin centre > Monitoring & health > Sign-in logs > Service principal sign-ins.

Where to find agent sign-ins: Agent identities appear in Service principal sign-in logs (filter agentType: agent identity). Agent users appear in Non-interactive user sign-in logs (filter agentType: agent user).

Each entry shows the agent identity, the resource it accessed, the result (success, failure, blocked by policy), and the Conditional Access policies that were evaluated.

Graph API Queries

To pull agent sign-in data programmatically:

GET https://graph.microsoft.com/v1.0/auditLogs/signIns
  ?$filter=signInEventTypes/any(t: t eq 'servicePrincipal')
    and appDisplayName eq 'YourAgentName'

To list all agent identities in your tenant:

GET https://graph.microsoft.com/v1.0/servicePrincipals
  ?$filter=servicePrincipalType eq 'AgentIdentity'

KQL for Log Analytics

If you're shipping Entra logs to a Log Analytics workspace, you can query agent activity with KQL:

AADServicePrincipalSignInLogs
| where TimeGenerated > ago(7d)
| where ServicePrincipalType == "AgentIdentity"
| summarize SignInCount = count(),
    DistinctResources = dcount(ResourceDisplayName),
    BlockedCount = countif(ResultType != "0")
    by ServicePrincipalName, ServicePrincipalId
| order by SignInCount desc

To find agents that were blocked by Conditional Access:

AADServicePrincipalSignInLogs
| where TimeGenerated > ago(7d)
| where ServicePrincipalType == "AgentIdentity"
| where ConditionalAccessStatus == "failure"
| project TimeGenerated, ServicePrincipalName, ResourceDisplayName,
    ConditionalAccessPolicies
| order by TimeGenerated desc

And to detect agents signing in from unexpected locations (useful for identifying compromised credentials):

AADServicePrincipalSignInLogs
| where TimeGenerated > ago(30d)
| where ServicePrincipalType == "AgentIdentity"
| summarize Locations = make_set(Location), LocationCount = dcount(Location)
    by ServicePrincipalName
| where LocationCount > 3
| order by LocationCount desc

Conditional Access Report-Only Results

Before enforcing any agent policy, use report-only mode and review the results in the sign-in logs. Each sign-in entry includes a "Report-only" tab showing what the policy would have done. This is the same workflow you'd use for user-targeted policies, it just applies to agent identities now.

Where AccessLens Fits

If you're managing Conditional Access policies across a tenant (or multiple tenants), you already know the challenge: visibility. You need to understand which policies cover which identities, where the gaps are, and whether new identity types like agents are falling through the cracks.

AccessLens analyses your Conditional Access policies and surfaces exactly this kind of gap. The Gap Analysis engine checks whether your policies cover the identity types in your tenant, including workload identities. If you have agent identities authenticating and no policy targeting them, that shows up as an uncovered surface.

The Policy Matrix gives you a visual map of coverage across identity types, applications, and conditions. You can see at a glance whether your agent identity policies are scoped correctly or whether they're leaving resources exposed.

The Conflict Detection engine catches cases where agent-targeted policies interact with existing workload identity policies in unexpected ways. If you have a broad "block all workload identities" policy and then create a more specific "allow approved agents" policy, the engine will flag the overlap and tell you which policy wins.

And the What-If Simulator lets you test scenarios before you deploy. "What happens if this agent identity tries to access this resource from this location?" You get the answer without having to create the policy, deploy it in report-only, wait for sign-in data, and then review the logs.

It's the difference between managing policies reactively (waiting for something to break, then investigating) and managing them proactively (understanding your coverage before there's an incident).

Practical Recommendations

A few things worth considering as you roll this out:

Start with an inventory. Before creating policies, understand what agent identities already exist in your tenant. Use the Entra admin centre or Graph API to enumerate them. You may find agents you didn't know about.

Default to block. The safest posture is blocking all agent identities and explicitly allowing the ones you've approved. This is the opposite of how most organisations handle workload identities today, and that's precisely why agent identity compromise is a growing risk.

Use custom security attributes for governance. Tagging agents with approval status, owner, and data classification gives you the foundation for granular policies. It also creates an audit trail for who approved what and when.

Monitor report-only before enforcing. This is standard advice for any Conditional Access policy, but it's especially important here because agent workloads can be brittle. Blocking an agent that's running a business-critical automation at 2am on a Saturday is not ideal.

Coordinate with your dev teams. Agents are typically created by developers, not identity admins. If your dev teams are spinning up agents without going through an approval process, your block-by-default policy will break their workflows. Get alignment on the process before enforcing.

What's Still Missing

This is a public preview, and it shows. The grant controls are limited to block. There's no concept of "require a managed identity" or "require federated credentials only" as grant controls, both of which would be more useful than a binary block/allow for most scenarios.

Location conditions aren't supported yet. For agents running in Azure, being able to restrict access to specific Azure regions or IP ranges would add a meaningful layer of control.

And the monitoring story, while functional, requires you to know where to look. Agent sign-ins being split across service principal logs and non-interactive user logs depending on the agent type adds friction to investigation workflows.

These will improve as the feature moves toward general availability. For now, the block-by-default pattern with custom security attributes is the most practical approach.

Share this post
LinkedIn