The multiple identities of a SharePoint site user
Share this post

I gave a talk on the subject of this post on the 8th October 2020 for the Microsoft SharePoint Framework and JavaScript Special Interest Group. They have kindly recorded and editing the video below.

Every SharePoint site maintains its own list of users and groups. In this post we’ll explore the relationship between a site’s users and groups and the corresponding users and groups in Azure Active Directory (AAD).

Consider a solution to process purchase orders where different members of staff are authorised to approve order values up to certain limits. We can define rules to apply approval limits to users, AAD groups and SharePoint groups as follows:

In the above list the Applies to IDs column has been formatted to display the IDs of the people and groups selected in the Applies to column.

When a user submits a purchase order the system needs to determine their approval limit so that the order can be automatically processed or delivered to another user for approval. We can determine a user’s approval limit by finding the rules (Purchase Order Limits items) which apply to that user.

The SharePoint Person or Group column type can be used to assign one or more users and groups to a rule. The selected users and groups are stored in the column as an array of IDs. Column formatting has been used in the above screenshot of the list to display those IDs in the Applies to IDs column.

To determine if a rule applies to a user, we need to find all IDs used to identify the user and their groups – i.e. their multiple identities – on the SharePoint site and match them against the values in the rule’s Applies to column.

What are SharePoint Site Users and Site Groups?

It is important to be clear whether we are talking about site users, site groups, organisation user accounts, security groups and Microsoft 365 groups.

WhatWhereManage using
Organisation UsersReal users or service accounts
Azure Active Directory (AAD)
On-premises AD

Azure AD

Microsoft 365 Admin Center
Organisation GroupsActive Directory security groups and Microsoft 365 groupsAzure Active Directory (AAD)On-premises AD

Azure AD

Microsoft 365 Admin Center
SharePoint Site UsersOrganisation’s users and groups that have been referenced on a siteSharePoint SiteCannot create directly

Can view and delete in SP Site User Profile view
SharePoint Site GroupsUsed to organise collections of Site UsersSharePoint SiteSP Site Settings

Each SharePoint site maintains its own list of users and groups. Site users can be assigned membership of a site group, but site groups cannot be nested as members of other site groups.

Site groups are created and maintained on the SharePoint site. They have no relation to Azure Active Directory Security Groups or Microsoft 365 Groups.

A SharePoint site creates site users to reference both an organisation’s users and groups. This means that security groups and Microsoft 365 groups can be members of SharePoint site groups.

AAD Users and Groups are both mapped to SharePoint Site Users.

Site users cannot be created directly in SharePoint, instead they are always created in response to some action which references the organisation user or group. This could be by:

  • A user visiting the site;
  • Granting permission to the user or group for the site, library, list or list item;
  • Choosing the user in a People or Group column for a list or library item.
  • Calling SharePoint EnsureUser service to add the user to the site.

The Site User and Group Information web part

To help explore the multiple identities a user has for a site SharePoint site I created the Site User and Group Information web part, now merged into the SharePoint Framework Client-Side Web Part Samples & Tutorial Materials.

If you are unable to build the web part yourself you can download a pre-built version here.

Deploy the package to your SharePoint Online app catalogue (alternative instructions) and then install on a site.

Next add the User and Group Info web part to a page on your site.

Demo site users and groups

Users and groups in Azure AD and corresponding site users and site groups on the demonstration SharePoint site.

In our demo tenant we’ve created security groups in Azure Active Directory as shown. The black arrows on the diagram indicate that a user or group is a member of the group being pointed to. E.g. Alex is a member of AD Group 3 which itself is a nested member of AD Group 1.

On our demo SharePoint site we have created two SharePoint site groups and assigned Grady and the AAD security groups as members.

Adele, Henrietta and AD Group 4 have been assigned read permissions on the site directly.

Using the web part

The User and Group Info web part allows us to search for tenant users or select from site users.

Start by selecting an existing site user:

Notice that users Diego, Alex and Isaiah are not present in the list of site users. This is because they have not accessed the site themselves and because they have not been directly assigned permissions to the site/lists/libraries/items or selected in any Person or Group columns in use on the site.

For our example we select Adele from the list of site users:

All the highlighted IDs in the above screenshot are:

  • 11 – SP Group 1
  • 12 – SP Group 2
  • 14 – AD Group 2
  • 15 – AD Group 1
  • 17 – Adele Vance

The SharePoint site users and groups that refer to Adele are shown below:

If we click on these IDs in the web part we can view the profile of the user, security group or SharePoint group.

