From ff0d620cfdef686ff297bb2a9ec031371004cc5f Mon Sep 17 00:00:00 2001 From: Gautam Sheth Date: Thu, 16 Dec 2021 11:23:23 +0200 Subject: [PATCH 1/2] Feature : extend Get-PnPAccessToken with additional resources --- CHANGELOG.md | 4 ++ documentation/Get-PnPAccessToken.md | 56 +++++++++++++++++++++++++- src/Commands/Base/GetAccessToken.cs | 55 +++++++++++++++++++++++-- src/Commands/Base/TokenHandling.cs | 18 +++++++-- src/Commands/Enums/ResourceTypeName.cs | 9 +++++ 5 files changed, 133 insertions(+), 9 deletions(-) create mode 100644 src/Commands/Enums/ResourceTypeName.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 838d48660..a98825567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added alias on `Copy-PnPFile` for `Copy-PnPFolder`. It could already be used to copy a folder, but to make this more clear, and as we already had a `Copy/Move-PnPFolder` as well, the same cmdlet is now also available under its alternative cmdlet name. - Added `IsFluidEnabled` state to be returned with `Get-PnPTenant` cmdlet. - Added `-IsFluidEnabled` to `Set-PnPTenant` cmdlet to enable/disable users from using Fluid components. +- Added `-ResourceTypeName` and `ResourceUrl` parameters to `Get-PnPAccessToken` to fetch access token of specified resource. ### Changed - Improved `Get-PnPFile` cmdlet to handle large file downloads @@ -48,6 +49,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - A clearer error message will now be returned when using `Add-PnPListItem -List` and specifying an invalid list name. - Response of `Add-PnPContentTypesFromContenTypeHub` is now returned in the root of the response as well as under Value as it was previously for backwards compatibility. - Improved synopsis documentation for `Update-PnPUserType` cmdlet. +- Improved documentation of `Add-PnPField` , reflects the missing `-AddToAllContentTypes` parameter. +- Improved documentation of `Get-PnPTaxonomyItem` with addition of new example and removing obsolete parameters. +- Improved documentation of `Get-PnPTerm` , fixed typos. ### Fixed - Fixed `Get-PnPGroupMember -User` not properly returning the specified user diff --git a/documentation/Get-PnPAccessToken.md b/documentation/Get-PnPAccessToken.md index 23ebba739..0395c6d45 100644 --- a/documentation/Get-PnPAccessToken.md +++ b/documentation/Get-PnPAccessToken.md @@ -10,12 +10,13 @@ title: Get-PnPAccessToken # Get-PnPAccessToken ## SYNOPSIS -Returns the current Microsoft Graph OAuth Access token +Returns the current Microsoft Graph OAuth Access token. +If a Resource Type Name or Resource URL is specified, it will fetch the access token of the specified resource. ## SYNTAX ```powershell -Get-PnPAccessToken [-Decoded] [] +Get-PnPAccessToken [-ResourceTypeName] [-ResourceUrl] [-Decoded] [] ``` ## DESCRIPTION @@ -30,8 +31,59 @@ Get-PnPAccessToken Gets the OAuth 2.0 Access Token to consume the Microsoft Graph API +### EXAMPLE 2 +```powershell +Get-PnPAccessToken -ResourceTypeName SharePoint +``` + +Gets the OAuth 2.0 Access Token to consume the SharePoint APIs and perform CSOM operations. + +### EXAMPLE 3 +```powershell +Get-PnPAccessToken -ResourceTypeName ARM +``` + +Gets the OAuth 2.0 Access Token to consume the Azure Resource Manager APIs and perform related operations. In PnP, you can use them in cmdlets related to Flow and PowerPlatform etc. + +### EXAMPLE 4 +```powershell +Get-PnPAccessToken -ResourceUrl "https://management.azure.com/.default" +``` + +Gets the OAuth 2.0 Access Token to consume the SharePoint APIs and perform CSOM operations. + ## PARAMETERS +### -ResourceTypeName +Specify the Resource Type for which you want the access token. +If not specified, it will by default return Microsoft Graph access token. + +```yaml +Type: SwitchParameter +Parameter Sets: Resource Type Name + +Required: False +Position: Named +Default value: Graph +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ResourceUrl +Specify the Resource URL for which you want the access token. +If not specified, it will by default return Microsoft Graph access token. + +```yaml +Type: SwitchParameter +Parameter Sets: Resource Url + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Decoded Returns the details from the access token in a decoded manner diff --git a/src/Commands/Base/GetAccessToken.cs b/src/Commands/Base/GetAccessToken.cs index 16cc491dc..37b0db26c 100644 --- a/src/Commands/Base/GetAccessToken.cs +++ b/src/Commands/Base/GetAccessToken.cs @@ -1,6 +1,7 @@ using System; using System.Management.Automation; using PnP.PowerShell.Commands.Attributes; +using PnP.PowerShell.Commands.Enums; namespace PnP.PowerShell.Commands.Base { @@ -8,18 +9,66 @@ namespace PnP.PowerShell.Commands.Base [RequiredMinimalApiPermissions("https://graph.microsoft.com/.default")] public class GetPnPAccessToken : PnPGraphCmdlet { + private const string ResourceTypeParam = "Resource Type Name"; + private const string ResourceUrlParam = "Resource Url"; + + [Parameter(Mandatory = false, ParameterSetName = ResourceTypeParam)] + public ResourceTypeName ResourceTypeName = ResourceTypeName.Graph; + + [Parameter(Mandatory = false, ParameterSetName = ResourceUrlParam)] + public string ResourceUrl; + + [Parameter(ParameterSetName = ResourceTypeParam)] + [Parameter(ParameterSetName = ResourceUrlParam)] [Parameter(Mandatory = false)] public SwitchParameter Decoded; - protected override void ExecuteCmdlet() { + var accessTokenValue = AccessToken; + + if (ParameterSetName == ResourceTypeParam) + { + accessTokenValue = null; + if (PnPConnection.Current != null) + { + if (PnPConnection.Current.Context != null) + { + switch (ResourceTypeName) + { + case ResourceTypeName.Graph: + accessTokenValue = AccessToken; + break; + case ResourceTypeName.SharePoint: + var settings = Microsoft.SharePoint.Client.InternalClientContextExtensions.GetContextSettings(PnPConnection.Current.Context); + if (settings != null) + { + var authManager = settings.AuthenticationManager; + if (authManager != null) + { + accessTokenValue = TokenHandler.GetAccessToken(null, PnPConnection.Current.Context.Url.TrimEnd('/') + "/.default"); + } + } + break; + case ResourceTypeName.ARM: + accessTokenValue = TokenHandler.GetAccessToken(null, "https://management.azure.com/.default"); + break; + } + } + } + } + + else if (ParameterSetName == ResourceUrlParam) + { + accessTokenValue = TokenHandler.GetAccessToken(null, ResourceUrl); + } + if (Decoded.IsPresent) { - WriteObject(new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(AccessToken)); + WriteObject(new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(accessTokenValue)); } else { - WriteObject(AccessToken); + WriteObject(accessTokenValue); } } } diff --git a/src/Commands/Base/TokenHandling.cs b/src/Commands/Base/TokenHandling.cs index f7d3042d8..0e8cc86a0 100644 --- a/src/Commands/Base/TokenHandling.cs +++ b/src/Commands/Base/TokenHandling.cs @@ -57,8 +57,19 @@ internal static string GetAccessToken(Type cmdletType, string appOnlyDefaultScop var authManager = contextSettings.AuthenticationManager; if (authManager != null) { + if (contextSettings.Type == Framework.Utilities.Context.ClientContextType.SharePointACSAppOnly) + { + // When connected using ACS, we cannot get a token for another endpoint + throw new PSInvalidOperationException("Trying to get a token for a different endpoint while being connected through an ACS token is not possible. Please connect differently."); + } + string[] requiredScopes = null; - var requiredScopesAttribute = (RequiredMinimalApiPermissions)Attribute.GetCustomAttribute(cmdletType, typeof(RequiredMinimalApiPermissions)); + //RequiredMinimalApiPermissions requiredScopesAttribute = (RequiredMinimalApiPermissions)Attribute.GetCustomAttribute(cmdletType, typeof(RequiredMinimalApiPermissions)); + RequiredMinimalApiPermissions requiredScopesAttribute = null; + if (cmdletType != null) + { + requiredScopesAttribute = (RequiredMinimalApiPermissions)Attribute.GetCustomAttribute(cmdletType, typeof(RequiredMinimalApiPermissions)); + } if (requiredScopesAttribute != null) { requiredScopes = requiredScopesAttribute.PermissionScopes; @@ -67,10 +78,9 @@ internal static string GetAccessToken(Type cmdletType, string appOnlyDefaultScop { requiredScopes = new[] { appOnlyDefaultScope }; // override for app only } - if (contextSettings.Type == Framework.Utilities.Context.ClientContextType.SharePointACSAppOnly) + if (requiredScopes == null && !string.IsNullOrEmpty(appOnlyDefaultScope)) { - // When connected using ACS, we cannot get a token for another endpoint - throw new PSInvalidOperationException("Trying to get a token for a different endpoint while being connected through an ACS token is not possible. Please connect differently."); + requiredScopes = new[] { appOnlyDefaultScope }; } var accessToken = authManager.GetAccessTokenAsync(requiredScopes).GetAwaiter().GetResult(); return accessToken; diff --git a/src/Commands/Enums/ResourceTypeName.cs b/src/Commands/Enums/ResourceTypeName.cs new file mode 100644 index 000000000..6dd2c644c --- /dev/null +++ b/src/Commands/Enums/ResourceTypeName.cs @@ -0,0 +1,9 @@ +namespace PnP.PowerShell.Commands.Enums +{ + public enum ResourceTypeName + { + Graph = 1, + SharePoint = 2, + ARM = 3 + } +} From bc5595813c757abce7d58b34ab51eb8c014596d2 Mon Sep 17 00:00:00 2001 From: Gautam Sheth Date: Thu, 16 Dec 2021 11:27:55 +0200 Subject: [PATCH 2/2] Removed extra code --- src/Commands/Base/GetAccessToken.cs | 35 +++++++++-------------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/Commands/Base/GetAccessToken.cs b/src/Commands/Base/GetAccessToken.cs index 37b0db26c..a8cf46650 100644 --- a/src/Commands/Base/GetAccessToken.cs +++ b/src/Commands/Base/GetAccessToken.cs @@ -29,31 +29,18 @@ protected override void ExecuteCmdlet() if (ParameterSetName == ResourceTypeParam) { accessTokenValue = null; - if (PnPConnection.Current != null) + + switch (ResourceTypeName) { - if (PnPConnection.Current.Context != null) - { - switch (ResourceTypeName) - { - case ResourceTypeName.Graph: - accessTokenValue = AccessToken; - break; - case ResourceTypeName.SharePoint: - var settings = Microsoft.SharePoint.Client.InternalClientContextExtensions.GetContextSettings(PnPConnection.Current.Context); - if (settings != null) - { - var authManager = settings.AuthenticationManager; - if (authManager != null) - { - accessTokenValue = TokenHandler.GetAccessToken(null, PnPConnection.Current.Context.Url.TrimEnd('/') + "/.default"); - } - } - break; - case ResourceTypeName.ARM: - accessTokenValue = TokenHandler.GetAccessToken(null, "https://management.azure.com/.default"); - break; - } - } + case ResourceTypeName.Graph: + accessTokenValue = AccessToken; + break; + case ResourceTypeName.SharePoint: + accessTokenValue = TokenHandler.GetAccessToken(null, PnPConnection.Current?.Context?.Url?.TrimEnd('/') + "/.default"); + break; + case ResourceTypeName.ARM: + accessTokenValue = TokenHandler.GetAccessToken(null, "https://management.azure.com/.default"); + break; } }