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

1

1 Answer 1

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"
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.