How to use Microsoft Graph to get office groups listed in a native (Console) application

To get groups from using Microsoft Graph you have to do the following things:

  • Register an application using Azure AD and give required privileges to the application
  • Request a token for your application using the client ID and client secret key
  • Make the API call to using REST by specifying that your realm where to get the groups from

Register your application through Azure AD

Go to https://portal.azure.com/ or https://manage.windowsazure.com

Next from the Azure navigation go to your active directory. Next you should see different options in the top area of the your AAD, such as:

Users, Groups, Applications, Domain and so on.

Select the Applications section.

aad1

Next you should get a listing of applications configured in your AAD.

Next from the AAD UI select ADD to add a new application.

aad2

Select what type of an application it is. You can use both option. I used the configurations of an MVC application which allowed me to work just fine. What matters is the client ID, client secret key and the privileges. The redirect URL is not necessary for a Native Application, you can type in anything as long as it is a URL.

aad4aad5

 

After your application is created go to the configure section.

aad6

Here find the client ID and copy store it somewhere to be used later.

Then go to the keys section and add a new key(client secret)

aad7

Then scroll down and go the applications section and add the Microsoft Graph application and select the needed privileges. In this case, you would like at least to be able to read groups.

aad8aad9

That is it, next is some code.

Request a token for your application

This is the piece of code that will get the token from your application. The constants and parameters will be explained soon.

public static string GetTokenForApplication(String realm, String clientId, String clientSecret)
 {
 AuthenticationContext authenticationContext = new AuthenticationContext(Constants.UnifiedApiConnect.AzureADAuthority + realm, false);
 // Config for OAuth client credentials 
 ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

 AuthenticationResult authenticationResult = authenticationContext.AcquireToken(Constants.UnifiedApiConnect.O365UnifiedAPIResource,
 clientCred);
 string token = authenticationResult.AccessToken;
 return token;
 }

Make the API Call to get the groups

This is the code that will get the token and request data from the Graph API


TokenHelper.Token = Program.GetTokenForApplication(realm, clientId, clientSecret);
 List<Group> groups = new List<Group>();
 string APIURL = Constants.UnifiedApiConnect.O365UnifiedAPIResource + "v1.0/" + realm + "/groups?$filter=groupTypes/any(c:c+eq+'Unified')";
 try
 {
 groups = GroupsHttpHelper.GetGroups(APIURL);
 foreach (var group in groups)
 {
 groupsSite.Add(new SiteDirectoryEntity() { Title = group.displayName, URL = String.Format(Program.O365OutlookMailGroupURL, realm, realmLCID, group.mail) });
 }
 }
 catch (Exception ex)
 {
 Logger.Error("Error in processing O365 groups through MS Graph: " + ex.Message + "\n" + ex.StackTrace);
 }

This is the code that will do the request to the Graph API, notice that the data is deserialized into objects.

 


public class GroupsHttpHelper
 {
 public static List<Group> GetGroups(string apiUrl)
 {
 if (String.IsNullOrEmpty(apiUrl)) { throw new ArgumentNullException("apiUrl"); }

 List<Group> groups = new List<Group>();

 string responseContent = GroupsHttpHelper.GetHttpResource(apiUrl);
 var responseObject = JsonConvert.DeserializeObject<GraphResponse<Group>>(responseContent);
 foreach (var item in responseObject.value)
 {
 groups.Add(item);
 }

 return groups;

 }

 public static string GetHttpResource(string url)
 {
 string responseContent = String.Empty;

 string token = TokenHelper.Token;

 var request = (HttpWebRequest)HttpWebRequest.Create(url);

 request.Method = "GET";
 request.Accept = "application/json";
 request.Headers.Add("Authorization", "Bearer " + token);

 var response = request.GetResponse();
 using (var reader = new StreamReader(response.GetResponseStream()))
 {
 responseContent = reader.ReadToEnd();
 }

 return responseContent;
 }
 }

public class Group
 {
 public string accessType { get; set; }

 public bool? allowExternalSenders { get; set; }

 public bool? autoSubscribeNewMembers { get; set; }
 public string description { get; set; }
 public string displayName { get; set; }
 public string[] groupTypes { get; set; }
 public string id { get; set; } // identifier

 public bool isSubscribedByMail { get; set; }
 public string mail { get; set; }

 public bool? mailEnabled { get; set; }
 public string mailNickname { get; set; }
 public string onPremisesLastSyncDateTime { get; set; } //timestamp
 public string onPremisesSecurityIdentifier { get; set; }

 public bool? onPremisesSyncEnabled { get; set; }
 public string[] proxyAddresses { get; set; }

 public bool? securityEnabled { get; set; }
 public int unseenCount { get; set; }
 public string visibility { get; set; }
 }

Namespaces needed in the code:

using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;

NuGet Packages needed:

Active Directory Authentication Library – Id: Microsoft.IdentityModel.Clients.ActiveDirectory
Json.NET – Id: Newtonsoft.Json

WebConfig Values and parameters in the code

 

<add key=”MSGraphGourps_Realm” value=”yourrealm.com” />

<add key=”ClientId” value=”your client ID in the Azure AD application” />
<add key=”ClientSecret” value=”your client secret key in the Azure AD application” />

The URL format for the authentication context request is something like this: https://login.microsoftonline.com/yourrealm.com

To acquire the token: https://graph.microsoft.com/

To get the groups the URL is: https://graph.microsoft.com/1.0/yourrealm.com/groups