No matter which the type of principal ID (user, security group, SP group) we click on we always visit the userdisp.aspx page, passing the ID value as a query parameter.

SharePoint will then either redirect to or display a page suitable for the type of principal we are viewing.

Clicking on 17 redirects to Adele’s Delve profile.

The link for SP Group 1 (with ID 11) redirects to SharePoint’s group profile page.

SharePoint group profile for SP Group 1. Notice that AAD security group, AD Group 1, is a member of this SharePoint site group.

The link for AD Group 1 (with ID 15) isn’t redirected, but userdisp.aspx shows a basic USER profile.

‘User’ profile of an AAD security group. The GUID in the Account (91a79c…) matches the Object Id of the group displayed in the Azure Active Directory Portal.

From this screen shot we can see that SharePoint is treating the AAD security group as a site user.

All those IDs listed for Adele correspond to either site users or site groups, but there is no duplication of IDs between users or groups. Further, accessing userdisp.aspx and passing either a site user or site group ID as a query parameter resulted in a redirect to a page appropriate for displaying a real user, an AAD group or a site group. We can surmise that site users and groups are maintained as a single internal list which is why the People and Groups column can mix selection of user or group values.

In the web part we select Grady from the list of site users and get the following results:

Grady is known to the SP site by his User principal (ID: 13) as well as his membership of site group, SP Group 1 (ID: 11).

For Grady the highlighted IDs in the above screenshot are:

  • 11 – SP Group 1
  • 13 – Grady Archie

Mapping these results onto the users and groups diagram we get:

Next we’ll look at Isaiah’s Ids. Since Isaiah is not a site user we’ll need to search for him in the web part. Once Isaiah has been found the following results are displayed:

Isaiah is only known to the SP site by his membership of AD Group 4 (ID: 18).

In this example Isaiah is not known to the SP site at all. This would change as soon as Isaiah attempted to visit the site, but right now the meantime the only way to refer to Isaiah is as site user, AD Group 4.

We can map Isaiah’s results onto the user and groups diagram:

Code

In this section we’ll look at some of the code used to implement the web part. The full source code is available in directory samples/react-sp-site-user-groups from the sp-dev-fx-webparts repository.

Main Component

The web part makes use of React. The top-level react component is the UserAndGroupInfo function. This component maintains state of the currently selected user and references to the services used to perform lookups against Graph and SP APIs.

The Graph and SP APIs are accessed using the PnP JS Library.

When the selected user changes, this component will create new lookup promises and pass them to child components for rendering once fulfilled:

      <>
        <UserInfo
          context={props.context}
          siteUserInfoPromise={userGroupLookup.getSpUserAndMemberGroupsPromise(siteUserId)}
          aadUserPromise={aadUserGroupLookup.getAadUser(email)}
        />
        <UserGroupMemberships
          context={props.context}
          membershipsPromise={userGroupLookup.getUserMemberships(siteUserId, email)}
        />
      </>

Selecting Users

Users can be found by searching across the tenant or by selecting from those already known to the site.

User selection is handled by the UserSelection function which takes properties for the web part context, a SharePoint User Lookup service reference and a call-back to notify of selection changes:

export interface IUserSelectionProps {
  context: WebPartContext;
  userGroupLookup: SpUserGroupLookup;
  onSelectedUserChanged: (siteUserId: number, email: string) => void;
}

The web part context is used by the People Picker control from the PnP SPFx Controls project. This control is used to search for users across the tenant, returning the email address of any selected user.

The SharePoint User Lookup service is used to retrieve the list of site users:

  public async getSpSiteUsers(): Promise<ISiteUserInfo[]> {
    return sp.web.siteUsers.filter("PrincipalType eq " + PrincipalType.User).get();
  }

Using the People Picker control or the list of site users, a user is selected and notified to the parent components via the onSelectedUserChanged call-back.

Displaying User (AAD + SP) Information

User information rendered as the siteUserInfo and aadUser promises resolve.

The main UserAndGroupInfo parent component passes two promises to its UserInfo child component as properties siteUserInfoPromise and aadUserPromise. These promise are retrieved by calls to the SpUserGroupLookup.getSpUserAndMemberGroupsPromise() and AadUserGroupLookup.getAadUser() methods respectively.

The getAadUser method takes an email address parameter which can be left undefined if we want to retrieve the current user’s details. AAD user information is retrieved from the Graph API:

public async getAadUser(email: string | undefined): Promise<IUser> {
    if (this.aadUserPromises.has(email)) {
      return this.aadUserPromises.get(email);
    } else {
      let aadUserPromise: Promise<IUser>;
      if (email) {
        console.debug("Getting AAD user by email:", email);
        aadUserPromise = graph.users.getById(email).get();
      } else {
        console.debug("Getting AAD user for current user");
        aadUserPromise = graph.me() as Promise<IUser>;
      }

      this.aadUserPromises.set(email, aadUserPromise);
      return aadUserPromise;
    }
  }

The API calls in the getAadUser code listing have been highlighted. The other code is mostly concerned with logging and caching.

Even though the UserInfo component doesn’t show group information, other components on the page will need group details. Therefore we use a single function, getSpUserAndMemberGroupsPromise, to retrieve all the information needed once and cache the resulting promise for other lookups. getSpUserAndMemberGroupsPromise takes a siteUserId parameter which refers to the site user to be queried from the SharePoint site.

public getSpUserAndMemberGroupsPromise(siteUserId: number): Promise<ISiteUserInfo | undefined> {
    if (this.spUserAndMemberGroupsPromises.has(siteUserId)) {
      return this.spUserAndMemberGroupsPromises.get(siteUserId);
    } else {
      let spUserAndMemberGroupsPromise: Promise<ISiteUserInfo>;
      if (siteUserId) {
        spUserAndMemberGroupsPromise = sp.web.getUserById(siteUserId).expand("Groups").get();
      } else if (siteUserId === 0) {
        spUserAndMemberGroupsPromise = sp.web.currentUser.expand("Groups").get();
      } else {
        spUserAndMemberGroupsPromise = Promise.resolve(undefined);
      }
      this.spUserAndMemberGroupsPromises.set(siteUserId, spUserAndMemberGroupsPromise);
      return spUserAndMemberGroupsPromise;
    }
  }

User Profile Synchronisation

An organisation’s user accounts and groups are created externally to SharePoint, using tools such as Azure Active Directory or the Microsoft 365 Admin Center. User and group accounts accounts are periodically synchronised to SharePoint where they can then be added to a site.

Microsoft describe the steps used to synchronise users from Azure AD to SharePoint here. Similar to other periodic processes in Microsoft 365, they don’t say how long it takes for an AAD user to become available in SharePoint, but in my experience new users are normally visible within a few minutes.

AAD users and groups synchronised through the SharePoint Directory Store and User Profile Application before becoming available to a SharePoint Site.

It isn’t clear from documentation what technology is behind the SharePoint Directory Store, but information about the overall synchronisation process says ‘Azure AD syncs data from Azure AD to the SharePoint directory store.’ This suggests that Azure AD is writing data into the SharePoint directory store, so we can reasonably assume it is an append-only log describing user and group changes in AD.

If we assume that the SharePoint directory store is an append-only log, then the User Profile Application must be driving the next stage of the synchronisation process by periodically checking for new log entries and processing them as user and group updates accordingly.

User Profile Content

Only minimal information about a user is stored on a SharePoint site, instead the User Profile Application maintains the user’s full profile.

The following is a snippet describing site user, Adele Vance, retrieved using the CLI for Microsoft 365:

> m365 spo user list --webUrl https://watconsdev.sharepoint.com/sites/SiteUsersDemo --output json
    {
      "Id": 17,
      "IsHiddenInUI": false,
      "LoginName": "i:0#.f|membership|adelev@watconsdev.onmicrosoft.com",
      "Title": "Adele Vance",
      "PrincipalType": 1,
      "Email": "AdeleV@watconsdev.onmicrosoft.com",
      "Expiration": "",
      "IsEmailAuthenticationGuestUser": false,
      "IsShareByEmailGuestUser": false,
      "IsSiteAdmin": false,
      "UserId": {
        "NameId": "10032000e5bd0a0a",
        "NameIdIssuer": "urn:federation:microsoftonline"
      },
      "UserPrincipalName": "adelev@watconsdev.onmicrosoft.com"
    }

The User Profile Application maintains much more information about the user, synchronised from AAD and Exchange. The User Profile Application can be accessed from SharePoint Admin Center.

Snippet of Adele Vance’s profile in the User Profile Application.

Share this post
Picture of Daniel Watford

Daniel Watford

A Software Consultant with over 20 years experience building solutions to help organisations solve problems and improve their business processes with both bespoke software and off-the-shelf IT.

Join our mailing list

Please fill out the form below to join our mailing list for opinions, suggestions and walk-through guides on using IT and Software Development to improve working practices at your organisation.