IdentityServer use IdentityModel to get user token and user info

Using IdentityServer have been made easier with the IdentityModel helper library. The library implements extension methods that maps the input and output to classes.

GET ACCESS TOKEN:

Use the PasswordTokenRequest and RequestPasswordTokenAsync to get the access token. replace your_domain, your_clientid and your_secret with the values from your Identity Server:

using IdentityModel.Client;

public string LoginUsingIdentityServer(string username, string password)
{
  var client = new HttpClient();
  PasswordTokenRequest tokenRequest = new PasswordTokenRequest() 
  { 
    Address = "http://your_domain/connect/token",
    ClientId = "your_clientid",
    ClientSecret = "your_secret",
    UserName = username,
    Password = password
  };
  
  var response = client.RequestPasswordTokenAsync(tokenRequest).Result;
  if (!response.IsError)
  {
     response.AccessToken;
  }
  else
  {
    throw new Exception("Invalid username or password");
  }
}

GET USERINFO:

First you need to ensure that the Identity Resource in Identity Server can return the claims from the user (claims is the fancy word for properties). If you use the Identity Server Admin interface, you can choose OPENID from the Resources/Identity Resources menu and select the claims visually:

Identity Server Claims

Identity Server Claims

Use the UserInfoRequest and pass your access token to GetUserInfoAsync to get the user claims:

using IdentityModel.Client;
using Newtonsoft.Json;
using System.Collections;
using System.Net.Http;

public void GetUserInfo(string accessToken)
{
  var client = new HttpClient();
  var userInfoRequest = new UserInfoRequest()
  {
    Address = "http://your_server/connect/userinfo",
    Token = accessToken
  };

  var response = client.GetUserInfoAsync(userInfoRequest).Result;
  if (response.IsError)
    throw new Exception("Invalid accessToken");

  dynamic responseObject = JsonConvert.DeserializeObject(response.Raw);
  if (responseObject.given_name != null && responseObject.family_name != null)
  {
    // do something with the name
    string name = responseObject.given_name.ToString() 
	              + " " 
				  + responseObject.family_name.ToString();
    }

    // If there is one role, the role property is a string.
	// There there is more roles, the role property is an array
	// To handle this, I use this clumsy statement:
    if (responseObject.role.Type == Newtonsoft.Json.Linq.JTokenType.String)
	{
      // do something with the roles
	string role = responseObject.role.ToString();
	}	
    else
    {
      foreach (var role in responseObject.role)
      {
        // do something with the roles
        string role = role.ToString();
      }
    }
  }
}

FOR SITECORE USERS:

If you use Sitecore, you can create a Virtual User based on the user info, and log into Sitecore using this virtual user.

using IdentityModel.Client;
using Newtonsoft.Json;
using Sitecore.Security.Authentication;
using System.Collections;
using System.Net.Http;

namespace MyCode
{
  public class VirtualUserFactory
  {
    public static Sitecore.Security.Accounts.User Create(string identityServerAccessToken)
    {
      var client = new HttpClient();
      var userInfoRequest = new UserInfoRequest()
      {
        Address = "http://your_server/connect/userinfo",
        Token = identityServerAccessToken
      };

      var response = client.GetUserInfoAsync(userInfoRequest).Result;
      if (response.IsError)
        throw new Sitecore.Exceptions.AccessDeniedException();

      dynamic responseObject = JsonConvert.DeserializeObject(response.Raw);

      Sitecore.Security.Accounts.User virtualUser = AuthenticationManager.BuildVirtualUser("extranet\\" + responseObject.preferred_username.ToString(), true);

      if (responseObject.given_name != null && responseObject.family_name != null)
        virtualUser.Profile.FullName = responseObject.given_name.ToString() + " " + responseObject.family_name.ToString();

      if (responseObject.email != null)
        virtualUser.Profile.Email = responseObject.email.ToString();

      if (responseObject.role.Type == Newtonsoft.Json.Linq.JTokenType.String)
        virtualUser.Roles.Add(Sitecore.Security.Accounts.Role.FromName(responseObject.role.ToString()));
      else
      {
        foreach (var role in responseObject.role)
        {
          virtualUser.Roles.Add(Sitecore.Security.Accounts.Role.FromName(role.ToString()));
        }
      }

      if (responseObject.sub != null)
        virtualUser.Profile.ProfileItemId = responseObject.sub.ToString();

      return virtualUser;
    }
  }
}

Logging into Sitecore uisng a virtual user is simple:

// Login the virtual user
Sitecore.Security.Authentication.AuthenticationManager.LoginVirtualUser(virtualUser);

MORE TO READ:

About briancaos

Developer at Pentia A/S since 2003. Have developed Web Applications using Sitecore Since Sitecore 4.1.
This entry was posted in General .NET, Sitecore 6, .net, c#, Sitecore 7, Sitecore 8, Sitecore 9, .NET Core and tagged , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.