简体   繁体   中英

Getting values of custom Claims from JWT

I have a controller that receives a JWT token and I need to get the custom claims from it. The claim is of type "custom" as defined by http://www.imsglobal.org/spec/lti/v1p3/#custom-properties-and-variable-substitution (unfortunately, their link to the spec is a 404).

What this looks like in a decoded token is

在此处输入图像描述

Doing this

var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.ReadJwtToken(authorizedRequest.id_token);          

// TODO this is way too vague and _can't_ be the correct way that we can get this information from all platforms, can it?
var claim = token.Claims.First(c => c.Type == "https://purl.imsglobal.org/spec/lti/claim/custom");
var data = JsonConvert.DeserializeObject(claim.Value);

data is:

在此处输入图像描述

I expected to see an object such as

{
  name = "Chris",
  email = "c@ex.com",
  userId = "123"
}

with the goal of being able to get these values with a data.name . What is the right way to access these?

You could get the data in object like below:

var claim = token.Claims.First(c => c.Type == "https://purl.imsglobal.org/spec/lti/claim/custom");
var data = (JObject)JsonConvert.DeserializeObject(claim.Value);//convert to JObject
var name = data["name"].ToString();  //get the property value...

//expected object
var model = new
{
    name = data["name"].ToString(),
    email = data["email"].ToString(),
    userId = data["userid"].ToString()
};

with the goal of being able to get these values with a data.name.

If you want to did this work,you need to create a View Model:

Model:

public class UserModel
{
    public string name { get; set; }
    public string email { get; set; }
    public int userid { get; set; }
}

Controller:

var data = JsonConvert.DeserializeObject<UserModel>(claim.Value);
var name = data.name;

Since you're using Newtonsoft, you can deserialize the JSON object to an anonymous type which will allow you to access the values like you mentioned data.Name . Whether or not this is a suitable solution for your use case is up to you.

var claim = token.Claims.First(c => c.Type == "https://purl.imsglobal.org/spec/lti/claim/custom");

var dataType = new { Name = "", Email = "", UserId = "" }
var data = JsonConvert.DeserializeAnonymousType(claim, dataType);

Foo.DoSomethingWithData(data.Name);

That will give you an object similar to what you were expecting in the first place. Of course, this requires that you're able to define the property names and types of the anonymous type. If the format of the claim is known, then it should be fine but you'll have to consider whether it's appropriate for your use case.

If you don't want to go with an anonymous type, you can simply deserialize the JSON into a dictionary and access it accordingly.

var claim = token.Claims.First(c => c.Type == "https://purl.imsglobal.org/spec/lti/claim/custom");

var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(claim);

DoSomething(data["name"]);

Here is a link to the Newtonsoft API reference for each method. https://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm https://www.newtonsoft.com/json/help/html/DeserializeDictionary.htm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM