diff --git a/docs/AT-Pop.md b/docs/AT-Pop.md new file mode 100644 index 00000000000..7793dd6c9e8 --- /dev/null +++ b/docs/AT-Pop.md @@ -0,0 +1,79 @@ +# Microsoft Graph PowerShell SDK: Access Token Proof of Possession (AT PoP) Capability + +## Overview + +This README provides comprehensive details on the Access Token Proof of Possession (AT PoP) functionality introduced in the Microsoft Graph PowerShell SDK. This feature enhances security by binding tokens to specific HTTP methods and URIs, ensuring they are used only for their intended purposes. + +## Table of Contents + +- [Key Features](#key-features) +- [Installation](#installation) +- [Configuration](#configuration) +- [Usage Examples](#usage-examples) +- [References](#references) + +## Key Features + +- **Access Token Proof of Possession (AT PoP)**: This feature binds tokens to specific HTTP methods and URIs, preventing misuse of tokens by ensuring they are used only for the intended HTTP requests. +- **Updated Dependencies**: Compatibility improvements with recent library changes. +- **Enhanced Token Acquisition Options**: Users can now specify the HTTP method and URI during token acquisition to further secure token usage. + +### Token acquisition behaviors + +| Condition | Unbound (default) | Bound (PoP) | +|-----------|-----------|-----------| +| First sign-in | New token, interactive| New token, interactive | +| Existing token, same URI | No new token, silent | No new token, silent | +| Existing token, different URI | No new token, silent | New token, silent | +| Existing expired token, below max token refreshes | New token, silent | New token, silent | +| Existing expired token, exceeded max refreshes | New token, interactive | New token, interactive | + +## Installation + +To install the Microsoft Graph PowerShell SDK with the latest updates, use the following command: + +```powershell +Install-Module -Name Microsoft.Graph -AllowClobber -Force +``` + +Ensure you are using the latest version to access the AT PoP functionality. + +## Configuration + +### Enabling Access Token Proof of Possession + +To enable AT PoP, configure the Microsoft Graph SDK options as follows: + +```powershell +Set-MgGraphOption -EnableATPoP $true + +Connect-MgGraph +``` + +This configuration ensures that the acquired token is only valid for the specified HTTP method and URI. + +## Usage Examples + +### Example 1: + +```powershell +Set-MgGraphOption -EnableATPoP $true + +Connect-MgGraph + +Invoke-MgGraphRequest -Method GET https://graph.microsoft.com/v1.0/me -Debug +``` + +### Example 2: + +```powershell +Set-MgGraphOption -EnableATPoP $true + +Connect-MgGraph + +Invoke-MgGraphRequest -Uri "https://graph.microsoft.com/v1.0/me/sendMail" -Method POST -Debug +``` + +## References + +This README provides a detailed guide on the new AT PoP functionality, offering users the ability to secure their token usage effectively. If you have any questions or need further assistance, please refer to the official [Microsoft Graph PowerShell SDK documentation](https://docs.microsoft.com/en-us/powershell/microsoftgraph/). diff --git a/docs/authentication.md b/docs/authentication.md index 6cfbfda695f..4d587898495 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -112,6 +112,26 @@ When using `-AccessToken`, we won't have access to the refresh token and the cli Before using the provided `-AccessToken` to get Microsoft Graph resources, customers should ensure that the access token has the necessary scopes/ permissions needed to access/modify a resource. +### Access Token Proof of Possession (AT PoP) + +AT PoP is a security mechanism that binds an access token to a cryptographic key that only the token requestor has. This prevents unauthorized use of the token by malicious actors. AT PoP enhances data protection, reduces token replay attacks, and enables fine-grained authorization policies. + +Note: AT PoP requires Web Account Manager (WAM) to function. + +Microsoft Graph PowerShell module supports AT PoP in the following scenario: + +- To enable AT PoP on supported devices + +```PowerShell +Set-MgGraphOption -EnableATPoP $true +``` + +- To disable AT PoP on supported devices + +```PowerShell +Set-MgGraphOption -EnableATPoP $false +``` + ## Web Account Manager (WAM) WAM is a Windows 10+ component that acts as an authentication broker allowing the users of an app benefit from integration with accounts known to Windows, such as the account already signed into an active Windows session. diff --git a/openApiDocs/beta/DeviceManagement.Actions.yml b/openApiDocs/beta/DeviceManagement.Actions.yml index 1bb85dea98b..13ba0d3e82c 100644 --- a/openApiDocs/beta/DeviceManagement.Actions.yml +++ b/openApiDocs/beta/DeviceManagement.Actions.yml @@ -487,4 +487,4 @@ components: tokenUrl: https://login.microsoftonline.com/common/oauth2/v2.0/token scopes: { } security: - - azureaadv2: [ ] + - azureaadv2: [ ] \ No newline at end of file diff --git a/src/Authentication/Authentication.Core/Interfaces/IGraphOptions.cs b/src/Authentication/Authentication.Core/Interfaces/IGraphOptions.cs index 3dd2483694f..de7f68f15d8 100644 --- a/src/Authentication/Authentication.Core/Interfaces/IGraphOptions.cs +++ b/src/Authentication/Authentication.Core/Interfaces/IGraphOptions.cs @@ -2,14 +2,11 @@ // Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information. // ------------------------------------------------------------------------------ -using System; -using System.Security; -using System.Security.Cryptography.X509Certificates; - namespace Microsoft.Graph.PowerShell.Authentication { public interface IGraphOption { bool EnableWAMForMSGraph { get; set; } + bool EnableATPoPForMSGraph { get; set; } } } \ No newline at end of file diff --git a/src/Authentication/Authentication.Core/Microsoft.Graph.Authentication.Core.csproj b/src/Authentication/Authentication.Core/Microsoft.Graph.Authentication.Core.csproj index 09fefaae4df..16610b51c96 100644 --- a/src/Authentication/Authentication.Core/Microsoft.Graph.Authentication.Core.csproj +++ b/src/Authentication/Authentication.Core/Microsoft.Graph.Authentication.Core.csproj @@ -4,7 +4,7 @@ 9.0 netstandard2.0;net6.0;net472 Microsoft.Graph.PowerShell.Authentication.Core - 2.31.0 + 2.32.0 true @@ -15,7 +15,9 @@ - + + + diff --git a/src/Authentication/Authentication.Core/Utilities/AuthenticationHelpers.cs b/src/Authentication/Authentication.Core/Utilities/AuthenticationHelpers.cs index 71919594c4a..23dbe2a5322 100644 --- a/src/Authentication/Authentication.Core/Utilities/AuthenticationHelpers.cs +++ b/src/Authentication/Authentication.Core/Utilities/AuthenticationHelpers.cs @@ -3,6 +3,7 @@ // ------------------------------------------------------------------------------ using Azure.Core; using Azure.Core.Diagnostics; +using Azure.Core.Pipeline; using Azure.Identity; using Azure.Identity.Broker; using Microsoft.Graph.Authentication; @@ -114,22 +115,24 @@ private static async Task GetInteractiveBrowserCre { if (authContext is null) throw new AuthenticationException(ErrorConstants.Message.MissingAuthContext); - var interactiveOptions = IsWamSupported() ? new InteractiveBrowserCredentialBrokerOptions(WindowHandleUtlities.GetConsoleOrTerminalWindow()) : new InteractiveBrowserCredentialOptions(); + var interactiveOptions = IsWamSupported() ? + new InteractiveBrowserCredentialBrokerOptions(WindowHandleUtlities.GetConsoleOrTerminalWindow()) : + new InteractiveBrowserCredentialOptions(); interactiveOptions.ClientId = authContext.ClientId; interactiveOptions.TenantId = authContext.TenantId ?? "common"; interactiveOptions.AuthorityHost = new Uri(GetAuthorityUrl(authContext)); interactiveOptions.TokenCachePersistenceOptions = GetTokenCachePersistenceOptions(authContext); + var interactiveBrowserCredential = new InteractiveBrowserCredential(interactiveOptions); if (!File.Exists(Constants.AuthRecordPath)) { AuthenticationRecord authRecord; - var interactiveBrowserCredential = new InteractiveBrowserCredential(interactiveOptions); if (IsWamSupported()) { authRecord = await Task.Run(() => { // Run the thread in MTA. - return interactiveBrowserCredential.Authenticate(new TokenRequestContext(authContext.Scopes), cancellationToken); + return interactiveBrowserCredential.AuthenticateAsync(new TokenRequestContext(authContext.Scopes), cancellationToken); }); } else diff --git a/src/Authentication/Authentication/Cmdlets/SetMgGraphOption.cs b/src/Authentication/Authentication/Cmdlets/SetMgGraphOption.cs index ad4f0f76a11..fc4da16a8ed 100644 --- a/src/Authentication/Authentication/Cmdlets/SetMgGraphOption.cs +++ b/src/Authentication/Authentication/Cmdlets/SetMgGraphOption.cs @@ -13,6 +13,9 @@ public class SetMgGraphOption : PSCmdlet { [Parameter] public bool EnableLoginByWAM { get; set; } + + [Parameter] + public bool EnableATPoP { get; set; } protected override void BeginProcessing() { @@ -27,6 +30,11 @@ protected override void ProcessRecord() GraphSession.Instance.GraphOption.EnableWAMForMSGraph = EnableLoginByWAM; WriteDebug($"Signin by Web Account Manager (WAM) is {(EnableLoginByWAM ? "enabled" : "disabled")}."); } + if (this.IsParameterBound(nameof(EnableATPoP))) + { + GraphSession.Instance.GraphOption.EnableATPoPForMSGraph = EnableATPoP; + WriteDebug($"Access Token Proof of Posession (AT-PoP) is {(EnableATPoP ? "enabled" : "disabled")}."); + } File.WriteAllText(Constants.GraphOptionsFilePath, JsonConvert.SerializeObject(GraphSession.Instance.GraphOption, Formatting.Indented)); } diff --git a/src/Authentication/Authentication/Handlers/AuthenticationHandler.cs b/src/Authentication/Authentication/Handlers/AuthenticationHandler.cs index e57d74186b3..4e6f5e9f7a6 100644 --- a/src/Authentication/Authentication/Handlers/AuthenticationHandler.cs +++ b/src/Authentication/Authentication/Handlers/AuthenticationHandler.cs @@ -3,11 +3,15 @@ // ------------------------------------------------------------------------------ +using Azure.Core; using Microsoft.Graph.Authentication; +using Microsoft.Graph.PowerShell.Authentication.Core.Utilities; using Microsoft.Graph.PowerShell.Authentication.Extensions; +using Microsoft.Identity.Client; using System; using System.Collections.Generic; using System.Linq; +using System.Management.Automation; using System.Net; using System.Net.Http; using System.Net.Http.Headers; @@ -21,7 +25,10 @@ internal class AuthenticationHandler : DelegatingHandler { private const string ClaimsKey = "claims"; private const string BearerAuthenticationScheme = "Bearer"; + private const string PopAuthenticationScheme = "Pop"; private int MaxRetry { get; set; } = 1; + private TokenRequestContext popTokenRequestContext; + private string cachedNonce; public AzureIdentityAccessTokenProvider AuthenticationProvider { get; set; } @@ -45,6 +52,24 @@ protected override async Task SendAsync(HttpRequestMessage HttpResponseMessage response = await base.SendAsync(httpRequestMessage, cancellationToken).ConfigureAwait(false); + // Extract nonce from API responses for future PoP requests + if (GraphSession.Instance.GraphOption.EnableATPoPForMSGraph && IsApiRequest(httpRequestMessage.RequestUri)) + { + try + { + var wwwAuthParams = WwwAuthenticateParameters.CreateFromAuthenticationHeaders(response.Headers, PopAuthenticationScheme); + if (wwwAuthParams?.Nonce != null && !string.IsNullOrEmpty(wwwAuthParams.Nonce)) + { + cachedNonce = wwwAuthParams.Nonce; + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"AuthenticationHandler: Failed to extract PoP nonce: {ex.Message}"); + // Don't throw - nonce extraction failure shouldn't break the response + } + } + // Check if response is a 401 & is not a streamed body (is buffered) if (response.StatusCode == HttpStatusCode.Unauthorized && httpRequestMessage.IsBuffered()) { @@ -63,9 +88,55 @@ private async Task AuthenticateRequestAsync(HttpRequestMessage httpRequestMessag { if (AuthenticationProvider != null) { - var accessToken = await AuthenticationProvider.GetAuthorizationTokenAsync(httpRequestMessage.RequestUri, additionalAuthenticationContext, cancellationToken: cancellationToken).ConfigureAwait(false); - if (!string.IsNullOrEmpty(accessToken)) - httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(BearerAuthenticationScheme, accessToken); + // Determine if this is an API request that should use PoP (when enabled) + // vs an authentication request that should always use Bearer + bool isApiRequest = IsApiRequest(httpRequestMessage.RequestUri); + bool shouldUsePoP = GraphSession.Instance.GraphOption.EnableATPoPForMSGraph && isApiRequest; + + // Debug logging for flow routing + if (GraphSession.Instance.GraphOption.EnableATPoPForMSGraph) + { + var requestType = isApiRequest ? "API" : "Auth"; + var tokenType = shouldUsePoP ? "PoP" : "Bearer"; + System.Diagnostics.Debug.WriteLine($"AuthenticationHandler: {requestType} request to {httpRequestMessage.RequestUri?.Host} using {tokenType} token"); + } + + if (shouldUsePoP) + { + // API Request with PoP enabled - use PoP tokens ONLY + try + { + // Create proper TokenRequestContext for PoP + // Note: cachedNonce may be null for initial requests - this is expected + popTokenRequestContext = new TokenRequestContext( + scopes: GraphSession.Instance.AuthContext.Scopes, + parentRequestId: null, + claims: additionalAuthenticationContext?.ContainsKey(ClaimsKey) == true ? additionalAuthenticationContext[ClaimsKey]?.ToString() : null, + tenantId: null, + isCaeEnabled: false, + isProofOfPossessionEnabled: true, + proofOfPossessionNonce: cachedNonce // May be null for initial requests + ); + + // Get TokenCredential from existing AuthenticationProvider + var tokenCredential = await AuthenticationHelpers.GetTokenCredentialAsync( + GraphSession.Instance.AuthContext, cancellationToken).ConfigureAwait(false); + + var accessToken = await tokenCredential.GetTokenAsync(popTokenRequestContext, cancellationToken).ConfigureAwait(false); + httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(PopAuthenticationScheme, accessToken.Token); + } + catch (Exception ex) when (!(ex is OperationCanceledException)) + { + // Re-throw with context for PoP-specific failures + throw new AuthenticationException($"Failed to acquire PoP token for {httpRequestMessage.RequestUri}: {ex.Message}", ex); + } + } + else + { + var accessToken = await AuthenticationProvider.GetAuthorizationTokenAsync(httpRequestMessage.RequestUri, additionalAuthenticationContext, cancellationToken: cancellationToken).ConfigureAwait(false); + if (!string.IsNullOrEmpty(accessToken)) + httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(BearerAuthenticationScheme, accessToken); + } } } @@ -128,5 +199,52 @@ private static async Task DrainAsync(HttpResponseMessage response) } response.Dispose(); } + + /// + /// Determines if the request is an API request that should use PoP when enabled, + /// vs an authentication/token request that should always use Bearer tokens. + /// This method implements the core routing logic for AT-PoP: + /// - Graph API endpoints → PoP tokens (when enabled) + /// - Authentication endpoints → Bearer tokens (always) + /// - Unknown endpoints → Bearer tokens (safe default) + /// + /// The request URI to evaluate + /// True if this is an API request, false if it's an authentication request + private static bool IsApiRequest(Uri requestUri) + { + if (requestUri == null) return false; + + var host = requestUri.Host?.ToLowerInvariant(); + var path = requestUri.AbsolutePath?.ToLowerInvariant(); + + // Microsoft Graph API endpoints that should use PoP + if (host?.Contains("graph.microsoft.com") == true || + host?.Contains("graph.microsoft.us") == true || + host?.Contains("microsoftgraph.chinacloudapi.cn") == true || + host?.Contains("graph.microsoft.de") == true) + { + // Exclude authentication/token endpoints - these should always use Bearer + if (path?.Contains("/oauth2/") == true || + path?.Contains("/token") == true || + path?.Contains("/authorize") == true || + path?.Contains("/devicecode") == true) + { + return false; // Authentication request + } + return true; // API request + } + + // Azure AD/authentication endpoints - never use PoP + if (host?.Contains("login.microsoftonline.com") == true || + host?.Contains("login.microsoft.com") == true || + host?.Contains("login.chinacloudapi.cn") == true || + host?.Contains("login.microsoftonline.de") == true || + host?.Contains("login.microsoftonline.us") == true) + { + return false; // Authentication request + } + + return false; // Default to authentication request for unknown endpoints + } } } \ No newline at end of file diff --git a/src/Authentication/Authentication/Models/GraphOption.cs b/src/Authentication/Authentication/Models/GraphOption.cs index d8c48d7f70a..e8c83e6ef01 100644 --- a/src/Authentication/Authentication/Models/GraphOption.cs +++ b/src/Authentication/Authentication/Models/GraphOption.cs @@ -9,6 +9,7 @@ namespace Microsoft.Graph.PowerShell.Authentication internal class GraphOption : IGraphOption { public bool EnableWAMForMSGraph { get; set; } + public bool EnableATPoPForMSGraph { get; set; } } } \ No newline at end of file diff --git a/src/Authentication/Authentication/test/Get-MgGraphOption.Tests.ps1 b/src/Authentication/Authentication/test/Get-MgGraphOption.Tests.ps1 index 786105807c7..2708d2f7f41 100644 --- a/src/Authentication/Authentication/test/Get-MgGraphOption.Tests.ps1 +++ b/src/Authentication/Authentication/test/Get-MgGraphOption.Tests.ps1 @@ -13,7 +13,7 @@ Describe "Get-MgGraphOption Command" { $GetMgGraphOptionCommand = Get-Command Set-MgGraphOption $GetMgGraphOptionCommand | Should -Not -BeNullOrEmpty $GetMgGraphOptionCommand.ParameterSets | Should -HaveCount 1 - $GetMgGraphOptionCommand.ParameterSets.Parameters | Should -HaveCount 13 # PS common parameters. + $GetMgGraphOptionCommand.ParameterSets.Parameters | Should -HaveCount 14 # PS common parameters. } It 'Executes successfully' { diff --git a/src/Authentication/Authentication/test/Set-MgGraphOption.Tests.ps1 b/src/Authentication/Authentication/test/Set-MgGraphOption.Tests.ps1 index 6a2cb60693a..775cdcaa629 100644 --- a/src/Authentication/Authentication/test/Set-MgGraphOption.Tests.ps1 +++ b/src/Authentication/Authentication/test/Set-MgGraphOption.Tests.ps1 @@ -9,14 +9,14 @@ Describe "Set-MgGraphOption" { Import-Module $ModulePath -Force -ErrorAction SilentlyContinue } Context "When executing the command" { - it 'Should have one ParameterSets' { + it 'Should have two ParameterSets' { $SetMgGraphOptionCommand = Get-Command Set-MgGraphOption $SetMgGraphOptionCommand | Should -Not -BeNullOrEmpty $SetMgGraphOptionCommand.ParameterSets | Should -HaveCount 1 - $SetMgGraphOptionCommand.ParameterSets.Parameters | Should -HaveCount 13 # PS common parameters. + $SetMgGraphOptionCommand.ParameterSets.Parameters | Should -HaveCount 14 # PS common parameters. } - It 'Executes successfully whren toggling WAM on' { + It 'Executes successfully when toggling WAM on' { { Set-MgGraphOption -EnableLoginByWAM $true -Debug | Out-Null } | Should -Not -Be $null { Set-MgGraphOption -EnableLoginByWAM $true -ErrorAction SilentlyContinue } | Should -Not -Throw } @@ -25,5 +25,15 @@ Describe "Set-MgGraphOption" { { Set-MgGraphOption -EnableLoginByWAM $false -Debug | Out-Null } | Should -Not -Be $null { Set-MgGraphOption -EnableLoginByWAM $false -ErrorAction SilentlyContinue } | Should -Not -Throw } + + It 'Executes successfully when toggling AT PoP on' { + { Set-MgGraphOption -EnableATPoP $true -Debug | Out-Null } | Should -Not -Be $null + { Set-MgGraphOption -EnableATPoP $true -ErrorAction SilentlyContinue } | Should -Not -Throw + } + + It 'Executes successfully when toggling AT PoP off' { + { Set-MgGraphOption -EnableATPoP $false -Debug | Out-Null } | Should -Not -Be $null + { Set-MgGraphOption -EnableATPoP $false -ErrorAction SilentlyContinue } | Should -Not -Throw + } } } \ No newline at end of file diff --git a/src/Authentication/docs/Connect-MgGraph.md b/src/Authentication/docs/Connect-MgGraph.md index 9ef5d0af7ce..57730953e7e 100644 --- a/src/Authentication/docs/Connect-MgGraph.md +++ b/src/Authentication/docs/Connect-MgGraph.md @@ -351,6 +351,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -ProgressAction +{{ Fill ProgressAction Description }} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Scopes An array of delegated permissions to consent to. @@ -366,6 +381,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -SendCertificateChain +Include x5c header in client claims when acquiring a token to enable subject name / issuer based authentication using given certificate. + +```yaml +Type: Boolean +Parameter Sets: AppCertificateParameterSet +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -TenantId The id of the tenant to connect to. You can also use this parameter to specify your sign-in audience. diff --git a/src/Authentication/docs/Get-MgGraphOption.md b/src/Authentication/docs/Get-MgGraphOption.md index f4ef0a7c258..7678d11d798 100644 --- a/src/Authentication/docs/Get-MgGraphOption.md +++ b/src/Authentication/docs/Get-MgGraphOption.md @@ -1,7 +1,7 @@ --- external help file: Microsoft.Graph.Authentication.dll-Help.xml Module Name: Microsoft.Graph.Authentication -online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.authentication/get-mgenvironment +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.authentication/get-mggraphoption schema: 2.0.0 --- diff --git a/src/Authentication/docs/Set-MgGraphOption.md b/src/Authentication/docs/Set-MgGraphOption.md index 85ee3e9fca6..99ef8e95a29 100644 --- a/src/Authentication/docs/Set-MgGraphOption.md +++ b/src/Authentication/docs/Set-MgGraphOption.md @@ -1,7 +1,7 @@ --- external help file: Microsoft.Graph.Authentication.dll-Help.xml Module Name: Microsoft.Graph.Authentication -online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.authentication/set-mgenvironment +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.authentication/set-mggraphoption schema: 2.0.0 --- @@ -15,6 +15,9 @@ Sets global configurations that apply to the SDK. For example, toggle Web Accoun ``` Set-MgGraphOption [-EnableLoginByWAM ] [] ``` +``` +Set-MgGraphOption [-EnableATPoP ] [] +``` ## DESCRIPTION Sets global configurations that apply to the SDK. For example, toggle Web Account Manager (WAM) support. @@ -28,11 +31,21 @@ PS C:\> Set-MgGraphOption -EnableLoginByWAM $True Sets web account manager support +### Example 2: Set access token proof of possession support +```powershell +PS C:\> Set-MgGraphOption -EnableATPoP $True +``` + + Sets access token proof of possession support + ## PARAMETERS ### -EnableLoginByWAM {{ Fill EnableLoginByWAM Description }} +### -EnableATPoP +{{ Fill EnableATPoP Description }} + ```yaml Type: Boolean Parameter Sets: (All) diff --git a/src/Authentication/examples/Set-MgGraphOption.md b/src/Authentication/examples/Set-MgGraphOption.md index 055431b5920..afc23d97cb1 100644 --- a/src/Authentication/examples/Set-MgGraphOption.md +++ b/src/Authentication/examples/Set-MgGraphOption.md @@ -2,4 +2,10 @@ ```powershell PS C:\> Set-MgGraphOption -EnableLoginByWAM $True ``` - Sets web account manager support \ No newline at end of file + Sets web account manager support + +### Example 2: Set access token proof of possession support +```powershell +PS C:\> Set-MgGraphOption -EnableATPoP $True +``` + Sets access token proof of possession support \ No newline at end of file