If you are not sure where to get your realm from there are two ways:

  1. Get it from the URL in your browser bar when you are viewing an O365 outlook mail box or group: https://outlook.office.com/owa/?realm=yourrealm.com
  2. The other option is to use the Azure Management UI and again in the url your should find it: https://manage.windowsazure.com/yourrealm.com

 

Getting other information from Groups

One Drive:

https://graph.microsoft.com/v1.0/your realm name/groups/{your group guid}/drive/root

Owners:

https://graph.microsoft.com/v1.0/your realm name/groups/{your group guid}/owners

Group Logo:

 

Advertisements

How to change SharePoint AD group names after the group name has changed in Active Directory

Well this is simple really, The code goes through each site collection, identifies groups coming from AD, then retrieves the same group using the SID value from Active Directory and updaes the SharePoint group name based on the value in the Active Directory.

param (
 [string]$SPSiteFilter = "Your application URL",
 [string]$SPADLoginNamePrefix = "c:0+.w|",
 [bool]$UseSAMAccountName = $true
 )

if ((Get-PSSnapin 'Microsoft.SharePoint.PowerShell' -ErrorAction SilentlyContinue) -eq $null){Add-PSSnapin 'Microsoft.SharePoint.PowerShell'}
 if (Get-Module -ListAvailable -Name ActiveDirectory) {
 Write-Host "ActiveDirectory Module exists"
 
} else {
 Write-Host "ActiveDirectory Module does not exist. This Script requires this module. Please check that the module is installed."
 Write-Host "To install the module through PowerShell you can use the following command:"
 Write-Host "Add-WindowsFeature RSAT-AD-PowerShell"
 return
}
 
 Import-Module ActiveDirectory
$spWebApp = Get-SPWebApplication $SPSiteFilter
foreach($site in $spWebApp.Sites)
 {
 Write-Host "Site: $($site.Url)"
 # Notice that the SPADLoginNamePrefix variable prefix is used to identify a AD group and also to parse the SID value
 $site.rootweb.siteusers | where { $_.IsDomainGroup -and $_.UserLogin.ToString().Contains($SPADLoginNamePrefix) } | %{
 
 
 $dispNameSplit = $_.UserLogin.ToString().Replace($SPADLoginNamePrefix, "")
 
 #Get the Account from AD to retrieve to correct name
 $adAccount = Get-ADGroup -Identity $dispNameSplit
 
 $newSPAccountDisplayName = ""
 #Modify the SharePoint Account DisplayName and Name based on the AD SamAccountName OR the Name 
 if($UseSAMAccountName -eq $true)
 { $newSPAccountDisplayName = $adAccount.SamAccountName }
 else
 { $newSPAccountDisplayName = $adAccount.Name }
 
 if($_.DisplayName -ne $newSPAccountDisplayName -or $_.Name -ne $newSPAccountDisplayName)
 {
 Write-Host "Changed SharePoint AD Group: $($_.DisplayName) to: $($newSPAccountDisplayName)"
 $_.DisplayName = $newSPAccountDisplayName
 $_.Name = $newSPAccountDisplayName
 $_.Update()
 } else
 {
 Write-Host "SharePoint AD Group name: $($_.DisplayName) is the same as in AD : $($newSPAccountDisplayName)"
 }
 $adAccount = $null
 }
 $site.Dispose();
}

SharePoint – Setting users or groups for a membership webpart through code

This is a rather simple thing… well once you have cracked it :).

 

There are two properties which need to be set:

And that is it. To find the “main” associated groups to your site you could use these properties:

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedownergroup.aspx

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedmembergroup.aspx

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedvisitorgroup.aspx

https://msdn.microsoft.com/EN-US/library/microsoft.sharepoint.spweb.associatedgroups.aspx


using (SPSite site = new SPSite(wsSite.ID))
{
using (SPWeb web2 = site.OpenWeb(wsSite.RootWeb.ID))
{
var pubWeb = PublishingWeb.GetPublishingWeb(web2);

using (var wpm = pubWeb.DefaultPage.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
// Search for the right webpart(you could use LINQ instead of a foreach)
int memberShipWebPartsCount = 0;
for (int x = wpm.WebParts.Count - 1; x >= 0; x--)
{
var membersWebPart = wpm.WebParts[x] as Microsoft.SharePoint.WebPartPages.MembersWebPart;
if (membersWebPart != null)
{

// There are only two members webparts which are needed to be processed, at the moment
if (memberShipWebPartsCount < 2)
{
if (memberShipWebPartsCount == 0)
membersWebPart.MembershipGroupId = wsSite.RootWeb.AssociatedOwnerGroup.ID;
else if (memberShipWebPartsCount == 1)
membersWebPart.MembershipGroupId = wsSite.RootWeb.AssociatedMemberGroup.ID;

membersWebPart.DisplayType = Microsoft.SharePoint.WebPartPages.MembersWebPartDisplayType.GroupMembership;
wpm.SaveChanges(membersWebPart);

pubWeb.DefaultPage.Update();
if (pubWeb.DefaultPage.CheckOutType != SPFile.SPCheckOutType.None)
pubWeb.DefaultPage.CheckIn("");

if (pubWeb.DefaultPage.ParentFolder.DocumentLibrary.EnableVersioning && pubWeb.DefaultPage.ParentFolder.DocumentLibrary.EnableMinorVersions)
pubWeb.DefaultPage.Publish("");
}
memberShipWebPartsCount++;
}
}

}
}
}