Creating a Custom Claims Provider

When Windows Live is used as the authentication provider, anyone with a Windows Live ID can login to the website. This could be any Windows Live domain (Hotmail, live, etc..) or a custom domain hosted on Windows Live.

The claims that are returned from Windows live does not provide any way to identify a specific user. One useful peace of information that is provided by Windows Live is the PUID of each user. This information can be used to identify users and either deny or allow access to the website. But to be able to identify the user using the PUID, you need to have this information before the user attempts to login to the website. Usually this happens during registration, which will be discussed in a future post.

During the registration process, information would be collection from the user and saved in a custom database along with the user’s PUID, either by asking for his Windows Live ID or by creating a new Windows live ID for the user on his behalf.

A custom claims provider can be created to augment the claims that are returned by Windows Live. In the claims provider, the PUID of the user can be obtained and then checked in the custom database. If a user with this PUID exists, then information about this user can be saved in custom claims for later use in the website (for example, displaying a welcome note for the user). If the PUID of the user attempting to login is not found, then another custom claim can be added which then will be used to deny access to the user to the website.

A sample implementation could be as follows

protected override void FillClaimsForEntity(Uri context, SPClaim entity, List<SPClaim> claims)
{
    SPClaimProviderManager cpm = SPClaimProviderManager.Local;
    SPClaim curUser = SPClaimProviderManager.DecodeUserIdentifierClaim(entity);
    SPOriginalIssuerType loginType = SPOriginalIssuers.GetIssuerType(curUser.OriginalIssuer);
    if (loginType == SPOriginalIssuerType.Windows)
    {
        claims.Add(CreateClaim("http://schema.WindowsLive.com/logintype", "Windows", WindowsLiveClaimValueType));
    }
    else if ((loginType == SPOriginalIssuerType.TrustedProvider) || (loginType == SPOriginalIssuerType.ClaimProvider))
    {
        string value = entity.Value; 
        string puid = value;
        //these are some business logic classes that are responsible for managing user data/
        UserManagement.UserManagement m = new UserManagement.UserManagement();
        User obj = m.GetUserByPUID(puid);
        if (obj == null)
        {
            //this claim will be used to deny access to users who are not registered in WindowsLive database
            claims.Add(CreateClaim("http://schema.WindowsLive.jo/authorized", "anuthorized", WindowsLiveClaimValueType));
           
        }
        else
        {
            //this claim will be used to cache the user's name
            claims.Add(CreateClaim("http://schema.WindowsLive.jo/logintype", "Live", WindowsLiveClaimValueType));
            claims.Add(CreateClaim("http://schema.WindowsLive.jo/FirstName", obj.FirstName, WindowsLiveClaimValueType));
            claims.Add(CreateClaim("http://schema.WindowsLive.jo/LastName", obj.LastName, WindowsLiveClaimValueType));
        }
    }
}

In this method you will have a chance to do some business logic to check if the logged in user is already registered on your website or not. Accordingly you can add a claim which you can use later to deny access to the user by specifying a user policy that denies access to any user that has a specific claim value.

A more complete sample can be found here.

Deploying the claims provider requires creating a feature receiver that inherits from SPClaimProviderFeatureReceiver class. An implementation can be found here.