Claims mapping script

This sample script automatically maps claims from an external login provider to user profile properties, such as assigning roles during user authentication.

External login providers send information about logged-in users as claims, which vary depending on the provider. In this example, Google is used as the login provider. Google provides two claims: givenname and surname. The script assumes the M.UserProfile entity definition includes FirstName and LastName properties and maps the givenname and surname claims to those properties.

Before you begin
  • Configure the schema editor to include the required properties that aren't included by default, such as FirstName and LastName.

  • Ensure the external login provider is integrated with Content Hub and that it provides claims for mapping.

Script

RequestResponse
using System.Linq;
using System.Security.Claims;

if (Context.ExternalUserInfo?.Claims == null) return;

var firstName = Context.ExternalUserInfo.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
var lastName = Context.ExternalUserInfo.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value;

if (string.IsNullOrEmpty(firstName) && string.IsNullOrEmpty(lastName)) return; // No first or lastname claims found, nothing to do.

var userToUserProfile = await Context.User.GetRelationAsync<IParentToOneChildRelation>("UserToUserProfile");
if (!userToUserProfile.Child.HasValue) throw new InvalidOperationException("The logged on user has no user-profile.");

var profile = await MClient.Entities.GetAsync(userToUserProfile.Child.Value); 
if (profile == null) throw new InvalidOperationException("The logged on user has no user-profile.");

if (!string.IsNullOrEmpty(firstName))
{
  profile.SetPropertyValue("FirstName", firstName);
}

if (!string.IsNullOrEmpty(lastName))
{
  profile.SetPropertyValue("LastName", lastName);
}

await MClient.Entities.SaveAsync(profile);

Script explanation

First, the script declares the libraries to be used during run time.

RequestResponse
using System.Linq;
using System.Security.Claims;

Users can log in using either basic authentication (with a username and password) or using an external login provider. If the user has logged in using basic authentication, Context.ExternalUserInfo will be null, meaning there are no claims to map, so the script exits.

RequestResponse
if (Context.ExternalUserInfo?.Claims == null) return;

If the user is logged in using an external provider, the script extracts the required values from the provided claims. These claims are defined as constants on the ClaimTypes class.

RequestResponse
var firstName = Context.ExternalUserInfo.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName)?.Value;
var lastName = Context.ExternalUserInfo.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname)?.Value;

If no givenname or surname claims are provided, there is nothing to map, so the script exits.

RequestResponse
if (string.IsNullOrEmpty(firstName) && string.IsNullOrEmpty(lastName)) return;

The logged-in user's profile must be loaded, as specified in Context.User. This profile is linked to the user through the UserToUserProfile relation, and every user is expected to have an associated profile. If the user's profile is not found, the script exits.

RequestResponse
var userToUserProfile = await Context.User.GetRelationAsync<IParentToOneChildRelation>("UserToUserProfile");
if (!userToUserProfile.Child.HasValue) throw new InvalidOperationException("The logged on user has no user-profile.");

var profile = await MClient.Entities.GetAsync(userToUserProfile.Child.Value); 
if (profile == null) throw new InvalidOperationException("The logged on user has no user-profile.");

Next, the script populates the FirstName and LastName properties of the profile entity. If one of the claims has not been provided, it is skipped.

RequestResponse
if (!string.IsNullOrEmpty(firstName))
{
  profile.SetPropertyValue("FirstName", firstName);
}

if (!string.IsNullOrEmpty(lastName))
{
  profile.SetPropertyValue("LastName", lastName);
}

Finally, the script stores the supplied user profile changes in the database.

RequestResponse
await MClient.Entities.SaveAsync(profile);

Setup

  • Create, publish, and enable a User sign-in script.

Do you have some feedback for us?

If you have suggestions for improving this article,