By the end of this sheet, a user who signed in this morning with a password and an Authenticator push cannot become Global Administrator without touching a security key. The activation is bound to an authentication context, a Conditional Access policy demands a phishing-resistant credential against that context, the emergency access accounts are excluded, and you have watched the step-up happen and found it in the sign-in log. This is the highest-value change in the wave.
Before you start
You need Microsoft Entra ID P2 or Microsoft Entra ID Governance for the PIM side, and Conditional Access, which means P1 as a floor. You need at least Privileged Role Administrator to edit role settings and Conditional Access Administrator or Security Administrator to create the policy. You need the work from the earlier build sheet done, so Global Administrator is already held eligible with deliberate settings. You need at least two emergency access accounts in a dedicated exclusion group, configured as the role-model article describes, because you are about to build a policy that could otherwise lock the tenant. And you need at least one real phishing-resistant credential registered on the test account before you begin, which is the subject of Step 1 and is not optional.
One statement of provenance, because this is a security control and you should know how much to trust the description. Everything in this sheet is verified against current Microsoft documentation, and the configuration is exactly what Microsoft prescribes. The precise on-screen sequence of the first activation, the exact shape of the resulting sign-in log entry, and the behaviour of the fallback under each of its documented non-trigger conditions are described here from the documentation rather than from my own tenant. Where I am reasoning rather than reporting, I say so in the text. A lab pass on a P2 tenant with a physical key is a credibility upgrade I intend to make, and I would rather tell you which parts are which than let you assume.
Step 1: Register the credentials first, or strand your administrators
Do this before anything else. The phishing-resistant strength admits exactly three things: Windows Hello for Business or platform credential, FIDO2 security key, and Microsoft Entra certificate-based authentication (multifactor). Nothing else qualifies. An Authenticator push does not. A text message does not. A voice call does not. A one-time passcode does not.
Every administrator who will be eligible for the gated role needs at least one of those three registered, and here is why the ordering is not negotiable. An authentication strength never constrains the first-factor sign-in, only the step-up. So an administrator whose only phishing-resistant method is Windows Hello for Business, who signed in this morning with a password, hits a wall at the challenge: Microsoft’s documented remedy is that the user must restart the session, select sign-in options, and choose a method the strength requires. That is a dead end discovered mid-task by someone who is trying to fix something, and it is the single most likely reason this project gets rolled back.
Prefer a FIDO2 security key for the administrator population, precisely because it is portable across sign-in surfaces and does not depend on which machine the person happens to be at. Register two per administrator, for the same reason you buy two of anything that can be left in a taxi. Verify registration before you continue, and treat an administrator without a registered method as not yet in scope rather than as a problem to solve later.
Step 2: Create and publish the authentication context
Go to Entra ID, then Conditional Access, then Authentication context, and select New authentication context.
| Setting | Value | Why |
|---|---|---|
| Display name | Privileged Role Activation | Name it for the act, not for the role or the policy. One context can gate several roles, and a name tied to Global Administrator will be wrong within a month. This string shows up when somebody else is choosing a context in a hurry, so it should tell them what it is for. |
| Description | Step-up required to activate a privileged Entra role. Enforced by the activation Conditional Access policy. | The link from context to policy is not discoverable from the context object. Write it down here or nobody will find it. |
| Publish to apps | Checked | Unpublished, the context is unavailable to downstream resources and will not appear where you need to select it. This is the checkbox people miss and then spend twenty minutes wondering why the context is not in the PIM dropdown. |
| ID | Read-only, assigned for you | You do not choose it and you should record it, because this is the value that appears in the token claim and in every script and error message from here on. Note the documentation is inconsistent about the ceiling, describing the range as running to c99 in the portal guidance and to c25 in the Graph reference, so do not build anything that assumes the high end exists. |
Deletion is blocked while a context is published or referenced by a policy, which is a helpful guard rather than an obstacle. If you need to remove one later, unpublish it and unlink the policies first.
Step 3: Build the Conditional Access policy, and enable it before you touch PIM
Ordering is documented and it is not stylistic: create and enable the Conditional Access policy for the authentication context before the authentication context is configured in PIM settings. Do it in that order.
Give the policy a name that says plainly what it does. I name this one PIM Activation - Global Admin - Phishing-Resistant. This is a standalone Conditional Access policy you create for the PIM activation pattern: it is not part of the VCIO CA Framework repo and it does not modify anything in it. Naming it descriptively rather than borrowing the framework’s numbering keeps the two cleanly separate, which is what you want when one of them is infrastructure as code and the other is a pattern you are adding alongside it.
| Setting | Value | Why |
|---|---|---|
| Users, Include | The group containing your eligible administrators, or All users | Scope by who the person is, never by the privilege they are requesting. See the exclusion note below, which is the more important half of this row. |
| Users, Exclude | EmergencyAccess (the break-glass group) | Mandatory. The emergency accounts hold Global Administrator permanently and never activate anything, so this policy can only ever harm them. Excluding them costs you nothing and not excluding them is how a tenant becomes unrecoverable. |
| Target resources | Select what this policy applies to = Authentication context, then tick Privileged Role Activation | This is what makes the policy fire on an act rather than on an application. Do not also add a directory role to this policy: during activation the user does not hold the role yet, so a policy scoped that way would never apply. |
| Grant | Grant access > Require authentication strength > Phishing-resistant MFA strength | The whole point. Note you cannot also tick Require multifactor authentication in the same policy: the two grant controls are mutually exclusive, because the built-in multifactor strength is the equivalent of the older control. |
| Session | Sign-in frequency = Every time | Microsoft’s documented way to force reauthentication on every activation. Without it, the ten-minute reauthentication window means a second activation shortly after the first prompts nothing. Expect two nuances: Every time means full reauthentication when the session is evaluated, and the platform tolerates five minutes of clock skew so nobody is prompted more than once every five minutes. |
| Enable policy | On | Not report-only. This is the one policy where report-only is actively harmful, for the reason in the failure modes below. If you need a staged rollout, stage it by narrowing the user scope, not by weakening the policy state. |
That last row deserves its own sentence because it contradicts good general practice. Everywhere else in Conditional Access work, including my own testing doctrine, report-only is the correct first move. Here it is not, and the reason is structural rather than a matter of taste. It is explained in full under failure modes, and if you read nothing else in this article, read that.
Step 4: Wire the role to the context
Now, and only now, go to ID Governance, then Privileged Identity Management, then Microsoft Entra roles, then Roles. Select Global Administrator, open Role settings, and choose Edit.
| Setting | Value | Why |
|---|---|---|
| On activation, require | Microsoft Entra Conditional Access authentication context, then select Privileged Role Activation | Replaces the multifactor option, which reused the morning’s claim. This one issues a real claims challenge that your policy answers. |
| Activation maximum duration | 1 hour (unchanged) | Keep what the earlier sheet set. Nothing here argues for a longer window; if anything, a stronger gate makes a short window easier to defend because re-activating is now a meaningful act rather than a formality. |
| Require approval to activate | Yes, unchanged | Keep it. The step-up proves who is asking; approval proves somebody else agrees they should. They answer different questions, and Microsoft specifically recommends approval on Global Administrator activation because compromised credentials otherwise allow near-instant escalation. |
Repeat for the other roles that deserve it. Privileged Role Administrator is the obvious second, since it can rewrite these settings. Security Administrator is the obvious third, since it can rewrite the policy. One context serves all of them; you do not need a context per role, and you should resist making one, because the operational value of these objects falls off sharply once there are more than a few.
Step 5: The second policy, for using the role rather than getting it
The context gates activation only. Once the role is active it is active on the account, and the user can carry on from a different browser, device or location. Microsoft’s own example is a user who activates from an Intune-compliant device and then uses the role from a machine that is not compliant.
The documented fix is a second policy, and it is a different shape from the first: create PIM - Privileged Role Use targeting Directory roles rather than an authentication context, scoped to the privileged roles you care about, granting on the same phishing-resistant strength and, if your estate supports it, requiring a compliant or hybrid-joined device. Exclude the same break-glass group. This is the policy that says what must be true while somebody is holding the role, as opposed to what must be true to pick it up.
This is where scoping to a directory role is correct and expected, which is worth stating clearly because it is the exact thing Step 3 forbade. The difference is timing: in this policy the user already holds the role, so the condition can match. In the activation policy they do not, so it cannot.
Step 6: The end-to-end test, which is the worked example
The scenario is deliberately the ordinary one. Priya is a standing User Administrator. She signs in at the start of her day with her password and an Authenticator push, which satisfies multifactor authentication and is not phishing-resistant. She is eligible for Global Administrator. Mid-morning a tenant-level change needs making, so she goes to elevate.
She opens Privileged Identity Management, then My roles, then Microsoft Entra roles, and selects Activate on Global Administrator. Because the role is bound to the context and her session token carries no claim for it, she is shown the documented banner: A Conditional Access policy is enabled and may require additional verification. Click to continue. She continues, and is redirected into Entra sign-in, where PIM Activation - Global Admin - Phishing-Resistant evaluates. It requires the phishing-resistant strength. Her password-plus-push session does not satisfy it, so she is prompted for a method that does, and she taps her security key. The token comes back carrying the claim, and she is returned to complete the activation: duration, justification, ticket. The request then goes to approval, and an approver clears it as in the earlier sheet.
Two variants are worth running while you are set up, because they teach different things. Have Priya sign in fresh with the security key as her first factor and then activate: the strength is already satisfied, so with sign-in frequency set to Every time she should still face a fresh interactive challenge, and that is the setting earning its place. Then have her activate a second eligible role within ten minutes of the first: she should not be challenged again, because that is the documented reauthentication window doing exactly what it is meant to do.
Now collect the evidence, in two places. In Entra ID > Monitoring & health > Sign-in logs, find the step-up sign-in that happened between the banner and the activation, and open it. The Conditional Access tab should show PIM Activation - Global Admin - Phishing-Resistant as applied and satisfied, and the authentication details should show the phishing-resistant method rather than the push she used that morning. Then in the audit log, filter Service to PIM and confirm the same trio the earlier sheet taught: Add member to role requested (PIM activation), the approval event, and Add member to role completed (PIM activation).
The pass condition is a single sentence: the sign-in log shows a phishing-resistant authentication that occurred after the workday’s original sign-in and immediately before the activation. If you cannot find that entry, the step-up did not happen, and something in the chain is wrong regardless of how correct the configuration looks. Note honestly that the precise field layout of that log entry, including which resource the step-up is recorded against, is something I am describing from the documented flow rather than from a capture of my own; the presence of the phishing-resistant method on a fresh sign-in immediately before the activation is the durable thing to look for.
Failure modes to test deliberately
The exclusion that removes the gate. This is the one that matters. Microsoft built a fallback: if there are no Conditional Access policies in the tenant targeting the authentication context configured in PIM, then activation falls back to requiring ordinary multifactor authentication. But the documentation is explicit that this fallback is not triggered if the policy is turned off, is in report-only mode, or has an eligible user excluded from it. Microsoft states those non-trigger conditions and stops there; the conclusion is mine, and it is this: for a user in any of those three states, there is a policy targeting the context so the fallback stays asleep, and the policy is not enforcing anything on them, so the activation proceeds with no step-up and no ordinary multifactor challenge either. A misconfigured exclusion is worse than never having built this.
Test it rather than trusting my reasoning or Microsoft’s silence. Put a test account into the exclusion group, have it activate, and watch what it is asked for. Then take it out. Do the same with the policy flipped to report-only, and put it back. Ten minutes of testing tells you whether your tenant behaves the way this paragraph says, and the answer determines whether your break-glass exclusion is a safety measure or a hole.
The Windows Hello dead end. An administrator with only Windows Hello for Business registered, signed in with a password, cannot satisfy the strength in that session and must restart it and choose a different sign-in option. Reproduce it once on a test account so that your service desk has seen it, because the user-facing symptom looks like a broken policy rather than a registration gap.
Activation from Graph or PowerShell stops working. Once a role is bound to an authentication context, activating it with New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest fails, because the interactive Graph token carries no claim for the context. The error is RoleAssignmentRequestAcrsValidationFailed, and you should know that this code appears nowhere in Microsoft’s documentation: the only published PIM error table lists role-assignment-exists and a family of policy-validation failures, with no authentication-context entry at all. The behaviour is community-documented and there are open issues against both the Az and Microsoft Graph PowerShell SDKs that have sat unresolved for around two years.
The workaround, credited to Trevor Jones at smsagent.blog, is to acquire your own access token that carries the claim and hand it to Connect-MgGraph. It is two requests rather than one: the acrs claim is requested on the authorization call, and the client-capabilities claim xms_cc with value cp1 is requested separately on the token call. A later independent write-up from December 2025 does the same job through MSAL directly and succeeds using acrs alone with no client-capabilities claim at all, so whether xms_cc is still required is genuinely unsettled and I will not tell you it is mandatory. If you are automating this, the durable advice is to parse the claims challenge out of the failed response rather than hardcoding the context identifier, and to expect to test it in your own tenant.
The approval timing question. The step-up happens when the requester submits. Whether the claim must still be fresh when an approver acts, possibly hours later, and whether the approver faces any challenge of their own, is not documented anywhere I can find. I expect neither, and I am telling you it is undocumented rather than asserting it.
The same work as one runnable block
Two of the three objects here have a clean scripted equivalent, and the third deliberately does not get one from me.
# Written against Microsoft.Graph PowerShell 2.38.1 and Microsoft Graph v1.0.
# Pin the module if you are scripting this for reuse. Cmdlet parameter sets move
# between releases, and a sheet that does not say what it was written against ages
# badly and fails in ways that look like your mistake.
$ErrorActionPreference = 'Stop'
# Scopes: creating the context needs AuthenticationContext.ReadWrite.All (or
# Policy.ReadWrite.ConditionalAccess); updating the PIM rule needs
# RoleManagementPolicy.ReadWrite.Directory. These are different surfaces.
Connect-MgGraph -Scopes "AuthenticationContext.ReadWrite.All",
"RoleManagementPolicy.ReadWrite.Directory",
"Directory.Read.All"
# CONTEXT ASSERTION. Fill these in before you run anything below. A build sheet
# executed against the wrong tenant is the worst outcome this series can produce,
# and the check costs two lines.
$ExpectedTenantId = '<your tenant id>'
$ExpectedAccount = '<the account you intend to be>'
$mgContext = Get-MgContext
if ($mgContext.TenantId -ne $ExpectedTenantId) { throw "Wrong tenant: $($mgContext.TenantId)" }
if ($mgContext.Account -ne $ExpectedAccount) { throw "Wrong identity: $($mgContext.Account)" }
# Nothing in this block is an asynchronous PIM request. Both writes below are
# synchronous, so there is no request status to poll; confirm them by reading the
# object back, which step 4 does.
# 1. Create (or update) the authentication context. In v1.0 this is an
# upsert by ID via PATCH, and it returns 204 No Content on success -
# no object comes back, which is not an error.
# Rollback: if you created c1 here, DELETE the same URI. If it already
# existed, PATCH back the displayName, description and isAvailable you found.
$ctx = @{
displayName = "Privileged Role Activation"
description = "Step-up required to activate a privileged Entra role."
isAvailable = $true # this is the 'Publish to apps' checkbox
}
Invoke-MgGraphRequest -Method PATCH `
-Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/authenticationContextClassReferences/c1" `
-Body ($ctx | ConvertTo-Json)
# 2. BUILD AND ENABLE THE CONDITIONAL ACCESS POLICY NOW, IN THE PORTAL.
# Step 3 of this sheet. Do not skip ahead to step 3 below until it is On.
# 3. Point Global Administrator's activation at the context. Resolve the role by
# its immutable ID, then confirm that ID is what you think it is. Never key a
# state change on a display name: names are localised and Microsoft renames them.
# Rollback: re-run this rule with isEnabled = $false, which returns activation
# to whatever Enablement_EndUser_Assignment already requires.
$RoleId = '62e90394-69f5-4237-9190-012177145e10' # Global Administrator
(Get-MgRoleManagementDirectoryRoleDefinition -UnifiedRoleDefinitionId $RoleId).DisplayName
$assignment = Get-MgPolicyRoleManagementPolicyAssignment `
-Filter "scopeId eq '/' and scopeType eq 'DirectoryRole' and roleDefinitionId eq '$RoleId'"
$rule = @{
"@odata.type" = "#microsoft.graph.unifiedRoleManagementPolicyAuthenticationContextRule"
id = "AuthenticationContext_EndUser_Assignment"
isEnabled = $true
claimValue = "c1"
target = @{ caller = "EndUser"; operations = @("all"); level = "Assignment" }
}
Update-MgPolicyRoleManagementPolicyRule `
-UnifiedRoleManagementPolicyId $assignment.PolicyId `
-UnifiedRoleManagementPolicyRuleId "AuthenticationContext_EndUser_Assignment" `
-BodyParameter $rule
# 4. Verify what you just set, rather than trusting the absence of an error.
Get-MgPolicyRoleManagementPolicyRule -UnifiedRoleManagementPolicyId $assignment.PolicyId |
Where-Object Id -eq "AuthenticationContext_EndUser_Assignment" |
Select-Object -ExpandProperty AdditionalProperties
Three notes on that block. The rule identifier and resource type are documented, and so are the two properties that carry the configuration, but Microsoft publishes no example of this particular update: the only JSON on Learn for this rule is a response body showing it disabled with a null claim value. The body above is therefore constructed from the documented shape rather than copied from a sample, so verify the result with step 4 rather than assuming. The @odata.type line is mandatory on a rule update and omitting it is the most common failure. And the scope split bites here as it did in the earlier sheet: creating the context and updating the policy rule are separate permissions.
I am deliberately not handing you a Conditional Access policy as JSON to import, and the reason is the failure mode at the top of this article rather than any difficulty in writing one. The difference between a policy that gates activation and a policy that silently removes the gate is a scope or an exclusion, and a policy created by pasting someone else’s JSON is a policy nobody read. Build this one in the portal, look at the summary before you enable it, and then capture the result as JSON through Graph and keep it under version control, which is the export-before-you-change discipline the Conditional Access testing article already argues for. Automate the second copy, not the first.
Where this goes next
Elevation now has a price that a stolen session cannot pay. Two things follow. The population who can edit Conditional Access policy can remove that price, so if Security Administrator and Conditional Access Administrator are not themselves under PIM with the same gate, you have moved the weak point rather than removed it, and the role model article is where that argument lives. And the same context can now be pointed at the group activations from earlier in this wave and at Azure resource roles, with one caveat carried over: never scope the policy to the group being activated, for exactly the reason you never scope it to the role.
The next article turns to Azure resource roles, where the same discipline meets a different administrative surface and one operational tax that catches everybody.
Governance
‹ Previous: [PIM 4] Activation Under Conditional Access: The Passwordless Elevation
Next: [PIM 5] The Role Model: Fewer Than Five, and Two Outside the Machine ›




