Skip to content

Commit 1bc7227

Browse files
authored
Merge pull request #388 from Azure-Samples/Shama-K/GroupMemberPermission
Permission update from Directory.Read.All to GroupMember.Read.All and Handled Groups Overage Scenario
2 parents c834e5c + 33368eb commit 1bc7227

30 files changed

+943
-896
lines changed

.github/ISSUE_TEMPLATE.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ Please add an 'x' for the scenario(s) where you found an issue
2727
1. [ ] With specific token caches: [2-WebApp-graph-user/2-2-TokenCache](../blob/master/2-WebApp-graph-user/2-2-TokenCache)
2828
1. [ ] Calling Microsoft Graph in national clouds: [2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph](../blob/master/2-WebApp-graph-user/2-4-Sovereign-Call-MSGraph)
2929
1. [ ] Web app calling several APIs [3-WebApp-multi-APIs](../blob/master/3-WebApp-multi-APIs)
30-
1. [ ] Web app calling your own Web API [4-WebApp-your-API](../blob/master/4-WebApp-your-API)
30+
1. [ ] Web app calling your own Web API
31+
1. [ ] with a work and school account in your organization: [4-WebApp-your-API/4-1-MyOrg](../blob/master/4-WebApp-your-API/4-1-MyOrg)
32+
1. [ ] with B2C users: [4-WebApp-your-API/4-2-B2C](../blob/master/4-WebApp-your-API/4-2-B2C)
33+
1. [ ] with any work and school account: [4-WebApp-your-API/4-3-AnyOrg](../blob/master/4-WebApp-your-API/4-3-AnyOrg)
3134
1. Web app restricting users
3235
1. [ ] by Roles: [5-WebApp-AuthZ/5-1-Roles](../blob/master/5-WebApp-AuthZ/5-1-Roles)
3336
1. [ ] by Groups: [5-WebApp-AuthZ/5-2-Groups](../blob/master/5-WebApp-AuthZ/5-2-Groups)

5-WebApp-AuthZ/5-2-Groups/AppCreationScripts/AppCreationScripts.md

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,47 @@
1-
# Registering the sample apps with Microsoft identity platform and updating the configuration files using PowerShell scripts
1+
# Registering the sample apps with the Microsoft identity platform and updating the configuration files using PowerShell
22

33
## Overview
44

55
### Quick summary
66

7-
1. On Windows run PowerShell and navigate to the root of the cloned directory
7+
1. On Windows run PowerShell as **Administrator** and navigate to the root of the cloned directory
88
1. In PowerShell run:
9+
910
```PowerShell
1011
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force
1112
```
13+
1214
1. Run the script to create your Azure AD application and configure the code of the sample application accordingly. (Other ways of running the scripts are described below)
15+
1316
```PowerShell
1417
cd .\AppCreationScripts\
1518
.\Configure.ps1
1619
```
20+
1721
1. Open the Visual Studio solution and click start
1822

1923
### More details
2024

2125
The following paragraphs:
2226

