Claims-based authentication and user profiles

Turns out it is relatively trivial to create a user profile for a claims authenticated user. You are probably familiar with the UserProfileManager.CreateUserProfile method. The overload of interest takes a string parameter that is the username of the profile to create – the signature is as follows

public UserProfile CreateUserProfile(
	string strAccountName
)

The question is what do you pass as your username string? In 2007 it was simple – it was either the windows username in the form DOMAIN\Username, or if FBA was being used then membershipprovidername:username. Since a claims-based user can be authenticated via windows, forms or a trusted identity provider then this must be different in 2010. It is. We need to pass the encoded string representing the user’s claims – you will have seen it looking something like:

i:0#.f|3guysmembership|ceej

So this gives us

// the user needs to have manage profiles permission for the service application
// get the user profile manager to facilitate profile creation
SPServiceContext svcCtx = SPServiceContext.Current;

// if this is being run outside of the web application (i.e. in the workflow)
// then the context will be null so get it explicitly
if (svcCtx == null)
{
    svcCtx = SPServiceContext.GetContext(workflowProperties.Site);
}

UserProfileManager profileMgr = new UserProfileManager(svcCtx);
string userClaim = "i:0#.f|3guysmembership|ceej";
// we had better double check that the profile does not exist
if (!profileMgr.UserExists(userClaim))
{
    UserProfile profile = null;
    try
    {
        profile = profileMgr.CreateUserProfile(userClaim);
    }
    catch (Exception)
    {
    }
    // now update the properties
    profile[PropertyConstants.PreferredName].Value = item[Fields.PreferredNameFieldName];
    profile[PropertyConstants.FirstName].Value = item[Fields.FirstNameFieldName];
    profile[PropertyConstants.LastName].Value = item[Fields.SurnameFieldName];
    profile[PropertyConstants.WorkEmail].Value = item.Title;
    profile[ProfileProperties.IdP].Value = item[Fields.IdPFieldName];
    profile.Commit();
}

Marvellous. But wait. How do we get this encoded string? There are two ways.

1. Construct an SPClaim object passing in the claim type (SPClaimTypes.UserLogonName), the claim value (login name), the claim value type (ClaimValueTypes.String) and finally, the original issuer (name of your membership provider if using FBA).

string userClaim = null;
SPClaimProviderManager claimMgr = SPClaimProviderManager.Local;
if (claimMgr != null)
{
    SPClaim claim = new SPClaim(SPClaimTypes.UserLogonName, "ceej", ClaimValueTypes.String, SPOriginalIssuers.Format(SPOriginalIssuerType.Forms, "3guysmembership"));
    userClaim = claimMgr.EncodeClaim(claim);
}

2. Obtain it from the LoginName property of an SPUser object

string userClaim = SPContext.Current.Web.CurrentUser.LoginName;

Note that there is a corresponding DecodeClaim method on the SPClaimProviderManager class you should be aware of

string userClaim = null;
SPClaimProviderManager claimMgr = SPClaimProviderManager.Local;
if (claimMgr != null)
{
    userClaim = claimMgr.DecodeClaim(SPContext.Current.Web.CurrentUser.LoginName).Value;
}

Of course what if the user does not yet have an entry in the user information list and hence the SPUser object is null? Simple and actually possibly the best way to go is to call SPWeb.EnsureUser

// add the user to site users list which will perform the claims encoding for us
// and return us the user, from which we can get the encoded string that can be
// used to create the profile
SPUser invitedUser = workflowProperties.Web.EnsureUser(nameId);
// get the encoded string representing the claim id
string userClaim = invitedUser.LoginName;

Saves constructing the SPClaim object and it all works as expected.

Reference
MSDN – UserProfileManager.CreateUserProfile Method (String)
http://msdn.microsoft.com/en-us/library/ms570840.aspx

MSDN – SPClaimProviderManager Class
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.claims.spclaimprovidermanager.aspx

This entry was posted in SharePoint 2010 and tagged , . Bookmark the permalink.

Comments are closed.