Link to home
Start Free TrialLog in
Avatar of coder
coderFlag for Australia

asked on

JWE error in asp.net core

Hi Experts,


I am trying to do JWE in asp.net core Web API application.  I able to authenticate, sign, encrypt and get token.

I am not able to authorize web API.  I get the following error in Postman   Please see errors below



System.InvalidOperationException: No authentication handler is registered for the scheme 'Bearer'. The registered schemes are: jwt. Did you forget to call AddAuthentication().Add[SomeAuthHandler]("Bearer",...)?

   at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme)

   at Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator.AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)

   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)

   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)

   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)



the code in the program.cs is as follows:- 



string? Issuer = "https://localhost:7022";

string? Audience = "https://localhost:7022";

string? encryptionKid = "********************************";

string? signingKid = "********************************";

var encryptionKey = RSA.Create(2048);

var signingKey = ECDsa.Create(ECCurve.NamedCurves.nistP256);

var publicSigningKey = new ECDsaSecurityKey(ECDsa.Create(signingKey.ExportParameters(false))) {KeyId = signingKid};

var privateEncryptionKey = new RsaSecurityKey(encryptionKey) {KeyId = encryptionKid};

builder.Configuration["EncriptionKid"] = encryptionKid;

builder.Configuration["SigningKid"] = signingKid;

builder.Configuration["Issuer"] = Issuer;

builder.Configuration["Audience"] = Audience;


builder.Services.AddAuthentication(option =>

    {

        option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

        option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

    })

  .AddJwtBearer("jwt", options =>

  {

      options.IncludeErrorDetails = true;       

      options.Authority = "https://localhost:7022";

      options.Audience = Audience;   

      options.SaveToken = true;

            

      options.Configuration = new OpenIdConnectConfiguration();       

      options.TokenValidationParameters.ValidateIssuer = true;

      options.TokenValidationParameters.ValidateAudience = true;

      options.TokenValidationParameters.ValidIssuer = Issuer;

      options.TokenValidationParameters.ValidAudience = Audience;

      options.TokenValidationParameters.ValidateLifetime = true;

      options.TokenValidationParameters.ValidateIssuerSigningKey = true;

      options.TokenValidationParameters.SaveSigninToken = true;

      options.TokenValidationParameters.IssuerSigningKey = publicSigningKey;

      //options.TokenValidationParameters.TokenDecryptionKey = new RsaSecurityKey(encryptionKey);

      options.TokenValidationParameters.TokenDecryptionKey = privateEncryptionKey;

  });



builder.Services.AddSingleton<IConfiguration>(builder.Configuration);

builder.Services.AddHttpsRedirection(options =>

{

    options.RedirectStatusCode = (int)HttpStatusCode.TemporaryRedirect;

    options.HttpsPort = 5001;

});


var app = builder.Build();

// Configure the HTTP request pipeline.

if (app.Environment.IsDevelopment())

{

    app.UseSwagger();

    app.UseSwaggerUI();

    app.UseDeveloperExceptionPage();

    IdentityModelEventSource.ShowPII = true;

}

app.UseHttpsRedirection();

app.UseAuthentication();

        

app.UseAuthorization();

app.MapControllers();

app.Run();



code in the login controller for authentication is as follows:- 



var bStatus = Authenticate(userLogin, strUserName);

            if (bStatus)

            {

                string encryptionKid = _config["EncriptionKid"];

                string signingKid = _config["SigningKid"]; 

                var encryptionKey = RSA.Create(2048);

                var publicEncryptionKey = new RsaSecurityKey(encryptionKey.ExportParameters(false)) {KeyId = encryptionKid};

                var signingKey = ECDsa.Create(ECCurve.NamedCurves.nistP256);

                var privateSigningKey = new ECDsaSecurityKey(signingKey) {KeyId = signingKid};

                var token = CreateJwe(privateSigningKey, publicEncryptionKey, userLogin);

                return Ok(token);

            }


