Open Closed

Validating ABP/IdS generated JWT auth token with legacy .NET Framework MVC API. #835


0
dmeagor created
  • ABP Framework version: 4.1.2
  • UI type: Angular
  • DB provider: EF Core
  • Tiered (MVC) or Identity Server Seperated (Angular): yes

Our ABP Angular tiered solution needs to integrate with an older .net framework MVC solution running separately.

This is the old Jwt code we use.

// from owinconfig.cs
public void ConfigureOpenAuth(IAppBuilder app)
{
//
    app.UseJwtBearerAuthentication(
        new JwtBearerAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Active,
            TokenValidationParameters = new TokenValidationParameters()
            {
                ValidAudience = ConfigurationManager.AppSettings["JwtAudience"],
                ValidIssuer = ConfigurationManager.AppSettings["JwtIssuer"],
                IssuerSigningKey = ConfigurationManager.AppSettings["JwtSecurityKey"].ToSymmetricSecurityKey(),
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true
            }
        });
}

//from JwtExtensions.cs
public static class SecurityExtensions
    public static SigningCredentials ToIdentitySigningCredentials(this string jwtSecret)
    {
        var symmetricKey = jwtSecret.ToSymmetricSecurityKey();
        var signingCredentials = new SigningCredentials(symmetricKey, SecurityAlgorithms.HmacSha256);

        return signingCredentials;
    }

    public static SymmetricSecurityKey ToSymmetricSecurityKey(this string jwtSecret)
    {
        return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret));
    }


}

edit: ive figured i need to generate a new rsa cert somehow as its using developer mode which isnt recommended for prod.

from what ive been reading the identityserver4 jwt packages are now incompatible with .net framework.

are you share some example code for processing the Jwt token on .net framework. (currently 4.6.x but can update if needed?). im not interested in the user table stuff, just getting the claims. is there anything in the old abpboilerplate code that might work?


2 Answer(s)
  • 0
    maliming created
    Support Team

    hi

    JWT is platform independent. I think there is no problem if the JwtBearerAuthenticationOptions of net framework and the JwtBearerOptions of net core are compatible. You need to make sure that the TokenValidationParameters parameters are consistent.

    https://docs.microsoft.com/en-us/dotnet/api/microsoft.owin.security.jwt.jwtbearerauthenticationoptions https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.jwtbearer.jwtbeareroptions?view=aspnetcore-5.0

    When you get any error, you can check the log to see detail message of UseJwtBearerAuthentication.

  • 0
    dmeagor created

    Solution

    This has taken me some time to get right so I'm putting the solution here. Use this for either generating the keys identity server keys for production or integrating an old ASP Framework MVC project with the ABP identity server. There are other ways to store the cert rather than a file but this will work for linux too.

    There are blog posts on this but they are wrong and will waste hours of your time. In particular do not include the "-certfile dev.crt" to the second openssl line as instructed by one post as it will generate an incompatable production cert.

    openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout dev.key -out dev.crt -subj "/CN=dev.com" -days 3650
    
    openssl pkcs12 -export -out dev.pfx -inkey dev.key -in shout.crt
    

    For ABP Identity Server project.

            public override void PreConfigureServices(ServiceConfigurationContext context)
            {
                var hostingEnvironment = context.Services.GetHostingEnvironment();
    
                PreConfigure<AbpIdentityServerBuilderOptions>(options =>
                {
                    options.AddDeveloperSigningCredential = false;
                });
    
                PreConfigure<IIdentityServerBuilder>(identityServerBuilder =>
                {
                    X509Certificate2 x509;
    
                    // todo: passwords need to be moved to secrets storage or deployment system
                    if (hostingEnvironment.IsDevelopment())
                    {
                        x509 = new X509Certificate2(
                            File.ReadAllBytes(Path.Combine(hostingEnvironment.ContentRootPath, "dev.pfx")),
                            "cert-password");
                    }
                    else
                    {
                        x509 = new X509Certificate2(
                            File.ReadAllBytes(Path.Combine(hostingEnvironment.ContentRootPath, "production.pfx")),
                            "dontaddhere");
                    }
    
                    identityServerBuilder
                        .AddSigningCredential(x509)
                        .AddValidationKey(x509);
                });
            }
    

    Legacy MVC Framework app. OwinConfig pipeline. For production put the password and possibly certificate somewhere outsite of the git repo.

    var x509 = new X509Certificate2(File.ReadAllBytes(Path.Combine(HostingEnvironment.ApplicationPhysicalPath, "dev.pfx")), "cert-password");
    var key = new X509SecurityKey(x509);
    
    
    app.UseJwtBearerAuthentication(
        new JwtBearerAuthenticationOptions
        {
            AuthenticationMode = AuthenticationMode.Active,
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidAudience = ConfigurationManager.AppSettings["JwtAudience"],
                ValidIssuer = ConfigurationManager.AppSettings["JwtIssuer"],
                IssuerSigningKey = key,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true
            }
        });