From f2c59130e829a6921a1f5c1e16ba7df4dc21bd9a Mon Sep 17 00:00:00 2001 From: Gautam Sheth Date: Sat, 17 Feb 2024 20:31:39 +0200 Subject: [PATCH] Fix #3717 - Added support for custom environment in App registration --- CHANGELOG.md | 1 + src/Commands/AzureAD/RegisterAzureADApp.cs | 33 ++++++++++++++++--- .../AzureAD/RegisterManagementShellAccess.cs | 18 +++++----- src/Commands/Utilities/AzureAuthHelper.cs | 28 +++++++++++----- 4 files changed, 59 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bb716d7b..50b8ae926 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/). - Fixed `Get-PnPPowerPlatformConnector`, `Get-PnPPowerPlatformEnvironment`, `Get-PnPPowerApp`, `Add-PnPFlowOwner`, `Disable-PnPFlow`, `Enable-PnPFlow`, `Export-PnPFlow`, `Get-PnPFlowOwner`, `Get-PnPFlowRun`, `Remove-PnPFlow`, `Remove-PnPFlowOwner` , `Restart-PnPFlow` and `Stop-PnPFlowRun` cmdlets to use the new HTTP endpoints. [#3687](https://github.com/pnp/powershell/pull/3687) - Fixed `Add-PnPHubSiteAssociation` cmdlet to allow support for multi-geo scenario. [#3568](https://github.com/pnp/powershell/pull/3568) - Fixed `Enable/Disable-PnPPageScheduling` cmdlet to also work with Viva connections enabled site. [#3713](https://github.com/pnp/powershell/pull/3713) +- Fixed `Register-PnPManagementShellAccess` and `Register-PnPAzureADApp` cmdlets to also work with custom environment. ### Changed diff --git a/src/Commands/AzureAD/RegisterAzureADApp.cs b/src/Commands/AzureAD/RegisterAzureADApp.cs index 8da6b45ae..612a609e3 100644 --- a/src/Commands/AzureAD/RegisterAzureADApp.cs +++ b/src/Commands/AzureAD/RegisterAzureADApp.cs @@ -527,7 +527,14 @@ private X509Certificate2 GetCertificate(PSObject record) private bool AppExists(string appName, HttpClient httpClient, string token) { Host.UI.Write(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"Checking if application '{appName}' does not exist yet..."); - var azureApps = RestHelper.GetAsync>(httpClient, $@"https://{PnP.Framework.AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}/v1.0/applications?$filter=displayName eq '{appName}'&$select=Id", token).GetAwaiter().GetResult(); + + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}"; + if (AzureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + + var azureApps = RestHelper.GetAsync>(httpClient, $"{graphEndpoint}/v1.0/applications?$filter=displayName eq '{appName}'&$select=Id", token).GetAwaiter().GetResult(); if (azureApps != null && azureApps.Items.Any()) { Host.UI.WriteLine(); @@ -571,7 +578,13 @@ private AzureADApp CreateApp(string loginEndPoint, HttpClient httpClient, string requiredResourceAccess = scopesPayload }; - var azureApp = RestHelper.PostAsync(httpClient, $"https://{AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}/v1.0/applications", token, payload).GetAwaiter().GetResult(); + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}"; + if (AzureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + + var azureApp = RestHelper.PostAsync(httpClient, $"{graphEndpoint}/v1.0/applications", token, payload).GetAwaiter().GetResult(); if (azureApp != null) { Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"App {azureApp.DisplayName} with id {azureApp.AppId} created."); @@ -583,7 +596,13 @@ private void StartConsentFlow(string loginEndPoint, AzureADApp azureApp, string { //Host.UI.WriteLine(ConsoleColor.Yellow, Host.UI.RawUI.BackgroundColor, $"Starting consent flow."); - var resource = scopes.FirstOrDefault(s => s.resourceAppId == PermissionScopes.ResourceAppId_Graph) != null ? $"https://{AzureAuthHelper.GetGraphEndPoint(AzureEnvironment)}/.default" : "https://microsoft.sharepoint-df.com/.default"; + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}"; + if (AzureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + + var resource = scopes.FirstOrDefault(s => s.resourceAppId == PermissionScopes.ResourceAppId_Graph) != null ? $"{graphEndpoint}/.default" : "https://microsoft.sharepoint-df.com/.default"; var consentUrl = $"{loginEndPoint}/{Tenant}/v2.0/adminconsent?client_id={azureApp.AppId}&scope={resource}&redirect_uri={redirectUri}"; @@ -658,7 +677,13 @@ private void SetLogo(AzureADApp azureApp, string token) { WriteVerbose("Setting the logo for the Azure AD app"); - var endpoint = $"https://{AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}/v1.0/applications/{azureApp.Id}/logo"; + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}"; + if (AzureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + + var endpoint = $"{graphEndpoint}/v1.0/applications/{azureApp.Id}/logo"; var bytes = File.ReadAllBytes(LogoFilePath); diff --git a/src/Commands/AzureAD/RegisterManagementShellAccess.cs b/src/Commands/AzureAD/RegisterManagementShellAccess.cs index 2886fe43f..92fe61ecc 100644 --- a/src/Commands/AzureAD/RegisterManagementShellAccess.cs +++ b/src/Commands/AzureAD/RegisterManagementShellAccess.cs @@ -1,6 +1,7 @@ using PnP.Framework; using PnP.PowerShell.Commands.Base; using PnP.PowerShell.Commands.Utilities; +using System; using System.Collections.Generic; using System.Management.Automation; using System.Net.Http; @@ -50,6 +51,12 @@ protected override void ProcessRecord() WriteWarning("Please specify the Tenant name for non-commercial clouds, otherwise this operation will fail."); } + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(AzureEnvironment)}"; + if (AzureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + Task.Factory.StartNew(() => { if (ParameterSetName == ParameterSet_REGISTER) @@ -64,7 +71,7 @@ protected override void ProcessRecord() { try { - authManager.GetAccessTokenAsync(new[] { $"https://{GetGraphEndPoint()}/.default" }, source.Token, Microsoft.Identity.Client.Prompt.Consent).GetAwaiter().GetResult(); + authManager.GetAccessTokenAsync(new[] { $"{graphEndpoint}/.default" }, source.Token, Microsoft.Identity.Client.Prompt.Consent).GetAwaiter().GetResult(); } catch (Microsoft.Identity.Client.MsalException) { @@ -91,7 +98,7 @@ protected override void ProcessRecord() var accessToken = string.Empty; try { - accessToken = authManager.GetAccessTokenAsync(new[] { $"https://{GetGraphEndPoint()}/.default" }, source.Token).GetAwaiter().GetResult(); + accessToken = authManager.GetAccessTokenAsync(new[] { $"{graphEndpoint}/.default" }, source.Token).GetAwaiter().GetResult(); } catch (Microsoft.Identity.Client.MsalException) { @@ -100,7 +107,7 @@ protected override void ProcessRecord() if (!string.IsNullOrEmpty(accessToken)) { var httpClient = Framework.Http.PnPHttpClient.Instance.GetHttpClient(); - using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"https://{GetGraphEndPoint()}/v1.0/organization")) + using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, $"{graphEndpoint}/v1.0/organization")) { requestMessage.Version = new System.Version(2, 0); requestMessage.Headers.Add("Authorization", $"Bearer {accessToken}"); @@ -142,10 +149,5 @@ protected override void StopProcessing() { source.Cancel(); } - - private string GetGraphEndPoint() - { - return PnP.Framework.AuthenticationManager.GetGraphEndPoint(AzureEnvironment); - } } } diff --git a/src/Commands/Utilities/AzureAuthHelper.cs b/src/Commands/Utilities/AzureAuthHelper.cs index 5e125f311..14ddc9218 100644 --- a/src/Commands/Utilities/AzureAuthHelper.cs +++ b/src/Commands/Utilities/AzureAuthHelper.cs @@ -19,7 +19,12 @@ internal static async Task AuthenticateAsync(string tenantId, string use using (var authManager = PnP.Framework.AuthenticationManager.CreateWithCredentials(username, password, azureEnvironment)) { - return await authManager.GetAccessTokenAsync(new[] { $"https://{GetGraphEndPoint(azureEnvironment)}/.default" }); + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(azureEnvironment)}"; + if (azureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + return await authManager.GetAccessTokenAsync(new[] { $"{graphEndpoint}/.default" }); } } @@ -46,7 +51,12 @@ internal static string AuthenticateDeviceLogin(CancellationTokenSource cancellat authManager.ClearTokenCache(); try { - return authManager.GetAccessTokenAsync(new string[] { $"https://{GetGraphEndPoint(azureEnvironment)}/.default" }, cancellationTokenSource.Token).GetAwaiter().GetResult(); + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(azureEnvironment)}"; + if (azureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + return authManager.GetAccessTokenAsync(new string[] { $"{graphEndpoint}/.default" }, cancellationTokenSource.Token).GetAwaiter().GetResult(); } catch (Microsoft.Identity.Client.MsalException) { @@ -78,7 +88,12 @@ internal static string AuthenticateInteractive(CancellationTokenSource cancellat authManager.ClearTokenCache(); try { - return authManager.GetAccessTokenAsync(new string[] { $"https://{GetGraphEndPoint(azureEnvironment)}/.default" }, cancellationTokenSource.Token).GetAwaiter().GetResult(); + var graphEndpoint = $"https://{AuthenticationManager.GetGraphEndPoint(azureEnvironment)}"; + if (azureEnvironment == AzureEnvironment.Custom) + { + graphEndpoint = Environment.GetEnvironmentVariable("MicrosoftGraphEndPoint", EnvironmentVariableTarget.Process); + } + return authManager.GetAccessTokenAsync(new string[] { $"{graphEndpoint}/.default" }, cancellationTokenSource.Token).GetAwaiter().GetResult(); } catch (Microsoft.Identity.Client.MsalException) { @@ -91,11 +106,6 @@ internal static string AuthenticateInteractive(CancellationTokenSource cancellat cancellationTokenSource.Cancel(); } return null; - } - - internal static string GetGraphEndPoint(AzureEnvironment azureEnvironment) - { - return PnP.Framework.AuthenticationManager.GetGraphEndPoint(azureEnvironment); - } + } } } \ No newline at end of file