23-
- [Present the scripts](#presentation-of-the-scripts) and explain their [usage patterns](#usage-pattern-for-tests-and-devops-scenarios) for test and DevOps scenarios.
24-
- Explain the [pre-requisites](#pre-requisites)
25-
- Explain [four ways of running the scripts](#four-ways-to-run-the-script):
26-
- [Interactively](#option-1-interactive) to create the app in your home tenant
27-
- [Passing credentials](#option-2-non-interactive) to create the app in your home tenant
28-
- [Interactively in a specific tenant](#option-3-interactive-but-create-apps-in-a-specified-tenant)
29-
- [Passing credentials in a specific tenant](#option-4-non-interactive-and-create-apps-in-a-specified-tenant)
30-
- [Passing environment name, for Sovereign clouds](#running-the-script-on-azure-sovereign-clouds)
31-
32-
## Goal of the scripts
27+
- [Registering the sample apps with the Microsoft identity platform and updating the configuration files using PowerShell](#Registering-the-sample-apps-with-the-Microsoft-identity-platform-and-updating-the-configuration-files-using-PowerShell)
28+
- [Overview](#Overview)
29+
- [Quick summary](#Quick-summary)
30+
- [More details](#More-details)
31+
- [Goal of the provided scripts](#Goal-of-the-provided-scripts)
32+
- [Presentation of the scripts](#Presentation-of-the-scripts)
33+
- [Usage pattern for tests and DevOps scenarios](#Usage-pattern-for-tests-and-DevOps-scenarios)
34+
- [How to use the app creation scripts?](#How-to-use-the-app-creation-scripts)
35+
- [Pre-requisites](#Pre-requisites)
36+
- [Run the script and start running](#Run-the-script-and-start-running)
37+
- [Four ways to run the script](#Four-ways-to-run-the-script)
38+
- [Option 1 (interactive)](#Option-1-interactive)
39+
- [Option 2 (non-interactive)](#Option-2-non-interactive)
40+
- [Option 3 (Interactive, but create apps in a specified tenant)](#Option-3-Interactive-but-create-apps-in-a-specified-tenant)
41+
- [Option 4 (non-interactive, and create apps in a specified tenant)](#Option-4-non-interactive-and-create-apps-in-a-specified-tenant)
42+
- [Running the script on Azure Sovereign clouds](#Running-the-script-on-Azure-Sovereign-clouds)
43+
44+
## Goal of the provided scripts
3345

3446
### Presentation of the scripts
3547

@@ -56,36 +68,43 @@ The `Configure.ps1` will stop if it tries to create an Azure AD application whic
5668
### Pre-requisites
5769

5870
1. Open PowerShell (On Windows, press `Windows-R` and type `PowerShell` in the search window)
59-
2. Navigate to the root directory of the project.
60-
3. Until you change it, the default [Execution Policy](https:/go.microsoft.com/fwlink/?LinkID=135170) for scripts is usually `Restricted`. In order to run the PowerShell script you need to set the Execution Policy to `RemoteSigned`. You can set this just for the current PowerShell process by running the command:
71+
1. Navigate to the root directory of the project.
72+
1. Until you change it, the default [Execution Policy](https:/go.microsoft.com/fwlink/?LinkID=135170) for scripts is usually `Restricted`. In order to run the PowerShell script you need to set the Execution Policy to `RemoteSigned`. You can set this just for the current PowerShell process by running the command:
73+
6174
```PowerShell
6275
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
6376
```
64-
### (Optionally) install AzureAD PowerShell modules
77+
78+
1. ### (Optionally) install AzureAD PowerShell modules
79+
2.
6580
The scripts install the required PowerShell module (AzureAD) for the current user if needed. However, if you want to install if for all users on the machine, you can follow the following steps:
6681
67-
4. If you have never done it already, in the PowerShell window, install the AzureAD PowerShell modules. For this:
82+
1. If you have never done it already, in the PowerShell window, install the AzureAD PowerShell modules. For this:
6883
6984
1. Open PowerShell as admin (On Windows, Search Powershell in the search bar, right click on it and select Run as administrator).
7085
2. Type:
86+
7187
```PowerShell
7288
Install-Module AzureAD
7389
```
7490
7591
or if you cannot be administrator on your machine, run:
92+
7693
```PowerShell
7794
Install-Module AzureAD -Scope CurrentUser
7895
```
7996
8097
### Run the script and start running
8198
82-
5. Go to the `AppCreationScripts` sub-folder. From the folder where you cloned the repo,
99+
1. Go to the `AppCreationScripts` sub-folder. From the folder where you cloned the repo,
100+
83101
```PowerShell
84102
cd AppCreationScripts
85103
```
86-
6. Run the scripts. See below for the [four options](#four-ways-to-run-the-script) to do that.
87-
7. Open the Visual Studio solution, and in the solution's context menu, choose **Set Startup Projects**.
88-
8. select **Start** for the projects
104+
105+
1. Run the scripts. See below for the [four options](#four-ways-to-run-the-script) to do that.
106+
1. Open the Visual Studio solution, and in the solution's context menu, choose **Set Startup Projects**.
107+
1. select **Start** for the projects
89108
90109
You're done. this just works!
91110
@@ -123,6 +142,7 @@ Of course, in real life, you might already get the password as a `SecureString`.
123142
#### Option 3 (Interactive, but create apps in a specified tenant)
124143

125144
if you want to create the apps in a particular tenant, you can use the following option:
145+
126146
- open the [Azure portal](https://portal.azure.com)
127147
- Select the Azure Active directory you are interested in (in the combo-box below your name on the top right of the browser window)
128148
- Find the "Active Directory" object in this tenant

5-WebApp-AuthZ/5-2-Groups/AppCreationScripts/BulkCreateGroups.ps1

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
$ErrorActionPreference = "Stop"
88

9+
# ObjectId of the user to be assigned to these security groups. The ObjectId can be obtained via Graph Explorer or in the "Users" blade on the portal.
10+
$usersobjectId = "695a3e1d-2e9f-4d24-aa3c-ac795c16f25c"
11+
912
Get-AzureADUser -ObjectId $usersobjectId
1013

11-
# ObjectId of the user to be assigned to these security groups. The ObjectId can be obtained via Graph Explorer or in the "Users" blade on the portal.
12-
$usersobjectId = "5b6e08a5-7789-4ae0-a4cb-3d73b4097752"
1314
$groupNamePrefix = "TestGroup"
1415
$numberOfGroupsToCreate = 222;
1516

5-WebApp-AuthZ/5-2-Groups/AppCreationScripts/BulkRemoveGroups.ps1

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ $numberOfGroupsToDelete = 222;
1010
for($i = 1; $i -le $numberOfGroupsToDelete; $i++)
1111
{
1212
$groupName = $groupNamePrefix + $i
13-
$group = Get-AzureADGroup -SearchString $groupName
14-
Remove-AzureADGroup -ObjectId $group.ObjectId
15-
Write-Host "Successfully deleted $($group.DisplayName)"
13+
$groups = Get-AzureADGroup -SearchString $groupName
14+
15+
Foreach ($group in $groups)
16+
{
17+
Write-Host "Trying to delete group $($group.DisplayName)"
18+
Remove-AzureADGroup -ObjectId $group.ObjectId
19+
Write-Host "Successfully deleted $($group.DisplayName)"
20+
}
1621
}

5-WebApp-AuthZ/5-2-Groups/AppCreationScripts/Cleanup.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ param(
77
[string] $azureEnvironmentName
88
)
99

10-
#Requires -Modules AzureAD
10+
#Requires -Modules AzureAD -RunAsAdministrator
1111

1212

1313
if ($null -eq (Get-Module -ListAvailable -Name "AzureAD")) {

5-WebApp-AuthZ/5-2-Groups/AppCreationScripts/Configure.ps1

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ param(
77
[string] $azureEnvironmentName
88
)
99

10-
#Requires -Modules AzureAD
10+
#Requires -Modules AzureAD -RunAsAdministrator
1111

1212
<#
1313
This script creates the Azure AD applications needed for this sample and updates the configuration files
@@ -206,7 +206,6 @@ Function ConfigureApplications
206206
-IdentifierUris "https://$tenantName/WebApp-GroupClaims" `
207207
-PasswordCredentials $key `
208208
-GroupMembershipClaims "SecurityGroup" `
209-
-Oauth2AllowImplicitFlow $true `
210209
-PublicClient $False
211210

212211
# create the service principal of the newly created application
@@ -234,7 +233,7 @@ Function ConfigureApplications
234233
# Add Required Resources Access (from 'webApp' to 'Microsoft Graph')
235234
Write-Host "Getting access from 'webApp' to 'Microsoft Graph'"
236235
$requiredPermissions = GetRequiredPermissions -applicationDisplayName "Microsoft Graph" `
237-
-requiredDelegatedPermissions "Directory.Read.All" `
236+
-requiredDelegatedPermissions "User.Read|GroupMember.Read.All" `
238237

239238
$requiredResourcesAccess.Add($requiredPermissions)
240239

@@ -244,10 +243,21 @@ Function ConfigureApplications
244243

245244
# Update config file for 'webApp'
246245
$configFile = $pwd.Path + "\..\appsettings.json"
246+
247247
Write-Host "Updating the sample code ($configFile)"
248248
$dictionary = @{ "ClientId" = $webAppAadApplication.AppId;"TenantId" = $tenantId;"Domain" = $tenantName;"ClientSecret" = $webAppAppKey };
249249
UpdateTextFile -configFilePath $configFile -dictionary $dictionary
250-
250+
Write-Host ""
251+
Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
252+
Write-Host "IMPORTANT: Please follow the instructions below to complete a few manual step(s) in the Azure portal":
253+
Write-Host "- For 'webApp'"
254+
Write-Host " - Navigate to '$webAppPortalUrl'"
255+
Write-Host " - Navigate to the API Permissions page and select 'Grant admin consent for (your tenant)'" -ForegroundColor Red
256+
Write-Host " - On Azure Portal, create a security group named GroupAdmin, assign some users to it, and configure your ID and Access token to emit GroupID in your app registration. Configure the value for 'GroupAdmin' key in appsettings.json." -ForegroundColor Red
257+
Write-Host " - On Azure Portal, create a security group named GroupMember, assign some users to it, and configure your ID and Access token to emit GroupID in your app registration. Configure the value for 'GroupMember' key in appsettings.json." -ForegroundColor Red
258+
259+
Write-Host -ForegroundColor Green "------------------------------------------------------------------------------------------------"
260+
251261
Add-Content -Value "</tbody></table></body></html>" -Path createdApps.html
252262
}
253263

5-WebApp-AuthZ/5-2-Groups/AppCreationScripts/sample.json

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,18 @@
2525
"RequiredResourcesAccess": [
2626
{
2727
"Resource": "Microsoft Graph",
28-
"DelegatedPermissions": [ "Directory.Read.All" ]
28+
"DelegatedPermissions": [ "User.Read", "GroupMember.Read.All" ]
29+
}
30+
],
31+
"ManualSteps": [
32+
{
33+
"Comment": "Navigate to the API Permissions page and select 'Grant admin consent for (your tenant)'"
34+
},
35+
{
36+
"Comment": "On Azure Portal, create a security group named GroupAdmin, assign some users to it, and configure your ID and Access token to emit GroupID in your app registration. Configure the value for 'GroupAdmin' key in appsettings.json."
37+
},
38+
{
39+
"Comment": "On Azure Portal, create a security group named GroupMember, assign some users to it, and configure your ID and Access token to emit GroupID in your app registration. Configure the value for 'GroupMember' key in appsettings.json."
2940
}
3041
]
3142
}
@@ -40,7 +51,7 @@
4051
"CodeConfiguration": [
4152
{
4253
"App": "webApp",
43-
"SettingKind": "JSon",
54+
"SettingKind": "JSON",
4455
"SettingFile": "\\..\\appsettings.json",
4556
"Mappings": [
4657
{
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Microsoft.AspNetCore.Authorization;
2+
using Microsoft.AspNetCore.Mvc;
3+
4+
namespace WebApp_OpenIDConnect_DotNet.Controllers
5+
{
6+
public class AccountController : Controller
7+
{
8+
[Authorize]
9+
public IActionResult SignOut()
10+
{
11+
HttpContext.Session.Clear();
12+
return RedirectToAction("SignOut", "Account", new { area = "MicrosoftIdentity" });
13+
}
14+
}
15+
}

5-WebApp-AuthZ/5-2-Groups/Controllers/HomeController.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using Microsoft.AspNetCore.Authorization;
22
using Microsoft.AspNetCore.Mvc;
33
using System.Diagnostics;
4-
using System.Security.Claims;
54
using WebApp_OpenIDConnect_DotNet.Models;
5+
using Microsoft.AspNetCore.Http;
6+
using WebApp_OpenIDConnect_DotNet.Services;
67

78
namespace WebApp_OpenIDConnect_DotNet.Controllers
89
{
@@ -16,14 +17,21 @@ public HomeController()
1617
public IActionResult Index()
1718
{
1819
ViewData["User"] = HttpContext.User;
20+
21+
// Calls method GetSessionGroupList to get groups from session.
22+
var groups = GraphHelper.GetUserGroupsFromSession(HttpContext.Session);
23+
if (groups?.Count > 0)
24+
{
25+
ViewData.Add("groupClaims", groups );
26+
}
1927
return View();
2028
}
2129

2230
[AllowAnonymous]
2331
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
2432
public IActionResult Error()
2533
{
26-
return View(new ErrorViewModel {RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier});
34+
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
2735
}
2836
}
2937
}

5-WebApp-AuthZ/5-2-Groups/Controllers/UserProfileController.cs

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
using Microsoft.AspNetCore.Mvc;
33
using Microsoft.Graph;
44
using Microsoft.Identity.Web;
5-
using System.Collections.Generic;
65
using System.Threading.Tasks;
7-
using WebApp_OpenIDConnect_DotNet.Services.MicrosoftGraph;
86
using Constants = WebApp_OpenIDConnect_DotNet.Infrastructure.Constants;
97

108
namespace WebApp_OpenIDConnect_DotNet.Controllers
@@ -13,39 +11,28 @@ namespace WebApp_OpenIDConnect_DotNet.Controllers
1311
//[Authorize(Roles = "8873daa2-17af-4e72-973e-930c94ef7549")]
1412
public class UserProfileController : Controller
1513
{
16-
private readonly ITokenAcquisition tokenAcquisition;
17-
private readonly IMSGraphService graphService;
14+
private readonly GraphServiceClient graphServiceClient;
1815

19-
public UserProfileController(ITokenAcquisition tokenAcquisition, IMSGraphService MSGraphService)
16+
public UserProfileController(GraphServiceClient graphServiceClient)
2017
{
21-
this.tokenAcquisition = tokenAcquisition;
22-
this.graphService = MSGraphService;
18+
this.graphServiceClient= graphServiceClient;
2319
}
24-
25-
[AuthorizeForScopes(Scopes = new[] { Constants.ScopeUserRead, Constants.ScopeDirectoryReadAll })]
20+
[Authorize(Policy = "GroupAdmin")]
21+
[AuthorizeForScopes(Scopes = new[] { Constants.ScopeUserRead })]
2622
public async Task<IActionResult> Index()
2723
{
28-
// This is how group ids/names are used in the IsInRole method
29-
// var isinrole = User.IsInRole("8873daa2-17af-4e72-973e-930c94ef7549");
30-
31-
string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new[] { Constants.ScopeUserRead, Constants.ScopeDirectoryReadAll });
32-
33-
User me = await graphService.GetMeAsync(accessToken);
24+
User me = await graphServiceClient.Me.Request().GetAsync();
3425
ViewData["Me"] = me;
3526

3627
try
3728
{
38-
var photo = await graphService.GetMyPhotoAsync(accessToken);
29+
var photo = await graphServiceClient.Me.Photo.Request().GetAsync();
3930
ViewData["Photo"] = photo;
4031
}
4132
catch
4233
{
4334
//swallow
4435
}
45-
46-
IList<Group> groups = await graphService.GetMyMemberOfGroupsAsync(accessToken);
47-
ViewData["Groups"] = groups;
48-
4936
return View();
5037
}
5138
}

5-WebApp-AuthZ/5-2-Groups/Infrastructure/Constants.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ namespace WebApp_OpenIDConnect_DotNet.Infrastructure
33
public static class Constants
44
{
55
public const string ScopeUserRead = "User.Read";
6-
public const string ScopeDirectoryReadAll = "Directory.Read.All";
6+
7+
public const string ScopeGroupMemberRead = "GroupMember.Read.All";
78

89
public const string BearerAuthorizationScheme = "Bearer";
910
}

0 commit comments

Comments
 (0)