0

You have a webapi project build on microservice architecture now I have a requirement of implementing JWT authentication in the web api project the for that I have created a seperate API project which will give the JWT Token.

In the Auth.API project in program.cs I have configured JWT middleware like this

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false; // Set to true in production
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
        ValidateIssuer = false,
        ValidateAudience = false
    };
});

I have a controller and login action to generate the token like this

[ApiController]
    [Route("api/[controller]")]
    public class LoginController : ControllerBase
    {
        public IConfiguration _configuration;

        public LoginController(IConfiguration config)
        {
            _configuration = config;
        }
        
        [HttpPost("login")]
        public IActionResult Login([FromBody] LoginModel loginModel)
        {
            // Authenticate the user (check username and password)
            //if (userIsValid)
            //{
            //    var token = GenerateJwtToken(username); // Implement this method to generate a JWT token
            //    return Ok(new { Token = token });
            //}
            if(loginModel.Username == "admin" && loginModel.Password == "admin")
            {
                var token = GenerateJwtToken(loginModel.Username); // Implement this method to generate a JWT token
                return Ok(new { Token = token });
            }
            
            return Unauthorized();
        }

        private string GenerateJwtToken(string username)
        {
            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]); // Replace with your secret key

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new[]
                {
                new Claim(ClaimTypes.Name, username)
                // Add other claims as needed
            }),
                Expires = DateTime.UtcNow.AddHours(1), // Token expiration time
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };

            var token = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(token);
        }
    }

Now in my actual web api project I have configured JWT like this

builder.Services.AddAuthentication("Bearer")
        .AddJwtBearer("Bearer", options =>
        {
            options.Authority = "https://localhost:7062/"; // URL of Auth.API
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateAudience = false
            };
        });

And in controller I have assigned [Authorize] attribute But when I am hitting the API from postman it is giving below error

System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'. ---> System.IO.IOException: IDX20807: Unable to retrieve document from: 'System.String'. HttpResponseMessage: 'System.Net.Http.HttpResponseMessage', HttpResponseMessage.Content: 'System.String'. at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync(CancellationToken cancel) --- End of inner exception stack trace --- at Microsoft.IdentityModel.Protocols.ConfigurationManager1.GetConfigurationAsync(CancellationToken cancel) at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.AuthenticateAsync() at Microsoft.AspNetCore.Authentication.AuthenticationService.AuthenticateAsync(HttpContext context, String scheme) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext) at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS

Accept: / Connection: keep-alive Host: localhost:7129 User-Agent: PostmanRuntime/7.28.4 Accept-Encoding: gzip, deflate, br Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiYWRtaW4iLCJuYmYiOjE2OTIyNzE3ODIsImV4cCI6MTY5MjI3NTM4MiwiaWF0IjoxNjkyMjcxNzgyfQ.70HmNyP8VyirxN8E8vN3Kfb9NLE8cepR2BXfrg9EN3k Content-Type: application/json Content-Length: 50 Postman-Token: 37e5176a-43c8-488d-994f-61e0b558e3c8

Thanks Utpal Maity

Utpal
  • 805
  • 4
  • 15
  • 44
  • In this post they solve the same or similar problem https://stackoverflow.com/questions/40281050/jwt-authentication-for-asp-net-web-api?rq=2 – SeiryuV Aug 17 '23 at 11:54

1 Answers1

0

You don't appear to be using OpenId, so

options.Authority = //metadata discovery endpoint

is not required.

You should be able to remove that line and go with:

options.TokenValidationParameters = new TokenValidationParameters
{
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])),
    ValidateIssuer = false,
    ValidateAudience = false
};

You'll need to make sure you WebAPI project has appropriate details in appSettings.json:

"Jwt": {
   "Key": "THE_KEY_USED_BY_YOUR_AUTHAPI_PROJECT"
}
Neil W
  • 7,670
  • 3
  • 28
  • 41