aspnetcore: Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken

I use Identityserver4 and try to connect with a .ner core 2.0 mvc app to Open Id authentication My Configuration is here

            services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie()
            .AddOpenIdConnect(options =>
            {
                options.ClientId = "clientId";
                options.ClientSecret = "secret";
                options.Authority = Configuration["IdentityServerAddress"];
                options.SignedOutRedirectUri = Configuration["IdentityServerManagerAddress"];
                options.ResponseType = "code id_token";
                options.Scope.Add("openid");
                options.Scope.Add("roles");
                options.Scope.Add("profile");
                options.Scope.Add("offline_access");
                options.Scope.Add("phone_number"); 
                options.SignInScheme = "Cookies";
                options.GetClaimsFromUserInfoEndpoint = true;
                options.SaveTokens = true;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                    RoleClaimType = "role"
                };
            });

but I got this error :

InvalidCastException: Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler+<HandleRequestAsync>d__12.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 24 (12 by maintainers)

Most upvoted comments

In my case the problem relates to IDS4 returning the role claim as an array when the user has multiple roles (see http://docs.identityserver.io/en/release/endpoints/userinfo.html). This causes an exception when trying to get the role into the Principal via:

oidcOptions.ClaimActions.MapUniqueJsonKey(JwtClaimTypes.Role, JwtClaimTypes.Role);

I’ve got around this as follows:

oidcOptions.Events = new OpenIdConnectEvents()
{
  OnUserInformationReceived = async context =>
  {
    // IDS4 returns multiple claim values as JSON arrays, which break the authentication handler
    if (context.User.TryGetValue(JwtClaimTypes.Role, out JToken role))
    {
      var claims = new List<Claim>();
      if (role.Type != JTokenType.Array) {
        claims.Add(new Claim(JwtClaimTypes.Role, (string)role));
      }
      else  {
        foreach (var r in role)
          claims.Add(new Claim(JwtClaimTypes.Role, (string)r));
      }
      var id = context.Principal.Identity as ClaimsIdentity;
      id.AddClaims(claims);
    }
  ...
}

It looks like the name claim is the issue. Try oidcOptions.ClaimActions.Remove("name") to drop that mapping.

It looks like IdentityServer4 is using a non-standard name format. http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims name | string | End-User's full name in displayable form including all name parts, possibly including titles and suffixes, ordered according to the End-User's locale and preferences.