Skip to content

Commit 48cb05a

Browse files
author
Tiago Brenck
committed
app creation ps1
1 parent bc0612c commit 48cb05a

File tree

4 files changed

+149
-31
lines changed

4 files changed

+149
-31
lines changed

1-WebApp-OIDC/1-2-AnyOrg/AppCreationScripts/Cleanup.ps1

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ param(
55
[string] $tenantId
66
)
77

8-
if ((Get-Module -ListAvailable -Name "AzureAD") -eq $null) {
8+
if ($null -eq (Get-Module -ListAvailable -Name "AzureAD")) {
99
Install-Module "AzureAD" -Scope CurrentUser
1010
}
1111
Import-Module AzureAD
12-
$ErrorActionPreference = 'Stop'
12+
$ErrorActionPreference = "Stop"
1313

1414
Function Cleanup
1515
{
@@ -44,20 +44,27 @@ This function removes the Azure AD applications for the sample. These applicatio
4444
$tenantId = $creds.Tenant.Id
4545
}
4646
$tenant = Get-AzureADTenantDetail
47-
$tenantName = ($tenant.VerifiedDomains | Where { $_._Default -eq $True }).Name
47+
$tenantName = ($tenant.VerifiedDomains | Where-Object { $_._Default -eq $True }).Name
4848

4949
# Removes the applications
5050
Write-Host "Cleaning-up applications from tenant '$tenantName'"
5151

5252
Write-Host "Removing 'webApp' (WebApp) if needed"
53-
$app=Get-AzureADApplication -Filter "DisplayName eq 'WebApp'"
53+
Get-AzureADApplication -Filter "DisplayName eq 'WebApp'" | ForEach-Object {Remove-AzureADApplication -ObjectId $_.ObjectId }
54+
$apps = Get-AzureADApplication -Filter "DisplayName eq 'WebApp'"
55+
if ($apps)
56+
{
57+
Remove-AzureADApplication -ObjectId $apps.ObjectId
58+
}
5459

55-
if ($app)
60+
foreach ($app in $apps)
5661
{
5762
Remove-AzureADApplication -ObjectId $app.ObjectId
58-
Write-Host "Removed."
63+
Write-Host "Removed WebApp.."
5964
}
60-
65+
# also remove service principals of this app
66+
Get-AzureADServicePrincipal -filter "DisplayName eq 'WebApp'" | ForEach-Object {Remove-AzureADServicePrincipal -ObjectId $_.Id -Confirm:$false}
67+
6168
}
6269

63-
Cleanup -Credential $Credential -tenantId $TenantId
70+
Cleanup -Credential $Credential -tenantId $TenantId

1-WebApp-OIDC/1-2-AnyOrg/AppCreationScripts/Configure.ps1

