Skip to content

Commit 0b2e10e

Browse files
committed
review changes
1 parent aa0ed92 commit 0b2e10e

File tree

5 files changed

+84
-125
lines changed

5 files changed

+84
-125
lines changed

5-AccessControl/2-call-api-groups/AppCreationScripts/Cleanup.ps1

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,7 @@ Import-Module Microsoft.Graph.Applications
9191
$ErrorActionPreference = "Stop"
9292

9393

94-
try
95-
{
96-
Cleanup -tenantId $tenantId -environment $azureEnvironmentName
97-
}
98-
catch
99-
{
100-
$_.Exception.ToString() | out-host
101-
$message = $_
102-
Write-Warning $Error[0]
103-
Write-Host "Unable to register apps. Error is $message." -ForegroundColor White -BackgroundColor Red
104-
}
94+
Cleanup -tenantId $tenantId -environment $azureEnvironmentName
10595

10696
Write-Host "Disconnecting from tenant"
10797
Disconnect-MgGraph

5-AccessControl/2-call-api-groups/AppCreationScripts/Configure.ps1

Lines changed: 13 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ Function ReplaceInTextFile([string] $configFilePath, [System.Collections.HashTab
115115

116116
Set-Content -Path $configFilePath -Value $lines -Force
117117
}
118+
118119
<#.Description
119120
This function creates a new Azure AD scope (OAuth2Permission) with default and provided values
120121
#>
@@ -132,25 +133,6 @@ Function CreateScope( [string] $value, [string] $userConsentDisplayName, [string
132133
return $scope
133134
}
134135

135-
<#.Description
136-
This function creates a new Azure AD AppRole with default and provided values
137-
#>
138-
Function CreateAppRole([string] $types, [string] $name, [string] $description)
139-
{
140-
$appRole = New-Object Microsoft.Graph.PowerShell.Models.MicrosoftGraphAppRole
141-
$appRole.AllowedMemberTypes = New-Object System.Collections.Generic.List[string]
142-
$typesArr = $types.Split(',')
143-
foreach($type in $typesArr)
144-
{
145-
$appRole.AllowedMemberTypes += $type;
146-
}
147-
$appRole.DisplayName = $name
148-
$appRole.Id = New-Guid
149-
$appRole.IsEnabled = $true
150-
$appRole.Description = $description
151-
$appRole.Value = $name;
152-
return $appRole
153-
}
154136
Function CreateOptionalClaim([string] $name)
155137
{
156138
<#.Description
@@ -287,40 +269,29 @@ Function ConfigureApplications
287269
# URL of the AAD application in the Azure portal
288270
# Future? $clientPortalUrl = "https://portal.azure.com/#@"+$tenantName+"/blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/Overview/appId/"+$clientAadApplication.AppId+"/objectId/"+$clientAadApplication.Id+"/isMSAApp/"
289271
$clientPortalUrl = "https://portal.azure.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/CallAnAPI/appId/"+$clientAadApplication.AppId+"/objectId/"+$clientAadApplication.Id+"/isMSAApp/"
290-
291272
Add-Content -Value "<tr><td>client</td><td>$currentAppId</td><td><a href='$clientPortalUrl'>msal-angular-app</a></td></tr>" -Path createdApps.html
292-
# Declare a list to hold RRA items
293-
273+
$requiredResourcesAccess = New-Object System.Collections.Generic.List[Microsoft.Graph.PowerShell.Models.MicrosoftGraphRequiredResourceAccess]
274+
294275
# Add Required Resources Access (from 'client' to 'client')
295276
Write-Host "Getting access from 'client' to 'client'"
296-
$requiredPermission = GetRequiredPermissions -applicationDisplayName "msal-angular-app"`
297-
-requiredDelegatedPermissions "access_via_group_assignments"
298-
$requiredResourcesAccess = New-Object System.Collections.Generic.List[Microsoft.Graph.PowerShell.Models.MicrosoftGraphRequiredResourceAccess]
277+
$requiredPermission = GetRequiredPermissions -applicationDisplayName "msal-angular-app" `
278+
-requiredDelegatedPermissions "access_via_group_assignments" `
279+
299280
$requiredResourcesAccess.Add($requiredPermission)
300-
Write-Host "Added 'client' to the RRA list."
301-
# Useful for RRA troubleshooting
302-
# $requiredResourcesAccess.Count
303-
# $requiredResourcesAccess
304281

305-
306282
# Add Required Resources Access (from 'client' to 'Microsoft Graph')
307283
Write-Host "Getting access from 'client' to 'Microsoft Graph'"
308-
$requiredPermission = GetRequiredPermissions -applicationDisplayName "Microsoft Graph"`
309-
-requiredDelegatedPermissions "User.Read|GroupMember.Read.All"
310-
$requiredResourcesAccess = New-Object System.Collections.Generic.List[Microsoft.Graph.PowerShell.Models.MicrosoftGraphRequiredResourceAccess]
284+
$requiredPermission = GetRequiredPermissions -applicationDisplayName "Microsoft Graph" `
285+
-requiredDelegatedPermissions "User.Read|GroupMember.Read.All" `
286+
311287
$requiredResourcesAccess.Add($requiredPermission)
312-
Write-Host "Added 'Microsoft Graph' to the RRA list."
313-
# Useful for RRA troubleshooting
314-
# $requiredResourcesAccess.Count
315-
# $requiredResourcesAccess
316-
317288
Update-MgApplication -ApplicationId $clientAadApplication.Id -RequiredResourceAccess $requiredResourcesAccess
318289
Write-Host "Granted permissions."
319290

291+
Write-Host "Successfully registered and configured that app registration for 'msal-angular-app' at" -ForegroundColor Green
292+
320293
# print the registered app portal URL for any further navigation
321-
Write-Host "Successfully registered and configured that app registration for 'msal-angular-app' at `n $clientPortalUrl"
322-
323-
294+
$clientPortalUrl
324295
Function UpdateLine([string] $line, [string] $value)
325296
{
326297
$index = $line.IndexOf(':')
@@ -363,7 +334,6 @@ Function UpdateTextFile([string] $configFilePath, [System.Collections.HashTable]
363334

364335
Write-Host "Updating the sample config '$configFile' with the following config values:"
365336
$dictionary
366-
Write-Host "-----------------"
367337

368338
ReplaceInTextFile -configFilePath $configFile -dictionary $dictionary
369339

@@ -375,16 +345,14 @@ Function UpdateTextFile([string] $configFilePath, [System.Collections.HashTable]
375345

376346
Write-Host "Updating the sample config '$configFile' with the following config values:"
377347
$dictionary
378-
Write-Host "-----------------"
379348

380349
ReplaceInTextFile -configFilePath $configFile -dictionary $dictionary
381350
Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
382351
Write-Host "IMPORTANT: Please follow the instructions below to complete a few manual step(s) in the Azure portal":
383352
Write-Host "- For client"
384353
Write-Host " - Navigate to $clientPortalUrl"
385354
Write-Host " - On Azure portal, create a security group named 'GroupAdmin' and assign some users to it. Afterwards, update the configuration files with the Object ID of the gruop you've just created." -ForegroundColor Red
386-
Write-Host " - On Azure portal, create a security group named 'GroupMember' and assign some users to it. Afterwards, update the configuration files with the Object ID of the gruop you've just created." -ForegroundColor Red
387-
Write-Host " - Security groups matching the names you provided have been created in this tenant (if not present already). On Azure portal, assign some users to it, and configure ID & Access tokens to emit Group IDs" -ForegroundColor Red
355+
Write-Host " - On Azure portal, create a security group named 'GroupMember' and assign some users to it. Afterwards, update the configuration files with the Object ID of the gruop you've just created." -ForegroundColor Red
388356
Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
389357
if($isOpenSSL -eq 'Y')
390358
{
@@ -416,7 +384,6 @@ try
416384
}
417385
catch
418386
{
419-
$_.Exception.ToString() | out-host
420387
$message = $_
421388
Write-Warning $Error[0]
422389
Write-Host "Unable to register apps. Error is $message." -ForegroundColor White -BackgroundColor Red

5-AccessControl/2-call-api-groups/AppCreationScripts/sample.json

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"Service": ".NET Core web API",
77
"RepositoryUrl": "ms-identity-javascript-angular-tutorial",
88
"Endpoint": "AAD v2.0",
9-
"platform":"javascript",
9+
"platform": "javascript",
1010
"Languages": [
1111
"typescript",
1212
"csharp",
@@ -22,61 +22,61 @@
2222
]
2323
},
2424
"AADApps": [
25-
{
26-
"Id": "client",
27-
"Name": "msal-angular-app",
28-
"Kind": "SinglePageApplication",
29-
"Audience": "AzureADMyOrg",
30-
"HomePage": "http://localhost:4200/",
31-
"ReplyUrls": "http://localhost:4200/, http://localhost:4200/auth",
32-
"GroupMembershipClaims": "SecurityGroup",
33-
"PasswordCredentials": "Auto",
34-
"Scopes": [
35-
"access_via_group_assignments"
36-
],
37-
"Sample": {
38-
"SampleSubPath": "5-AccessControl\\2-call-api-groups\\SPA",
39-
"ProjectDirectory": "\\2-call-api-groups\\SPA"
40-
},
41-
"SecurityGroups": [
42-
{
43-
"Name": "GroupAdmin",
44-
"Description": "Admin Security Group"
45-
},
46-
{
47-
"Name": "GroupMember",
48-
"Description": "User Security Group"
49-
}
50-
],
51-
"RequiredResourcesAccess": [
52-
{
53-
"Resource": "client",
54-
"DelegatedPermissions": [
55-
"access_via_group_assignments"
56-
]
57-
},
58-
{
59-
"Resource": "Microsoft Graph",
60-
"DelegatedPermissions": [
61-
"User.Read",
62-
"GroupMember.Read.All"
25+
{
26+
"Id": "client",
27+
"Name": "msal-angular-app",
28+
"Kind": "SinglePageApplication",
29+
"Audience": "AzureADMyOrg",
30+
"HomePage": "http://localhost:4200/",
31+
"ReplyUrls": "http://localhost:4200/, http://localhost:4200/auth",
32+
"GroupMembershipClaims": "SecurityGroup",
33+
"PasswordCredentials": "Auto",
34+
"Scopes": [
35+
"access_via_group_assignments"
36+
],
37+
"Sample": {
38+
"SampleSubPath": "5-AccessControl\\2-call-api-groups\\SPA",
39+
"ProjectDirectory": "\\2-call-api-groups\\SPA"
40+
},
41+
"SecurityGroups": [
42+
{
43+
"Name": "GroupAdmin",
44+
"Description": "Admin Security Group"
45+
},
46+
{
47+
"Name": "GroupMember",
48+
"Description": "User Security Group"
49+
}
50+
],
51+
"RequiredResourcesAccess": [
52+
{
53+
"Resource": "client",
54+
"DelegatedPermissions": [
55+
"access_via_group_assignments"
56+
]
57+
},
58+
{
59+
"Resource": "Microsoft Graph",
60+
"DelegatedPermissions": [
61+
"User.Read",
62+
"GroupMember.Read.All"
63+
]
64+
}
65+
],
66+
"OptionalClaims": {
67+
"IdTokenClaims": [
68+
"acct"
69+
]
70+
},
71+
"ManualSteps": [
72+
{
73+
"Comment": "On Azure portal, create a security group named 'GroupAdmin' and assign some users to it. Afterwards, update the configuration files with the Object ID of the gruop you've just created."
74+
},
75+
{
76+
"Comment": "On Azure portal, create a security group named 'GroupMember' and assign some users to it. Afterwards, update the configuration files with the Object ID of the gruop you've just created."
77+
}
6378
]
64-
}
65-
],
66-
"OptionalClaims": {
67-
"IdTokenClaims": [
68-
"acct"
69-
]
70-
},
71-
"ManualSteps": [
72-
{
73-
"Comment": "On Azure portal, create a security group named 'GroupAdmin' and assign some users to it. Afterwards, update the configuration files with the Object ID of the gruop you've just created."
74-
},
75-
{
76-
"Comment": "On Azure portal, create a security group named 'GroupMember' and assign some users to it. Afterwards, update the configuration files with the Object ID of the gruop you've just created."
77-
}
78-
]
79-
}
79+
}
8080
],
8181
"CodeConfiguration": [
8282
{

5-AccessControl/2-call-api-groups/README.md

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
---
22
page_type: sample
3-
services: ms-identity
4-
client: Angular SPA
5-
service: .NET Core web API
63
level: 300
74
languages:
85
- typescript
@@ -14,14 +11,12 @@ products:
1411
- msal-js
1512
- msal-angular
1613
- microsoft-identity-web
17-
platform: javascript
18-
endpoint: AAD v2.0
1914
urlFragment: ms-identity-javascript-angular-tutorial
20-
name: Angular single-page application calling a protected AspNet Core web API and using Security Groups to implement Role-Based Access Control
21-
description: Angular single-page application calling a protected AspNet web API and using Security Groups to implement Role-Based Access Control (RBAC)
15+
name: Angular single-page application calling a protected ASP.NET Core web API using Security Groups to implement Role-Based Access Control
16+
description: Angular single-page application calling a protected ASP.NET Core web API using Security Groups to implement Role-Based Access Control (RBAC)
2217
---
2318

24-
# Angular single-page application calling a protected AspNet Core web API and using Security Groups to implement Role-Based Access Control
19+
# Angular single-page application calling a protected ASP.NET Core web API using Security Groups to implement Role-Based Access Control
2520

2621
* [Overview](#overview)
2722
* [Scenario](#scenario)
@@ -38,7 +33,7 @@ description: Angular single-page application calling a protected AspNet web API
3833

3934
This sample demonstrates a cross-platform application suite involving an Angular single-page application (*TodoListSPA*) calling an ASP.NET Core web API (*TodoListAPI*) secured with the Microsoft identity platform. In doing so, it implements **Role-based Access Control** (RBAC) by using Azure AD **Security Groups**.
4035

41-
Access control in Azure AD can also be done with, **App Roles** (see the [previous tutorial](../1-call-api-roles/README.md)) and/or **Delegated Permissions**. **Security Groups**, **App Roles** and **Delegated Permissions** in Azure AD are by no means mutually exclusive - they can be used in tandem to provide even finer grained access control.
36+
Access control in Azure AD can also be done with, **App Roles** (see the [previous tutorial](../1-call-api-roles/README.md)) and/or **Delegated Permissions**. **Security Groups**, **App Roles** and **Delegated Permissions** in Azure AD are by no means mutually exclusive -they can be used in tandem to provide even finer grained access control.
4237

4338
In the sample, a dashboard component allows signed-in users to see the tasks assigned to them or other users based on their memberships to one of the two security groups, **GroupAdmin** and **GroupMember**.
4439

@@ -176,7 +171,6 @@ To manually register the apps, as a first step you'll need to:
176171
1. Select one of the available key durations (**6 months**, **12 months** or **Custom**) as per your security posture.
177172
1. The generated key value will be displayed when you select the **Add** button. Copy and save the generated value for use in later steps.
178173
1. You'll need this key later in your code's configuration files. This key value will not be displayed again, and is not retrievable by any other means, so make sure to note it from the Azure portal before navigating to any other screen or blade.
179-
> :bulb: For enhanced security, instead of using client secrets, consider [using certificates](./README-use-certificate.md) and [Azure KeyVault](https://azure.microsoft.com/services/key-vault/#product-overview).
180174
1. In the app's registration screen, select the **Expose an API** blade to the left to open the page where you can publish the permission as an API for which client applications can obtain [access tokens](https://aka.ms/access-tokens) for. The first thing that we need to do is to declare the unique [resource](https://docs.microsoft.com/azure/active-directory/develop/v2-oauth2-auth-code-flow) URI that the clients will be using to obtain access tokens for this API. To declare an resource URI(Application ID URI), follow the following steps:
181175
1. Select **Set** next to the **Application ID URI** to generate a URI that is unique for this app.
182176
1. For this sample, accept the proposed Application ID URI (`api://{clientId}`) by selecting **Save**. Read more about Application ID URI at [Validation differences by supported account types \(signInAudience\)](https://docs.microsoft.com/azure/active-directory/develop/supported-accounts-validation).
@@ -390,15 +384,17 @@ If a user is member of more groups than the overage limit (**150 for SAML tokens
390384
391385
#### Create the Overage scenario for testing
392386

393-
1. You can use the `BulkCreateGroups.ps1` provided in the [App Creation Scripts](./AppCreationScripts/) folder to create a large number of groups and assign users to them. This will help test overage scenarios during development. You'll need to enter a user Object ID when prompted by the `BulkCreateGroups.ps1` script.
387+
1. You can use the [BulkCreateGroups.ps1](./AppCreationScripts/BulkCreateGroups.ps1) provided in the [App Creation Scripts](./AppCreationScripts/) folder to create a large number of groups and assign users to them. This will help test overage scenarios during development. You'll need to enter a user Object ID when prompted by the `BulkCreateGroups.ps1` script. If you would like to delete these groups, run the [BulkRemoveGroups.ps1](./AppCreationScripts/BulkRemoveGroups.ps1) after testing the overage scenario.
388+
389+
When overage occurs, the user's ID and/or access token will not gave the **groups** claim. Instead, a new claim named **_claim_names** will appear. This confirms that the overage scenario is reproduced.
394390

395391
When attending to overage scenarios, which requires a call to [Microsoft Graph](https://graph.microsoft.com) to read the signed-in user's group memberships, your app will need to have the [User.Read](https://docs.microsoft.com/graph/permissions-reference#user-permissions) and [GroupMember.Read.All](https://docs.microsoft.com/graph/permissions-reference#group-permissions) for the [getMemberGroups](https://docs.microsoft.com/graph/api/user-getmembergroups) API to execute successfully.
396392

397393
> :warning: For the overage scenario, make sure you have granted **Admin Consent** for the MS Graph API's **GroupMember.Read.All** scope (see the **App Registration** steps above).
398394
399395
##### Angular GroupGuard service
400396

401-
Consider the [group.guard.ts](./SPA/src/app/group.guard.ts). Here, we are checking whether the token for the user has the `_claim_names` claim, which indicates that the user has too many group memberships. If so, we redirect the user to the [overage](./SPA/src/app/overage/overage.component.ts) component. There, we initiate a call to MS Graph API's `https://graph.microsoft.com/v1.0/me/memberOf` endpoint to query the full list of groups that the user belongs to. Finally we check for the designated `groupID` among this list.
397+
Consider the [group.guard.ts](./SPA/src/app/group.guard.ts). Here, we are checking whether the token for the user's ID token has the `_claim_names` claim, which indicates that the user has too many group memberships. If so, we redirect the user to the [overage](./SPA/src/app/overage/overage.component.ts) component. There, we initiate a call to MS Graph API's `https://graph.microsoft.com/v1.0/me/memberOf` endpoint to query the full list of groups that the user belongs to. Finally we check for the designated `groupID` among this list.
402398

403399
```typescript
404400
@Injectable()

0 commit comments

Comments
 (0)