|
| 1 | +--- |
| 2 | +title: Token protection in Azure AD Conditional Access |
| 3 | +description: Learn how to use token protection in Conditional Access policies. |
| 4 | +ms.service: active-directory |
| 5 | +ms.subservice: conditional-access |
| 6 | +ms.topic: conceptual |
| 7 | +ms.date: 03/09/2023 |
| 8 | + |
| 9 | +ms.author: joflore |
| 10 | +author: MicrosoftGuyJFlo |
| 11 | +manager: amycolannino |
| 12 | +ms.reviewer: paulgarn |
| 13 | + |
| 14 | +ms.collection: M365-identity-device-management |
| 15 | +--- |
| 16 | +# Conditional Access: Token protection (preview) |
| 17 | + |
| 18 | +Token protection (sometimes referred to as token binding in the industry) attempts to reduce attacks using token theft by ensuring a token is usable only from the intended device. When an attacker is able to steal a token, by hijacking or replay, they can impersonate their victim until the token expires or is revoked. Token theft is thought to be a relatively rare event, but the damage from it can be significant. |
| 19 | + |
| 20 | +Token protection creates a cryptographically secure tie between the token and the device (client secret) it's issued to. Without the client secret, the bound token is useless. When a user registers a Windows 10 or newer device in Azure AD, their primary identity is [bound to the device](../devices/concept-primary-refresh-token.md#how-is-the-prt-protected). This connection means that any issued sign-in token is tied to the device significantly reducing the chance of theft and replay attacks. These sign-in tokens are specifically the session cookies in Microsoft Edge and most Microsoft product refresh tokens in this preview release. |
| 21 | + |
| 22 | +With this preview, we're giving you the ability to create a Conditional Access policy to require token protection for sign-in tokens for specific services. We support token protection for sign-in tokens in Conditional Access for Exchange Online and SharePoint Online on Windows devices. |
| 23 | + |
| 24 | +:::image type="content" source="media/concept-token-protection/complete-policy-components-session.png" alt-text="Screenshot showing a Conditional Access policy requiring token protection as the session control"::: |
| 25 | + |
| 26 | +## Requirements |
| 27 | + |
| 28 | +This preview supports the following configurations: |
| 29 | + |
| 30 | +* Windows 10 or newer devices that are Azure AD joined, hybrid Azure AD joined, or Azure AD registered. |
| 31 | +* OneDrive sync client version 22.217 or later |
| 32 | +* Teams native client version 1.6.00.1331 or later |
| 33 | +* Office Perpetual clients aren't supported |
| 34 | + |
| 35 | +### Known limitations |
| 36 | + |
| 37 | +- External users (Azure AD B2B) aren't supported and shouldn't be included in your Conditional Access policy. |
| 38 | +- The following applications don't support signing in using protected token flows and users are blocked when accessing Exchange and SharePoint: |
| 39 | + - Power BI Desktop client |
| 40 | + - PowerShell modules accessing Exchange, SharePoint, or Microsoft Graph scopes that are served by Exchange or SharePoint |
| 41 | + - PowerQuery extension for Excel |
| 42 | + - Extensions to Visual Studio Code which access Exchange or SharePoint |
| 43 | + - Visual Studio |
| 44 | +- The following Windows client devices aren't supported: |
| 45 | + - Windows Server |
| 46 | + - Surface Hub |
| 47 | + |
| 48 | +## Deployment |
| 49 | + |
| 50 | +For users, the deployment of a Conditional Access policy to enforce token protection should be invisible when using compatible client platforms on registered devices and compatible applications. |
| 51 | + |
| 52 | +To minimize the likelihood of user disruption due to app or device incompatibility, we highly recommend: |
| 53 | + |
| 54 | +- Start with a pilot group of users, and expand over time. |
| 55 | +- Create a Conditional Access policy in [report-only mode](concept-conditional-access-report-only.md) before moving to enforcement of token protection. |
| 56 | +- Capture both Interactive and Non-interactive sign in logs. |
| 57 | +- Analyze these logs for long enough to cover normal application use. |
| 58 | +- Add known good users to an enforcement policy. |
| 59 | + |
| 60 | +This process helps to assess your users’ client and app compatibility for token protection enforcement. |
| 61 | + |
| 62 | +### Create a Conditional Access policy |
| 63 | + |
| 64 | +Users who perform specialized roles like those described in [Privileged access security levels](/security/compass/privileged-access-security-levels#specialized) are possible targets for this functionality. We recommend piloting with a small subset to begin. |
| 65 | + |
| 66 | +:::image type="content" source="media/concept-token-protection/exposed-policy-attributes.png" alt-text="Screenshot of a configured Conditional Access policy and its components." lightbox="media/concept-token-protection/exposed-policy-attributes.png"::: |
| 67 | + |
| 68 | +The steps that follow help create a Conditional Access policy to require token protection for Exchange Online and SharePoint Online on Windows devices. |
| 69 | + |
| 70 | +1. Sign in to the **Azure portal** as a Conditional Access Administrator, Security Administrator, or Global Administrator. |
| 71 | +1. Browse to **Azure Active Directory** > **Security** > **Conditional Access**. |
| 72 | +1. Select **New policy**. |
| 73 | +1. Give your policy a name. We recommend that organizations create a meaningful standard for the names of their policies. |
| 74 | +1. Under **Assignments**, select **Users or workload identities**. |
| 75 | + 1. Under **Include**, select the users or groups who are testing this policy. |
| 76 | + 1. Under **Exclude**, select **Users and groups** and choose your organization's emergency access or break-glass accounts. |
| 77 | +1. Under **Cloud apps or actions** > **Include**, select **Select apps**. |
| 78 | + 1. Under **Select**, select the following applications supported by the preview: |
| 79 | + 1. Office 365 Exchange Online |
| 80 | + 1. Office 365 SharePoint Online |
| 81 | + |
| 82 | + > [!WARNING] |
| 83 | + > Your Conditional Access policy should only be configured for these applications. Selecting the **Office 365** application group may result in unintended failures. This is an exception to the general rule that the **Office 365** application group should be selected in a Conditional Access policy. |
| 84 | +
|
| 85 | + 1. Choose **Select**. |
| 86 | +1. Under **Conditions**: |
| 87 | + 1. Under **Device platforms**: |
| 88 | + 1. Set **Configure** to **Yes**. |
| 89 | + 1. **Include** > **Select device platforms** > **Windows**. |
| 90 | + 1. Select **Done**. |
| 91 | + 1. Under **Client apps**: |
| 92 | + 1. Set **Configure** to **Yes**. |
| 93 | + 1. Under Modern authentication clients, only select **Mobile apps and desktop clients**. Leave other items unchecked. |
| 94 | + 1. Select **Done**. |
| 95 | +1. Under **Access controls** > **Session**, select **Require token protection for sign-in sessions** and select **Select**. |
| 96 | +1. Confirm your settings and set **Enable policy** to **Report-only**. |
| 97 | +1. Select **Create** to create to enable your policy. |
| 98 | + |
| 99 | +After confirming your settings using [report-only mode](howto-conditional-access-insights-reporting.md), an administrator can move the **Enable policy** toggle from **Report-only** to **On**. |
| 100 | + |
| 101 | +### Capture logs and analyze |
| 102 | + |
| 103 | +Monitoring Conditional Access enforcement of token protection before and after enforcement. |
| 104 | + |
| 105 | +#### Sign-in logs |
| 106 | + |
| 107 | +Use Azure AD sign-in log to verify the outcome of a token protection enforcement policy in report only mode or in enabled mode. |
| 108 | + |
| 109 | +1. Sign in to the **Azure portal** as a Conditional Access Administrator, Security Administrator, or Global Administrator. |
| 110 | +1. Browse to **Azure Active Directory** > **Sign-in logs**. |
| 111 | +1. Select a specific request to determine if the policy is applied or not. |
| 112 | +1. Go to the **Conditional Access** or **Report-Only** pane depending on its state and select the name of your policy requiring token protection. |
| 113 | +1. Under **Session Controls** check to see if the policy requirements were satisfied or not. |
| 114 | + |
| 115 | +:::image type="content" source="media/concept-token-protection/sign-in-log-sample.png" alt-text="Screenshot showing an example of a policy not being satisfied." lightbox="media/concept-token-protection/sign-in-log-sample.png"::: |
| 116 | + |
| 117 | +#### Log Analytics |
| 118 | + |
| 119 | +You can also use [Log Analytics](../reports-monitoring/tutorial-log-analytics-wizard.md) to query the sign-in logs (interactive and non-interactive) for blocked requests due to token protection enforcement failure. |
| 120 | + |
| 121 | +Here's a sample Log Analytics query searching the non-interactive sign-in logs for the last seven days, highlighting **Blocked** versus **Allowed** requests by **Application**. |
| 122 | + |
| 123 | +```kusto |
| 124 | +//Per Apps query |
| 125 | +// Select the log you want to query (SigninLogs or AADNonInteractiveUserSignInLogs ) |
| 126 | +//SigninLogs |
| 127 | +AADNonInteractiveUserSignInLogs |
| 128 | +// Adjust the time range below |
| 129 | +| where TimeGenerated > ago(7d) |
| 130 | +| project Id,ConditionalAccessPolicies, Status,UserPrincipalName, AppDisplayName, ResourceDisplayName |
| 131 | +| where ConditionalAccessPolicies != "[]" |
| 132 | +| where ResourceDisplayName == "Office 365 Exchange Online" or ResourceDisplayName =="Office 365 SharePoint Online" |
| 133 | +//Add userPrinicpalName if you want to filter |
| 134 | +// | where UserPrincipalName =="<user_principal_Name>" |
| 135 | +| mv-expand todynamic(ConditionalAccessPolicies) |
| 136 | +| where ConditionalAccessPolicies ["enforcedSessionControls"] contains '["Protection"]' |
| 137 | +| where ConditionalAccessPolicies.result !="reportOnlyNotApplied" and ConditionalAccessPolicies.result !="notApplied" |
| 138 | +| extend SessionNotSatisfyResult = ConditionalAccessPolicies["sessionControlsNotSatisfied"] |
| 139 | +| extend Result = case (SessionNotSatisfyResult contains 'Protection', 'Block','Allow') |
| 140 | +| summarize by Id,UserPrincipalName, AppDisplayName, Result |
| 141 | +| summarize Requests = count(), Users = dcount(UserPrincipalName), Block = countif(Result == "Block"), Allow = countif(Result == "Allow"), BlockedUsers = dcountif(UserPrincipalName, Result == "Block") by AppDisplayName |
| 142 | +| extend PctAllowed = round(100.0 * Allow/(Allow+Block), 2) |
| 143 | +| sort by Requests desc |
| 144 | +``` |
| 145 | + |
| 146 | +The result of the previous query should be similar to the following screenshot: |
| 147 | + |
| 148 | +:::image type="content" source="media/concept-token-protection/log-analytics-results.png" alt-text="Screenshot showing example results of a Log Analytics query looking for token protection policies" lightbox="media/concept-token-protection/log-analytics-results.png"::: |
| 149 | + |
| 150 | +The following query example looks at the non-interactive sign-in log for the last seven days, highlighting **Blocked** versus **Allowed** requests by **User**. |
| 151 | + |
| 152 | +```kusto |
| 153 | +//Per users query |
| 154 | +// Select the log you want to query (SigninLogs or AADNonInteractiveUserSignInLogs ) |
| 155 | +//SigninLogs |
| 156 | +AADNonInteractiveUserSignInLogs |
| 157 | +// Adjust the time range below |
| 158 | +| where TimeGenerated > ago(7d) |
| 159 | +| project Id,ConditionalAccessPolicies, UserPrincipalName, AppDisplayName, ResourceDisplayName |
| 160 | +| where ConditionalAccessPolicies != "[]" |
| 161 | +| where ResourceDisplayName == "Office 365 Exchange Online" or ResourceDisplayName =="Office 365 SharePoint Online" |
| 162 | +//Add userPrincipalName if you want to filter |
| 163 | +// | where UserPrincipalName =="<user_principal_Name>" |
| 164 | +| mv-expand todynamic(ConditionalAccessPolicies) |
| 165 | +| where ConditionalAccessPolicies.enforcedSessionControls contains '["Protection"]' |
| 166 | +| where ConditionalAccessPolicies.result !="reportOnlyNotApplied" and ConditionalAccessPolicies.result !="notApplied" |
| 167 | +| extend SessionNotSatisfyResult = ConditionalAccessPolicies.sessionControlsNotSatisfied |
| 168 | +| extend Result = case (SessionNotSatisfyResult contains 'Protection', 'Block','Allow') |
| 169 | +| summarize by Id, UserPrincipalName, AppDisplayName, ResourceDisplayName,Result |
| 170 | +| summarize Requests = count(),Block = countif(Result == "Block"), Allow = countif(Result == "Allow") by UserPrincipalName, AppDisplayName,ResourceDisplayName |
| 171 | +| extend PctAllowed = round(100.0 * Allow/(Allow+Block), 2) |
| 172 | +| sort by UserPrincipalName asc |
| 173 | +``` |
| 174 | + |
| 175 | +## Next steps |
| 176 | + |
| 177 | +- [What is a Primary Refresh Token?](../devices/concept-primary-refresh-token.md) |
0 commit comments