private string CreateJwe(SecurityKey privateSigningKey, SecurityKey publicEncryptionKey, UserLogin userLogin)

        {

            var handler = new JsonWebTokenHandler();

            var subject1  = new ClaimsIdentity(new Claim[]

            {

                new Claim(ClaimTypes.NameIdentifier, userLogin.UserName),

                new Claim(ClaimTypes.Role, userLogin.GroupName),

                new Claim(ClaimTypes.Dns, userLogin.DomainName),           

            });

            

            var signingCred = new SigningCredentials(privateSigningKey, SecurityAlgorithms.EcdsaSha256);

                

                // public key for encryption

            var encryptingCred = new EncryptingCredentials(publicEncryptionKey , SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes256CbcHmacSha512);


            var tokendescriptor = new SecurityTokenDescriptor { Audience = _config["Audience"], Issuer = _config["Issuer"], Subject = subject1, 

                Expires = DateTime.Now.AddMinutes(60), SigningCredentials = signingCred, EncryptingCredentials = encryptingCred };

            return handler.CreateToken(tokendescriptor);

        }          

   


Authorization for the Web API is as follows which fails in postman


     [Route("GetAllGroups")]              

     [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

     [HttpGet]

     public ActionResult<List<Group>> GetAllGroups(string strDomainName)

     {

            List<Group> ADMyGroups = getAllAdGroups(strDomainName);

            return ADMyGroups;

      }


Please help me in resolving this issue     

Avatar of David Johnson, CD
David Johnson, CD
Flag of Canada image

https://www.scottbrady91.com/c-sharp/json-web-encryption-jwe-in-dotnet-core


dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

Open in new window

Then, in your authentication registration, you need to set the authority and audience properties like usual, with the added step of setting the token decryption key on the token validation parameters, which needs to be your private key used for decryption.

builder.Services.AddAuthentication("jwt")
  .AddJwtBearer("jwt", options =>
  {
      options.Authority = "https://localhost:5000";
      options.Audience = "api1";
      options.TokenValidationParameters.TokenDecryptionKey = new RsaSecurityKey(encryptionKey);
  });

Open in new window

Don’t forget the call to UseAuthentication in your pipeline!

Avatar of coder

ASKER

@David,
   
     Thanks for your response.  I had tried all these options.

I have Microsoft.AspNetCore.Authentication.JwtBearer installed.

I have tested with these below options it fails.

options.Authority = "https://localhost:5000"
options.Audience = "api1"

But my application runs on "https://localhost:7022.
Hence I have given authority and audience as https://localhost:7022

options.TokenValidationParameters.TokenDecryptionKey = new RsaSecurityKey(encryptionKey); is not valid.

I had tested with
var privateEncryptionKey = new RsaSecurityKey(encryptionKey) {KeyId = encryptionKid};

with keyid = encryptionKid.

but in scott brady article in the git hub source code it uses key id for decryption (TokenValidationParameters.TokenDecryptionKey)

I think it is not the problem with encryption or decryption, it is the problem to do with the settings with .net.

In program.cs It has code for authentication and authorization for the rest apis(Validation and verfication tokens), in login controller I create token which is signed and encryption.(creating tokens)

There something I miss in the .Net part for validation and verification of the token

The error is System.InvalidOperationException: No authentication handler is registered for the scheme 'Bearer'. The registered schemes are: jwt. Did you forget to call AddAuthentication().Add[SomeAuthHandler]("Bearer",...)?

I am not able figure out what I miss?
Please advise what I have to do.

I am not currently well versed in doing this in .net. However, these services work similarly. 



Start with the documentation for the service you are using and review the examples. Then in Postman, check what is being sent to the server and compare that to what is expected.  From that difference, you may be able to determine what to do in .NET to get to what is expected. 


As example, are you sure you are ending up with


GET: \api\route   

Authorization: Bearer <TOKEN>


when perhaps it needed something different?

ASKER CERTIFIED SOLUTION
Avatar of coder
coder
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial