Skip to content

Commit

Permalink
Deploy with 3 separate app registrations, Fixes #686 (#698)
Browse files Browse the repository at this point in the history
* Added Separate app registrations for Landing page and Admin portal

* Updated app settings for both web apps

* Updated check for multiple app regs

* Fixed error in braces

* Updated check for existing app regs

* Updated check for adding redirects to app registration
  • Loading branch information
neelavarshad authored Jun 6, 2024
1 parent 67885e0 commit 555bc9f
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 24 deletions.
117 changes: 102 additions & 15 deletions deployment/Deploy.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Param(
[string][Parameter()]$AzureSubscriptionID, # Subscription where the resources be deployed
[string][Parameter()]$ADApplicationID, # The value should match the value provided for Active Directory Application ID in the Technical Configuration of the Transactable Offer in Partner Center
[string][Parameter()]$ADApplicationSecret, # Secret key of the AD Application
[string][Parameter()]$ADMTApplicationID, # Multi-Tenant Active Directory Application ID
[string][Parameter()]$ADMTApplicationIDAdmin, # Multi-Tenant Active Directory Application ID for the Admin Portal
[string][Parameter()]$ADMTApplicationIDPortal, #Multi-Tenant Active Directory Application ID for the Landing Portal
[string][Parameter()]$SQLDatabaseName, # Name of the database (Defaults to AMPSaaSDB)
[string][Parameter()]$SQLServerName, # Name of the database server (without database.windows.net)
[string][Parameter()]$LogoURLpng, # URL for Publisher .png logo
Expand Down Expand Up @@ -188,7 +189,17 @@ if($LogoURLico) {
#region Create AAD App Registrations

#Record the current ADApps to reduce deployment instructions at the end
$ISADMTApplicationIDProvided = $ADMTApplicationID
$ISADMTApplicationIDProvided = ($ADMTApplicationIDAdmin && $ADMTApplicationIDPortal)

if($ISADMTApplicationIDProvided -eq $null){
Write-Host "🔑 Multi-Tenant App Registrations provided."
Write-Host " ➡️ Admin Portal App Registration ID:" $ADMTApplicationIDAdmin
Write-Host " ➡️ Landing Page App Registration ID:" $ADMTApplicationIDPortal
}
else {
Write-Host "🔑 Multi-Tenant App Registrations not provided."
}


#Create App Registration for authenticating calls to the Marketplace API
if (!($ADApplicationID)) {
Expand All @@ -211,6 +222,84 @@ if (!($ADApplicationID)) {
}
}

#Create Multi-Tenant App Registration for Admin Portal User Login
if (!($ADMTApplicationID)) {
Write-Host "🔑 Creating Admin Portal SSO App Registration"
try {

$appCreateRequestBodyJson = @"
{
"displayName" : "$WebAppNamePrefix-AdminPortalAppReg",
"api":
{
"requestedAccessTokenVersion" : 2
},
"signInAudience" : "AzureADandPersonalMicrosoftAccount",
"web":
{
"redirectUris":
[
"https://$WebAppNamePrefix-admin.azurewebsites.net",
"https://$WebAppNamePrefix-admin.azurewebsites.net/",
"https://$WebAppNamePrefix-admin.azurewebsites.net/Home/Index",
"https://$WebAppNamePrefix-admin.azurewebsites.net/Home/Index/"
],
"logoutUrl": "https://$WebAppNamePrefix-admin.azurewebsites.net/logout",
"implicitGrantSettings":
{ "enableIdTokenIssuance" : true }
},
"requiredResourceAccess":
[{
"resourceAppId": "00000003-0000-0000-c000-000000000000",
"resourceAccess":
[{
"id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
"type": "Scope"
}]
}]
}
"@
if ($PsVersionTable.Platform -ne 'Unix') {
#On Windows, we need to escape quotes and remove new lines before sending the payload to az rest.
# See: https://github.com/Azure/azure-cli/blob/dev/doc/quoting-issues-with-powershell.md#double-quotes--are-lost
$appCreateRequestBodyJson = $appCreateRequestBodyJson.replace('"','\"').replace("`r`n","")
}

$adminPortalAppReg = $(az rest --method POST --headers "Content-Type=application/json" --uri https://graph.microsoft.com/v1.0/applications --body $appCreateRequestBodyJson ) | ConvertFrom-Json

$ADMTApplicationIDAdmin = $adminPortalAppReg.appId
$ADMTObjectIDAdmin = $adminPortalAppReg.id

Write-Host " 🔵 Admin Portal SSO App Registration created."
Write-Host " ➡️ Application Id: $ADMTApplicationIDAdmin"


# Download Publisher's AppRegistration logo
if($LogoURLpng) {
Write-Host " 🔵 Logo image provided. Setting the Application branding logo"
Write-Host " ➡️ Setting the Application branding logo"
$token=(az account get-access-token --resource "https://graph.microsoft.com" --query accessToken --output tsv)
$logoWeb = Invoke-WebRequest $LogoURLpng
$logoContentType = $logoWeb.Headers["Content-Type"]
$logoContent = $logoWeb.Content

$uploaded = Invoke-WebRequest `
-Uri "https://graph.microsoft.com/v1.0/applications/$ADMTObjectIDAdmin/logo" `
-Method "PUT" `
-Header @{"Authorization"="Bearer $token";"Content-Type"="$logoContentType";} `
-Body $logoContent

Write-Host " ➡️ Application branding logo set."
}

}
catch [System.Net.WebException],[System.IO.IOException] {
Write-Host "🚨🚨 $PSItem.Exception"
break;
}
}

#Create Multi-Tenant App Registration for Landing Page User Login
if (!($ADMTApplicationID)) {
Write-Host "🔑 Creating Landing Page SSO App Registration"
Expand All @@ -231,11 +320,8 @@ if (!($ADMTApplicationID)) {
"https://$WebAppNamePrefix-portal.azurewebsites.net",
"https://$WebAppNamePrefix-portal.azurewebsites.net/",
"https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index",
"https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index/",
"https://$WebAppNamePrefix-admin.azurewebsites.net",
"https://$WebAppNamePrefix-admin.azurewebsites.net/",
"https://$WebAppNamePrefix-admin.azurewebsites.net/Home/Index",
"https://$WebAppNamePrefix-admin.azurewebsites.net/Home/Index/"
"https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index/"
],
"logoutUrl": "https://$WebAppNamePrefix-portal.azurewebsites.net/logout",
"implicitGrantSettings":
Expand All @@ -260,11 +346,11 @@ if (!($ADMTApplicationID)) {

$landingpageLoginAppReg = $(az rest --method POST --headers "Content-Type=application/json" --uri https://graph.microsoft.com/v1.0/applications --body $appCreateRequestBodyJson ) | ConvertFrom-Json

$ADMTApplicationID = $landingpageLoginAppReg.appId
$ADMTObjectID = $landingpageLoginAppReg.id
$ADMTApplicationIDPortal = $landingpageLoginAppReg.appId
$ADMTObjectIDPortal = $landingpageLoginAppReg.id

Write-Host " 🔵 Landing Page SSO App Registration created."
Write-Host " ➡️ Application Id: $ADMTApplicationID"
Write-Host " ➡️ Application Id: $ADMTApplicationIDPortal"

# Download Publisher's AppRegistration logo
if($LogoURLpng) {
Expand All @@ -276,7 +362,7 @@ if (!($ADMTApplicationID)) {
$logoContent = $logoWeb.Content

$uploaded = Invoke-WebRequest `
-Uri "https://graph.microsoft.com/v1.0/applications/$ADMTObjectID/logo" `
-Uri "https://graph.microsoft.com/v1.0/applications/$ADMTObjectIDPortal/logo" `
-Method "PUT" `
-Header @{"Authorization"="Bearer $token";"Content-Type"="$logoContentType";} `
-Body $logoContent
Expand Down Expand Up @@ -378,7 +464,7 @@ Write-host " ➡️ Setup access to KeyVault"
az keyvault set-policy --name $KeyVault --object-id $WebAppNameAdminId --secret-permissions get list --key-permissions get list --resource-group $ResourceGroupForDeployment --output $azCliOutput
Write-host " ➡️ Set Configuration"
az webapp config connection-string set -g $ResourceGroupForDeployment -n $WebAppNameAdmin -t SQLAzure --output $azCliOutput --settings DefaultConnection=$DefaultConnectionKeyVault
az webapp config appsettings set -g $ResourceGroupForDeployment -n $WebAppNameAdmin --output $azCliOutput --settings KnownUsers=$PublisherAdminUsers SaaSApiConfiguration__AdAuthenticationEndPoint=https://login.microsoftonline.com SaaSApiConfiguration__ClientId=$ADApplicationID SaaSApiConfiguration__ClientSecret=$ADApplicationSecretKeyVault SaaSApiConfiguration__FulFillmentAPIBaseURL=https://marketplaceapi.microsoft.com/api SaaSApiConfiguration__FulFillmentAPIVersion=2018-08-31 SaaSApiConfiguration__GrantType=client_credentials SaaSApiConfiguration__MTClientId=$ADMTApplicationID SaaSApiConfiguration__Resource=20e940b3-4c77-4b0b-9a53-9e16a1b010a7 SaaSApiConfiguration__TenantId=$TenantID SaaSApiConfiguration__SignedOutRedirectUri=https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index/ SaaSApiConfiguration_CodeHash=$SaaSApiConfiguration_CodeHash
az webapp config appsettings set -g $ResourceGroupForDeployment -n $WebAppNameAdmin --output $azCliOutput --settings KnownUsers=$PublisherAdminUsers SaaSApiConfiguration__AdAuthenticationEndPoint=https://login.microsoftonline.com SaaSApiConfiguration__ClientId=$ADApplicationID SaaSApiConfiguration__ClientSecret=$ADApplicationSecretKeyVault SaaSApiConfiguration__FulFillmentAPIBaseURL=https://marketplaceapi.microsoft.com/api SaaSApiConfiguration__FulFillmentAPIVersion=2018-08-31 SaaSApiConfiguration__GrantType=client_credentials SaaSApiConfiguration__MTClientIdAdmin=$ADMTApplicationIDAdmin SaaSApiConfiguration__MTCLientIdPortal=$ADMTApplicationIDPortal SaaSApiConfiguration__Resource=20e940b3-4c77-4b0b-9a53-9e16a1b010a7 SaaSApiConfiguration__TenantId=$TenantID SaaSApiConfiguration__SignedOutRedirectUri=https://$WebAppNamePrefix-admin.azurewebsites.net/Home/Index/ SaaSApiConfiguration_CodeHash=$SaaSApiConfiguration_CodeHash
az webapp config set -g $ResourceGroupForDeployment -n $WebAppNameAdmin --always-on true --output $azCliOutput

Write-host " 🔵 Customer Portal WebApp"
Expand All @@ -390,7 +476,7 @@ Write-host " ➡️ Setup access to KeyVault"
az keyvault set-policy --name $KeyVault --object-id $WebAppNamePortalId --secret-permissions get list --key-permissions get list --resource-group $ResourceGroupForDeployment --output $azCliOutput
Write-host " ➡️ Set Configuration"
az webapp config connection-string set -g $ResourceGroupForDeployment -n $WebAppNamePortal -t SQLAzure --output $azCliOutput --settings DefaultConnection=$DefaultConnectionKeyVault
az webapp config appsettings set -g $ResourceGroupForDeployment -n $WebAppNamePortal --output $azCliOutput --settings SaaSApiConfiguration__AdAuthenticationEndPoint=https://login.microsoftonline.com SaaSApiConfiguration__ClientId=$ADApplicationID SaaSApiConfiguration__ClientSecret=$ADApplicationSecretKeyVault SaaSApiConfiguration__FulFillmentAPIBaseURL=https://marketplaceapi.microsoft.com/api SaaSApiConfiguration__FulFillmentAPIVersion=2018-08-31 SaaSApiConfiguration__GrantType=client_credentials SaaSApiConfiguration__MTClientId=$ADMTApplicationID SaaSApiConfiguration__Resource=20e940b3-4c77-4b0b-9a53-9e16a1b010a7 SaaSApiConfiguration__TenantId=$TenantID SaaSApiConfiguration__SignedOutRedirectUri=https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index/ SaaSApiConfiguration_CodeHash=$SaaSApiConfiguration_CodeHash
az webapp config appsettings set -g $ResourceGroupForDeployment -n $WebAppNamePortal --output $azCliOutput --settings SaaSApiConfiguration__AdAuthenticationEndPoint=https://login.microsoftonline.com SaaSApiConfiguration__ClientId=$ADApplicationID SaaSApiConfiguration__ClientSecret=$ADApplicationSecretKeyVault SaaSApiConfiguration__FulFillmentAPIBaseURL=https://marketplaceapi.microsoft.com/api SaaSApiConfiguration__FulFillmentAPIVersion=2018-08-31 SaaSApiConfiguration__GrantType=client_credentials SaaSApiConfiguration__MTClientIdPortal=$ADMTApplicationIDPortal SaaSApiConfiguration__MTClientIdAdmin=$ADMTApplicationIDAdmin SaaSApiConfiguration__Resource=20e940b3-4c77-4b0b-9a53-9e16a1b010a7 SaaSApiConfiguration__TenantId=$TenantID SaaSApiConfiguration__SignedOutRedirectUri=https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index/ SaaSApiConfiguration_CodeHash=$SaaSApiConfiguration_CodeHash
az webapp config set -g $ResourceGroupForDeployment -n $WebAppNamePortal --always-on true --output $azCliOutput

#endregion
Expand Down Expand Up @@ -431,12 +517,13 @@ Remove-Item -Path script.sql
#region Present Output

Write-host "✅ If the intallation completed without error complete the folllowing checklist:"
if ($ISADMTApplicationIDProvided) { #If provided then show the user where to add the landing page in AAD, otherwise script did this already for the user.
Write-host " 🔵 Add The following URLs to the multi-tenant AAD App Registration in Azure Portal:"
if ($ISADMTApplicationIDProvided -ne $null) { #If provided then show the user where to add the landing page in AAD, otherwise script did this already for the user.
Write-host " 🔵 Add The following URLs to the multi-tenant Landing Page AAD App Registration in Azure Portal:"
Write-host " ➡️ https://$WebAppNamePrefix-portal.azurewebsites.net"
Write-host " ➡️ https://$WebAppNamePrefix-portal.azurewebsites.net/"
Write-host " ➡️ https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index"
Write-host " ➡️ https://$WebAppNamePrefix-portal.azurewebsites.net/Home/Index/"
Write-host " 🔵 Add The following URLs to the multi-tenant Admin Portal AAD App Registration in Azure Portal:"
Write-host " ➡️ https://$WebAppNamePrefix-admin.azurewebsites.net"
Write-host " ➡️ https://$WebAppNamePrefix-admin.azurewebsites.net/"
Write-host " ➡️ https://$WebAppNamePrefix-admin.azurewebsites.net/Home/Index"
Expand Down
5 changes: 3 additions & 2 deletions src/AdminSite/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ public void ConfigureServices(IServiceCollection services)
ClientId = this.Configuration["SaaSApiConfiguration:ClientId"] ?? Guid.Empty.ToString(),
ClientSecret = this.Configuration["SaaSApiConfiguration:ClientSecret"] ?? String.Empty,
FulFillmentAPIBaseURL = this.Configuration["SaaSApiConfiguration:FulFillmentAPIBaseURL"],
MTClientId = this.Configuration["SaaSApiConfiguration:MTClientId"] ?? Guid.Empty.ToString(),
MTClientIdAdmin = this.Configuration["SaaSApiConfiguration:MTClientIdAdmin"] ?? Guid.Empty.ToString(),
MTClientIdPortal = this.Configuration["SaaSApiConfiguration:MTClientIdPortal"] ?? Guid.Empty.ToString(),
FulFillmentAPIVersion = this.Configuration["SaaSApiConfiguration:FulFillmentAPIVersion"],
GrantType = this.Configuration["SaaSApiConfiguration:GrantType"],
Resource = this.Configuration["SaaSApiConfiguration:Resource"],
Expand All @@ -96,7 +97,7 @@ public void ConfigureServices(IServiceCollection services)
.AddOpenIdConnect(options =>
{
options.Authority = $"{config.AdAuthenticationEndPoint}/common/v2.0";
options.ClientId = config.MTClientId;
options.ClientId = config.MTClientIdAdmin;
options.ResponseType = OpenIdConnectResponseType.IdToken;
options.CallbackPath = "/Home/Index";
options.SignedOutRedirectUri = config.SignedOutRedirectUri;
Expand Down
3 changes: 2 additions & 1 deletion src/AdminSite/appsettings.Development.json.rename
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
// "tenantid": "",
// "clientid": "",
// "clientsecret": "",
// "mtclientid": "",
// "mtclientidadmin": "",
// "mtclientidportal": "",
// "resource": "20e940b3-4c77-4b0b-9a53-9e16a1b010a7",
// "fulfillmentapibaseurl": "https://marketplaceapi.microsoft.com/api",
// "signedoutredirecturi": "",
Expand Down
3 changes: 2 additions & 1 deletion src/AdminSite/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
// "tenantid": "",
// "clientid": "",
// "clientsecret": "",
// "mtclientid": "",
// "mtclientidadmin": "",
// "mtclientidportal": "",
// "resource": "20e940b3-4c77-4b0b-9a53-9e16a1b010a7",
// "fulfillmentapibaseurl": "https://marketplaceapi.microsoft.com/api",
// "signedoutredirecturi": "",
Expand Down
5 changes: 3 additions & 2 deletions src/CustomerSite/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ public void ConfigureServices(IServiceCollection services)
AdAuthenticationEndPoint = this.Configuration["SaaSApiConfiguration:AdAuthenticationEndPoint"],
ClientId = this.Configuration["SaaSApiConfiguration:ClientId"],
ClientSecret = this.Configuration["SaaSApiConfiguration:ClientSecret"],
MTClientId = this.Configuration["SaaSApiConfiguration:MTClientId"],
MTClientIdAdmin = this.Configuration["SaaSApiConfiguration:MTClientIdAdmin"],
MTClientIdPortal = this.Configuration["SaaSApiConfiguration:MTClientIdPortal"],
FulFillmentAPIBaseURL = this.Configuration["SaaSApiConfiguration:FulFillmentAPIBaseURL"],
FulFillmentAPIVersion = this.Configuration["SaaSApiConfiguration:FulFillmentAPIVersion"],
GrantType = this.Configuration["SaaSApiConfiguration:GrantType"],
Expand Down Expand Up @@ -95,7 +96,7 @@ public void ConfigureServices(IServiceCollection services)
.AddOpenIdConnect(options =>
{
options.Authority = $"{config.AdAuthenticationEndPoint}/common/v2.0";
options.ClientId = config.MTClientId;
options.ClientId = config.MTClientIdPortal;
options.ResponseType = OpenIdConnectResponseType.IdToken;
options.CallbackPath = "/Home/Index";
options.SignedOutRedirectUri = config.SignedOutRedirectUri;
Expand Down
3 changes: 2 additions & 1 deletion src/CustomerSite/appsettings.Development.json.rename
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
// "tenantid": "",
// "clientid": "",
// "clientsecret": "",
// "mtclientid": "",
// "mtclientidadmin": "",
// "mtclientidportal": "",
// "resource": "20e940b3-4c77-4b0b-9a53-9e16a1b010a7",
// "fulfillmentapibaseurl": "https://marketplaceapi.microsoft.com/api",
// "signedoutredirecturi": "",
Expand Down
3 changes: 2 additions & 1 deletion src/CustomerSite/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
// "granttype": "client_credentials",
// "clientid": "",
// "clientsecret": "",
// "mtclientid": "",
// "mtclientidadmin": "",
// "mtclientidportal": "",
// "tenantid": "",
// "resource": "20e940b3-4c77-4b0b-9a53-9e16a1b010a7",
// "fulfillmentapibaseurl": "https://marketplaceapi.microsoft.com/api",
Expand Down
10 changes: 9 additions & 1 deletion src/Services/Configurations/SaaSApiClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,15 @@ public class SaaSApiClientConfiguration
/// <value>
/// The resource.
/// </value>
public string MTClientId { get; set; }
public string MTClientIdAdmin { get; set; }

/// <summary>
/// Gets or sets the AAD Client ID resource.
/// </summary>
/// <value>
/// The resource.
/// </value>
public string MTClientIdPortal { get; set; }

/// <summary>
/// Gets or sets the resource.
Expand Down

0 comments on commit 555bc9f

Please sign in to comment.