{"id":2156,"date":"2018-11-19T11:00:51","date_gmt":"2018-11-19T11:00:51","guid":{"rendered":"https:\/\/developer.microsoft.com\/en-us\/office\/blogs\/?p=2156"},"modified":"2018-11-19T11:00:51","modified_gmt":"2018-11-19T11:00:51","slug":"30daysmsgraph-day-19-use-case-assign-permissions-using-unified-groups","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/30daysmsgraph-day-19-use-case-assign-permissions-using-unified-groups\/","title":{"rendered":"30DaysMSGraph \u2013 Day 19 \u2013 Use Case: Assign Permissions using Unified Groups"},"content":{"rendered":"<h4><a href=\"https:\/\/aka.ms\/30DaysMSGraph\">List of all posts in the #30DaysMSGraph series<\/a><\/h4>\n<p>In <a href=\"https:\/\/developer.microsoft.com\/en-us\/graph\/blogs\/30daysmsgraph-day-18-use-case-update-user-mailbox-settings\/\">Day 18<\/a> we extended the base .Net Core console application to update the users (exchange online) mailbox settings in Office 365. Today we\u2019ll extend the base console application to assign permissions to the users by adding them to the unified groups.\u00a0 Note that it is not required to perform each of the daily Use Case samples in order to continue to the next.\u00a0 Starting with the base console application from Day 15 will be sufficient if building from scratch, or as always, you can clone the completed version in the provided repo at bottom of this post. The application uses a client secret and the Microsoft Authentication Library (MSAL) to establish an authentication context with the Microsoft Graph API.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/30DaysMSGraph_Day19_Source.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-2160\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/30DaysMSGraph_Day19_Source.jpg\" alt=\"\" width=\"992\" height=\"700\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/30DaysMSGraph_Day19_Source.jpg 1280w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/30DaysMSGraph_Day19_Source-300x212.jpg 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/30DaysMSGraph_Day19_Source-1024x722.jpg 1024w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/30DaysMSGraph_Day19_Source-768x542.jpg 768w\" sizes=\"(max-width: 992px) 100vw, 992px\" \/><\/a><\/p>\n<p>Today we will explore the process of adding user to the required Office 365 Groups in preparation for onboarding a user.<\/p>\n<h3>Add and validate user permissions in unified groups<\/h3>\n<p>In preparation for onboarding a user, once the user is created and appropriate license is applied, now we can add the permissions required for the user to various groups. In this post we will show you how to add users to Office 365 unified groups. By virtue of being part of these groups, the user will get permissions to access not just the group but also the associated SharePoint Online site. As of today (Nov 2018), Microsoft Graph does not support adding user permissions to SharePoint Online site. However, you can update the Azure AD App and assign permissions to SharePoint Online (in addition to Microsoft Graph) and then access SharePoint Online REST API to accomplish the task of assigning permissions. Note that this is outside the scope for today&#8217;s post.<\/p>\n<p>You can use the Microsoft Graph endpoint \/users\/{id|userPrincipalName}\/memberOf to get groups and directory roles that a user is a direct member of. You can find the Microsoft Graph documentation <a href=\"https:\/\/developer.microsoft.com\/en-us\/graph\/docs\/api-reference\/v1.0\/api\/user_list_memberof\">here<\/a>.<\/p>\n<p>You can use the Microsoft Graph endpoint \/groups\/{id}\/members\/$ref to add a user to a group. The documentation for this endpoint is <a href=\"https:\/\/developer.microsoft.com\/en-us\/graph\/docs\/api-reference\/v1.0\/api\/group_post_members\">here<\/a>.<\/p>\n<p>To use the above API the Azure AD App needs new permissions. As such the Azure AD App Registration\u00a0needs to be updated to include the following application permissions: User.Read.All, Group.ReadWrite.All, Directory.Read.All, and Directory.ReadWrite.All<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/day19-app-permissions-2.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2161\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/day19-app-permissions-2.png\" alt=\"\" width=\"1813\" height=\"682\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/day19-app-permissions-2.png 1813w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/day19-app-permissions-2-300x113.png 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/day19-app-permissions-2-1024x385.png 1024w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/day19-app-permissions-2-768x289.png 768w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2018\/11\/day19-app-permissions-2-1536x578.png 1536w\" sizes=\"(max-width: 1813px) 100vw, 1813px\" \/><\/a><\/p>\n<p>With the necessary permissions configured it is time to look at new the code required.<\/p>\n<div>\n<h4>Get list of groups user is a member of<\/h4>\n<\/div>\n<div>\n<p>Below is a helper method added to PermissionHelper.cs class that will list out all the Groups that a user belongs to.<\/p>\n<div>\n<div>\n<pre>        \/\/Returns a list of groups that the given user belongs to\n        public async Task&lt;List&lt;ResultsItem&gt;&gt; UserMemberOf(string alias)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 User user = FindByAlias(alias).Result;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 List&lt;ResultsItem&gt; items = new List&lt;ResultsItem&gt;();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 IUserMemberOfCollectionWithReferencesPage groupsCollection = await _graphClient.Users[user.Id].MemberOf.Request().GetAsync();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (groupsCollection?.Count &gt; 0)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach (DirectoryObject dirObject in groupsCollection)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (dirObject is Group)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Group group = dirObject as Group;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 items.Add(new ResultsItem\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Display = group.DisplayName,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Id = group.Id\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 });\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return items;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/pre>\n<div>\n<h4>Identify a group and add user permissions to the group and the associated SharePoint Online Site<\/h4>\n<\/div>\n<div>Below are two more helper methods that will help in adding a user to a unified group and also ensures the user is not already part of that group.<\/div>\n<div>\n<div>\n<pre>\u00a0 \u00a0 \u00a0 \u00a0 \/\/Adds the user to the given group if not already a member of\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public async Task AddUserToGroup(string alias, string groupId)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 User user = FindByAlias(alias).Result;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 List&lt;ResultsItem&gt; items = UserMemberOf(alias).Result;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (items.FindIndex(f =&gt; f.Id == groupId) &gt;= 0)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(\"User already belongs to this group\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 await _graphClient.Groups[groupId].Members.References.Request().AddAsync(user);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/Returns the first unified group with the given suffix\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 public async Task&lt;string&gt; GetGroupByName(string groupNameSuffix)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var groups = await _graphClient.Groups.Request().Filter(\"groupTypes\/any(c:c%20eq%20'unified') AND startswith(displayName,'\" + groupNameSuffix + \"')\").Select(\"displayName,description,id\").GetAsync();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if (groups?.Count &gt; 0)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return (groups[0] as Group).Id as string;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return null;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/pre>\n<\/div>\n<\/div>\n<div>Now that the helper methods are ready. You can call into these methods from the Program.cs class using below method:<\/div>\n<div>\n<div>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private static void PermissionHelperExampleScenario()\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 const string alias = \"adelev\";\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ListUnifiedGroupsForUser(alias);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 string groupId = GetUnifiedGroupStartswith(\"Contoso\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 AddUserToUnifiedGroup(alias, groupId);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ListUnifiedGroupsForUser(alias);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private static void ListUnifiedGroupsForUser(string alias)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var permissionHelper = new PermissionHelper(_graphServiceClient);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 List&lt;ResultsItem&gt; items = permissionHelper.UserMemberOf(alias).Result;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(\"User is member of \"+ items.Count +\" group(s).\");\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 foreach(ResultsItem item in items)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(\"\u00a0 Group Name: \"+ item.Display);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private static string GetUnifiedGroupStartswith(string groupSuffix)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var permissionHelper = new PermissionHelper(_graphServiceClient);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var groupId = permissionHelper.GetGroupByName(groupSuffix).Result;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return groupId;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 private static void AddUserToUnifiedGroup(string alias, string groupId)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var permissionHelper = new PermissionHelper(_graphServiceClient);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 permissionHelper.AddUserToGroup(alias, groupId).GetAwaiter().GetResult();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/pre>\n<\/div>\n<\/div>\n<\/div>\n<div>In the above code the method\u00a0PermissionHelperExampleScenario encapsulates today&#8217;s use case secnario. It first lists out all the unified groups that a given user belongs to. Then it identifies a new unified group. Then attemps to add the user to this new group. The code takes care of validating if the user is already part of this group. Finally to validate the use case, it lists out the groups that the user belongs to.<\/div>\n<div><\/div>\n<div>The complete set of instructions and code are on GitHub in the\u00a0<a href=\"https:\/\/github.com\/microsoftgraph\/dotnetcore-console-sample\">dotnetcore-console-sample<\/a> repo for you try it yourself.<\/div>\n<div>\n<h2>Try It Out<\/h2>\n<p>Navigate to the\u00a0<a href=\"https:\/\/github.com\/microsoftgraph\/dotnetcore-console-sample\">dotnetcore-console-sample<\/a> repo.\u00a0 Do one (or both) of the following:<\/p>\n<p><a href=\"https:\/\/github.com\/microsoftgraph\/30DaysMSGraph-TryItOut\/blob\/master\/Day19-O365GroupsPerm.md\">Day 19 repo link<\/a><\/p>\n<ol>\n<li>Clone the repo and configure the project in the Day 19 subfolder.<\/li>\n<li>Follow the instructions in Day 19 to build the project from scratch yourself.<\/li>\n<\/ol>\n<p>If you run into any issues while building or configuring the project please create a new Issue on the repo.<\/p>\n<p>Join us tomorrow as we show you how to use Device Code Flow to authenticate user and use Microsoft Graph API in <a href=\"https:\/\/developer.microsoft.com\/en-us\/graph\/blogs\/30daysmsgraph-day-20-use-case-device-code-flow-to-authenticate-users\/\">Day 20<\/a>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this post we will show you how to add users to Office 365 unified groups. By virtue of being part of these groups, the user will get permissions to access not just the group but also the associated SharePoint Online site. <\/p>\n","protected":false},"author":69213,"featured_media":25159,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[84],"class_list":["post-2156","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-graph","tag-30daysmsgraph"],"acf":[],"blog_post_summary":"<p>In this post we will show you how to add users to Office 365 unified groups. By virtue of being part of these groups, the user will get permissions to access not just the group but also the associated SharePoint Online site. <\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/2156","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/users\/69213"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/comments?post=2156"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/2156\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media\/25159"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media?parent=2156"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/categories?post=2156"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/tags?post=2156"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}