Lines changed: 112 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,87 @@ param(
1717
There are four ways to run this script. For more information, read the AppCreationScripts.md file in the same folder as this script.
1818
#>
1919

20+
# Create a password that can be used as an application key
21+
Function ComputePassword
22+
{
23+
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
24+
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
25+
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
26+
$aesManaged.BlockSize = 128
27+
$aesManaged.KeySize = 256
28+
$aesManaged.GenerateKey()
29+
return [System.Convert]::ToBase64String($aesManaged.Key)
30+
}
31+
32+
# Create an application key
33+
# See https://www.sabin.io/blog/adding-an-azure-active-directory-application-and-key-using-powershell/
34+
Function CreateAppKey([DateTime] $fromDate, [double] $durationInYears, [string]$pw)
35+
{
36+
$endDate = $fromDate.AddYears($durationInYears)
37+
$keyId = (New-Guid).ToString();
38+
$key = New-Object Microsoft.Open.AzureAD.Model.PasswordCredential
39+
$key.StartDate = $fromDate
40+
$key.EndDate = $endDate
41+
$key.Value = $pw
42+
$key.KeyId = $keyId
43+
return $key
44+
}
45+
46+
# Adds the requiredAccesses (expressed as a pipe separated string) to the requiredAccess structure
47+
# The exposed permissions are in the $exposedPermissions collection, and the type of permission (Scope | Role) is
48+
# described in $permissionType
49+
Function AddResourcePermission($requiredAccess, `
50+
$exposedPermissions, [string]$requiredAccesses, [string]$permissionType)
51+
{
52+
foreach($permission in $requiredAccesses.Trim().Split("|"))
53+
{
54+
foreach($exposedPermission in $exposedPermissions)
55+
{
56+
if ($exposedPermission.Value -eq $permission)
57+
{
58+
$resourceAccess = New-Object Microsoft.Open.AzureAD.Model.ResourceAccess
59+
$resourceAccess.Type = $permissionType # Scope = Delegated permissions | Role = Application permissions
60+
$resourceAccess.Id = $exposedPermission.Id # Read directory data
61+
$requiredAccess.ResourceAccess.Add($resourceAccess)
62+
}
63+
}
64+
}
65+
}
66+
67+
#
68+
# Example: GetRequiredPermissions "Microsoft Graph" "Graph.Read|User.Read"
69+
# See also: http://stackoverflow.com/questions/42164581/how-to-configure-a-new-azure-ad-application-through-powershell
70+
Function GetRequiredPermissions([string] $applicationDisplayName, [string] $requiredDelegatedPermissions, [string]$requiredApplicationPermissions, $servicePrincipal)
71+
{
72+
# If we are passed the service principal we use it directly, otherwise we find it from the display name (which might not be unique)
73+
if ($servicePrincipal)
74+
{
75+
$sp = $servicePrincipal
76+
}
77+
else
78+
{
79+
$sp = Get-AzureADServicePrincipal -Filter "DisplayName eq '$applicationDisplayName'"
80+
}
81+
$appid = $sp.AppId
82+
$requiredAccess = New-Object Microsoft.Open.AzureAD.Model.RequiredResourceAccess
83+
$requiredAccess.ResourceAppId = $appid
84+
$requiredAccess.ResourceAccess = New-Object System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.ResourceAccess]
85+
86+
# $sp.Oauth2Permissions | Select Id,AdminConsentDisplayName,Value: To see the list of all the Delegated permissions for the application:
87+
if ($requiredDelegatedPermissions)
88+
{
89+
AddResourcePermission $requiredAccess -exposedPermissions $sp.Oauth2Permissions -requiredAccesses $requiredDelegatedPermissions -permissionType "Scope"
90+
}
91+
92+
# $sp.AppRoles | Select Id,AdminConsentDisplayName,Value: To see the list of all the Application permissions for the application
93+
if ($requiredApplicationPermissions)
94+
{
95+
AddResourcePermission $requiredAccess -exposedPermissions $sp.AppRoles -requiredAccesses $requiredApplicationPermissions -permissionType "Role"
96+
}
97+
return $requiredAccess
98+
}
99+
100+
20101
Function UpdateLine([string] $line, [string] $value)
21102
{
22103
$index = $line.IndexOf('=')
@@ -56,13 +137,16 @@ Function UpdateTextFile([string] $configFilePath, [System.Collections.HashTable]
56137
Set-Content -Value "<html><body><table>" -Path createdApps.html
57138
Add-Content -Value "<thead><tr><th>Application</th><th>AppId</th><th>Url in the Azure portal</th></tr></thead><tbody>" -Path createdApps.html
58139

140+
$ErrorActionPreference = "Stop"
141+
59142
Function ConfigureApplications
60143
{
61144
<#.Description
62145
This function creates the Azure AD applications for the sample in the provided Azure AD tenant and updates the
63146
configuration files in the client and service project of the visual studio solution (App.Config and Web.Config)
64147
so that they are consistent with the Applications parameters
65148
#>
149+
$commonendpoint = "common"
66150

67151
# $tenantId is the Active Directory Tenant. This is a GUID which represents the "Directory ID" of the AzureAD tenant
68152
# into which you want to create the apps. Look it up in the Azure portal in the "Properties" of the Azure AD.
@@ -93,52 +177,74 @@ Function ConfigureApplications
93177
$tenant = Get-AzureADTenantDetail
94178
$tenantName = ($tenant.VerifiedDomains | Where { $_._Default -eq $True }).Name
95179

96-
# Get the user running the script
180+
# Get the user running the script to add the user as the app owner
97181
$user = Get-AzureADUser -ObjectId $creds.Account.Id
98182

99183
# Create the webApp AAD application
100184
Write-Host "Creating the AAD application (WebApp)"
185+
# Get a 2 years application key for the webApp Application
186+
$pw = ComputePassword
187+
$fromDate = [DateTime]::Now;
188+
$key = CreateAppKey -fromDate $fromDate -durationInYears 2 -pw $pw
189+
$webAppAppKey = $pw
190+
# create the application
101191
$webAppAadApplication = New-AzureADApplication -DisplayName "WebApp" `
102192
-HomePage "https://localhost:44321/" `
103193
-LogoutUrl "https://localhost:44321/signout-oidc" `
104194
-ReplyUrls "https://localhost:44321/", "https://localhost:44321/signin-oidc" `
105195
-IdentifierUris "https://$tenantName/WebApp" `
106196
-AvailableToOtherTenants $True `
197+
-PasswordCredentials $key `
107198
-Oauth2AllowImplicitFlow $true `
108199
-PublicClient $False
109200

201+
# create the service principal of the newly created application
110202
$currentAppId = $webAppAadApplication.AppId
111203
$webAppServicePrincipal = New-AzureADServicePrincipal -AppId $currentAppId -Tags {WindowsAzureActiveDirectoryIntegratedApp}
112204

113205
# add the user running the script as an app owner if needed
114206
$owner = Get-AzureADApplicationOwner -ObjectId $webAppAadApplication.ObjectId
115207
if ($owner -eq $null)
116208
{
117-
Add-AzureADApplicationOwner -ObjectId $webAppAadApplication.ObjectId -RefObjectId $user.ObjectId
118-
Write-Host "'$($user.UserPrincipalName)' added as an application owner to app '$($webAppServicePrincipal.DisplayName)'"
209+
Add-AzureADApplicationOwner -ObjectId $webAppAadApplication.ObjectId -RefObjectId $user.ObjectId
210+
Write-Host "'$($user.UserPrincipalName)' added as an application owner to app '$($webAppServicePrincipal.DisplayName)'"
119211
}
120212

213+
121214
Write-Host "Done creating the webApp application (WebApp)"
122215

123216
# URL of the AAD application in the Azure portal
124217
# Future? $webAppPortalUrl = "https://portal.azure.com/#@"+$tenantName+"/blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/"+$webAppAadApplication.AppId+"/objectId/"+$webAppAadApplication.ObjectId+"/isMSAApp/"
125218
$webAppPortalUrl = "https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/CallAnAPI/appId/"+$webAppAadApplication.AppId+"/objectId/"+$webAppAadApplication.ObjectId+"/isMSAApp/"
126219
Add-Content -Value "<tr><td>webApp</td><td>$currentAppId</td><td><a href='$webAppPortalUrl'>WebApp</a></td></tr>" -Path createdApps.html
127220

221+
$requiredResourcesAccess = New-Object System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.RequiredResourceAccess]
222+
223+
# Add Required Resources Access (from 'webApp' to 'Microsoft Graph')
224+
Write-Host "Getting access from 'webApp' to 'Microsoft Graph'"
225+
$requiredPermissions = GetRequiredPermissions -applicationDisplayName "Microsoft Graph" `
226+
-requiredDelegatedPermissions "Directory.Read.All" `
227+
228+
$requiredResourcesAccess.Add($requiredPermissions)
229+
230+
231+
Set-AzureADApplication -ObjectId $webAppAadApplication.ObjectId -RequiredResourceAccess $requiredResourcesAccess
232+
Write-Host "Granted permissions."
128233

129234
# Update config file for 'webApp'
130235
$configFile = $pwd.Path + "\..\appsettings.json"
131236
Write-Host "Updating the sample code ($configFile)"
132-
$dictionary = @{ "ClientId" = $webAppAadApplication.AppId;"TenantId" = "organizations";"Domain" = $tenantName };
237+
$dictionary = @{ "ClientId" = $webAppAadApplication.AppId;"TenantId" = "organizations";"Domain" = $tenantName;"ClientSecret" = $webAppAppKey };
133238
UpdateTextFile -configFilePath $configFile -dictionary $dictionary
134-
239+
135240
Add-Content -Value "</tbody></table></body></html>" -Path createdApps.html
136241
}
137242

138243
# Pre-requisites
139244
if ((Get-Module -ListAvailable -Name "AzureAD") -eq $null) {
140245
Install-Module "AzureAD" -Scope CurrentUser
141-
}
246+
}
247+
142248
Import-Module AzureAD
143249

144250
# Run interactively (will ask you for the tenant ID)

1-WebApp-OIDC/1-2-AnyOrg/NEW_README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
22
services: active-directory
33
platforms: dotnet
4-
author: jmprieur
5-
level: 100
4+
author: TiagoBrenck
5+
level: 400
66
client: ASP.NET Core Web App
77
endpoint: Microsoft identity platform
88
---
@@ -136,7 +136,7 @@ The sample implements two distinct tasks: the onboarding of a new tenant and a b
136136

137137
#### Sign-in
138138

139-
Users can only sign-in if their tenant has been onboarded. The sample will guide them for it, but it requires a **tenant admin account** to complete the onboarding process. Once the admin have consented, all users from their tenant will be able to sign-in.
139+
Users can only sign-in if their tenant had been onboarded. The sample will guide them for it, but it requires a **tenant admin account** to complete the onboarding process. Once the admin have consented, all users from their tenant will be able to sign-in.
140140

141141
#### Todo List
142142

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
{
2-
"AzureAd": {
3-
"Instance": "https://login.microsoftonline.com/",
4-
"Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]",
5-
"TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]",
6-
"ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]",
7-
"CallbackPath": "/signin-oidc",
8-
"SignedOutCallbackPath ": "/signout-callback-oidc"
9-
},
10-
"Logging": {
11-
"LogLevel": {
12-
"Default": "Warning"
13-
}
14-
},
15-
"AllowedHosts": "*",
2+
"AzureAd": {
3+
"Instance": "https://login.microsoftonline.com/",
4+
"Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]",
5+
"TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]",
6+
"ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]",
7+
"CallbackPath": "/signin-oidc",
8+
"SignedOutCallbackPath ": "/signout-callback-oidc",
9+
// To call an API
10+
"ClientSecret": "[Copy the client secret added to the app from the Azure portal]"
11+
},
12+
"ConnectionStrings": {
13+
"SampleDbConnStr": "Data Source=(LocalDb)\\MSSQLLocalDB;Database=MultiTenantOnboarding;Trusted_Connection=True;"
14+
},
15+
"Logging": {
16+
"LogLevel": {
17+
"Default": "Warning"
18+
}
19+
},
20+
"AllowedHosts": "*"
1621
}

0 commit comments

Comments
 (0)