0

I did try this method in API Startup below And Show me the Error When I Call API through the Web MVC Project. The Error is "Response status code does not indicate success: 401 (Unauthorized)."

        app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
        {

            AuthenticationType = "jwt",
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
            TokenValidationParameters = new TokenValidationParameters
            {

                ValidIssuer = Urls.IdentityServer,
                ValidateIssuer = true,

                ValidAudience = Urls.IdentityServer + "/resources", 
                ValidateAudience = true,

                ValidateIssuerSigningKey = true,

                ValidateLifetime = true,
                IssuerSigningKeyResolver = LoadKeys,
                NameClaimType = "name",
                RoleClaimType = "role",
            },
        });

My Keyset method in Web API Startup.

internal static DiscoveryCache _discoveryCache = new DiscoveryCache(Urls.IdentityServer);

    private IEnumerable<SecurityKey> LoadKeys(string token, SecurityToken securityToken, string kid, TokenValidationParameters validationParameters)
    {
       
        var disco = _discoveryCache.GetAsync().Result;

        var keys = disco.KeySet.Keys
            .Where(x => x.N != null && x.E != null)
            .Select(x =>
            {
                var rsa = new RSAParameters
                {
                    Exponent = Base64UrlEncoder.DecodeBytes(x.E),
                    Modulus = Base64UrlEncoder.DecodeBytes(x.N),
                };

                return new RsaSecurityKey(rsa)
                {
                    KeyId = x.Kid
                };
            });

        
        return keys;
    }

policies/rules method in web identityserver. this is my " public Task GetProfileDataAsync(ProfileDataRequestContext context)" method.

    {
        var UserName = "";
      

        foreach (var data in context.Subject.Identities)
        {
            UserName = data.Name;
          
        }
        var Roless = _loginValidationService.RoleAsync(UserName).Result;

        List<Claim> customClaims = new List<Claim>();

        foreach (var item in Roless)
        {
            var role = new Claim("role", item.Name);
            customClaims.Add(role);
        }

        var RoleClaim = _loginValidationService.ClaimAsync(Roless).Result;

        foreach (var claim in RoleClaim)
        {
            var Roleclaim = new Claim( claim.ClaimType, claim.ClaimValue) ;
            customClaims.Add(Roleclaim);
        }

        var getuser = _applicationDbContext.Users.Where(x => x.UserName.Equals(UserName)).ToList();

        foreach (var user in getuser)
        {
            var Userclaims = _applicationDbContext.UserClaims.Where(x => x.UserId.Equals(user.Id)).ToList();
            foreach (var Claim in Userclaims)
            {
                var role = new Claim(Claim.ClaimType, Claim.ClaimValue);
                customClaims.Add(role);
            }
        }
        

        context.IssuedClaims.AddRange(customClaims);
        return Task.CompletedTask;
    }` 







   
  • Is the `[asp.net-core]` tag an accidental inclusion? – ProgrammingLlama Jun 20 '23 at 09:28
  • And if you're using IdentityServer, don't you want to be using `Microsoft.Owin.Security.OpenIdConnect` instead? – ProgrammingLlama Jun 20 '23 at 09:29
  • I did use (.Net Framework 4.8) and I did using Microsoft.Owin.Security.OpenIdConnect in WebApplication MVC and I did using UseJwtBearerAuthentication in WebApplication API Project. – Om Makwana Jun 20 '23 at 09:59
  • @OmMakwana Identity Server does not run on .NET Framework 4.8 - it requires .NET Core, so that makes even less sense. – Dai Jun 21 '23 at 05:14
  • My Identity Server is in .NET Core and My Web API is in the (.Net Framework 4.8). – Om Makwana Jun 21 '23 at 05:19
  • Okay, thank you for clarifying that. – Dai Jun 21 '23 at 05:32
  • `ValidAudience = Urls.IdentityServer + "/resources", ` <-- This doesn't look right to me: in OIDC and JWT, the `aud` (Audience) claim is usually the OAuth2 `scope` that corresponds to your web-API's `ApiResource` in IdentityServer, which is usually a short string and not an absolute URI. – Dai Jun 21 '23 at 05:33
  • How are you adding authorization rules to your Web API actions/endpoints? I assume you're using the `[Authorize]` attribute? If so, then please show us what policies/rules you're specifying and how you're evaluating them. – Dai Jun 21 '23 at 05:34
  • I edited my question. and this is my policies/rules method in web identityserver. – Om Makwana Jun 22 '23 at 04:58
  • See my blog post at https://nestenius.se/2023/02/21/troubleshooting-jwtbearer-authentication-problems-in-asp-net-core/ – Tore Nestenius Jun 22 '23 at 15:02
  • @ToreNestenius Thank you for answering my question but my problem is my Web API is created in (.Net Framework 4.8) not in ASP.NET Core. – Om Makwana Jun 23 '23 at 06:06
  • I think my blog post also applies to troubleshooting in .NET framework. the problem is that UseJwtBearerAuthentication is all about authentication, not authorization. If you get a 401, then that means your access token was rejected. UseJwtBearerAuthentication Is not about what you are allowed to do, its only a about creating the user object, who are you? – Tore Nestenius Jun 23 '23 at 09:07
  • @ToreNestenius thank you for answering my questions but will you give me an example? – Om Makwana Jun 29 '23 at 12:06
  • What error do you get? – Tore Nestenius Jun 30 '23 at 16:25
  • The error are generated in my Web API startup keyset part " var keys = disco.KeySet.Keys" because the keyset are null. so how to solve this error. i edited my question. and this is my full startup of Web API. – Om Makwana Jul 03 '23 at 12:30

1 Answers1

0

Ok, i have an answer to this question. KeySet is null in my Web API startup. I did include one method for this solution. and I solved my problem with this method. The method is...

{
public class OpenIdConnectSigningKeyResolver
{
    private readonly OpenIdConnectConfiguration openIdConfig;

    public OpenIdConnectSigningKeyResolver(string authority)
    {
        var cm = new ConfigurationManager<OpenIdConnectConfiguration>($"{authority.TrimEnd('/')}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
        openIdConfig = AsyncHelper.RunSync(async () => await cm.GetConfigurationAsync());
    }

    public SecurityKey[] GetSigningKey(string kid)
    {
        return new[] { openIdConfig.JsonWebKeySet.GetSigningKeys().FirstOrDefault(t => t.KeyId == kid) };
    }
}

}

And my Web API Startup is...

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var Domain = Urls.IdentityServer;
        var KeyResolver = new OpenIdConnectSigningKeyResolver(Domain);

        app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
        {
            AuthenticationType = "jwt",
            AuthenticationMode = AuthenticationMode.Active,
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidIssuer = Domain,
                ValidAudience = "APICore",
                IssuerSigningKeyResolver = (token, securityToken, kid, parameters) => KeyResolver.GetSigningKey(kid)
            }
        });

        HttpConfiguration config = new HttpConfiguration();
        config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "{controller}/{id}",
            defaults: new { id = RouteParameter.Optional });
        app.UseWebApi(config);
    }
}