Authentication with jwt doen't work for minimal apis

Serge 20 Reputation points
2024-08-26T19:21:29.7066667+00:00

Hi

I have minimal Api project and use Identity.

For user authentication I would like use jwt tokens instead cookies.

This is my code

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = IdentityConstants.BearerScheme;
    options.DefaultChallengeScheme = IdentityConstants.BearerScheme;
}).AddBearerToken();

Login endpoint

app.MapPost("/login", async ([FromServices] SignInManager<ApplicationUser> signInManager, LoginRequestModel model) =>
{
   signInManager.AuthenticationScheme = "BearerToken";
    var result = await signInManager.PasswordSignInAsync(model.Email,model.Password,false,false);
    if(result.Succeeded)
    {
        return TypedResults.Empty;
       
    }
    return Results.BadRequest();

after login I received accessToken , refreshToken

but when I try to access to authorized endpoint , jwt token not validated
for example. How I can fix it? Maybe I miss something in setup ?



app.MapGet("userinfo", async ([FromServices] IClientService clientService, [FromServices]UserManager <ApplicationUser> userManager,ClaimsPrincipal claimsPrincipal) =>
{
    if (await userManager.GetUserAsync(claimsPrincipal) is not { } user)
    {
        return Results.BadRequest();
    }
    var email = await userManager.GetEmailAsync(user);
    return TypedResults.Ok(email);

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,504 questions
{count} votes

3 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 63,746 Reputation points
    2024-08-26T20:15:49.9233333+00:00

    it is not clear how the api callers get the bearer token. typically the login endpoint would return the token (maybe as json), but yours does not. how did the code calling /userinfo get the bearer token to pass?

    // json result token: is token
    const token  = await fetch("login",{
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify(user)
    ).then(r => r.json()).then(r => r.token);
    
    const userInfo = await fetch("userinfo",
    {
      headers: {Authorization: 'Bearer {token}'}
    }).then(r => r.json());
    

  2. Serge 20 Reputation points
    2024-08-27T04:59:49.9366667+00:00

    I use login endpoint for token , but generated token not valid ( checked via jwt.io)

    app.MapPost("/login", async ([FromServices] SignInManager<ApplicationUser> signInManager, LoginRequestModel model) => { signInManager.AuthenticationScheme = "BearerToken"; var result = await signInManager.PasswordSignInAsync(model.Email,model.Password,false,false); if(result.Succeeded) { return TypedResults.Empty; } return Results.BadRequest();
    

    Screenshot 2024-08-27 085924


  3. SurferOnWww 2,661 Reputation points
    2024-08-28T01:32:52.9333333+00:00

    I could not see the code which enables JWT authentication and issues JWT in your question above. Shown below is a sample which I use in my ASP.NET Core Web API project. Hope they can help:

    (1) Install NuGet package Microsoft.AspNetCore.Authentication.JwtBearer.

    (2) Register JWT authentication schema in the Program.cs:

    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.IdentityModel.Tokens;
    using System.Text;
    using WebApi.Data;
    using Microsoft.EntityFrameworkCore;
     
    namespace WebApi
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var builder = WebApplication.CreateBuilder(args);
     
                // Add the following for JWT authentication
                builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options =>
                    {
                        options.TokenValidationParameters = new TokenValidationParameters
                        {
                            ValidateIssuer = true,
                            ValidateAudience = true,
                            ValidateLifetime = true,
                            ValidateIssuerSigningKey = true,
                            ValidIssuer = builder.Configuration["Jwt:Issuer"],
                            ValidAudience = builder.Configuration["Jwt:Issuer"],
                            IssuerSigningKey = new SymmetricSecurityKey(
                                Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
                        };
                    });
     
                // code omitted
     
                // Add the following for JWT authentication
                app.UseAuthentication();
     
                // code omitted
    

    (3) Add key and issuer in appsettings.json

    {
     
      ... code omitted ...
     
      "AllowedHosts": "*",
      "Jwt": {
        "Key": "veryVerySecretKeyWhichMustBeLongerThan32",
        "Issuer": "https://<your hostname>"
      }
    }
    

    (4) Add controller and action method to issue JWT token

    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.IdentityModel.Tokens;
    using System.IdentityModel.Tokens.Jwt;
    using System.Text;
     
    namespace WebApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TokenController : ControllerBase
        {
            private readonly IConfiguration _config;
            private readonly UserManager<IdentityUser> _userManager;
     
            public TokenController(IConfiguration config,
                                   UserManager<IdentityUser> userManager)
            {
                _config = config;
                _userManager = userManager;
            }
     
            [AllowAnonymous]
            [HttpPost]
            public async Task<IActionResult> CreateToken(LoginModel login)
            {
                string? id = login.Username;
                string? pw = login.Password;
                IActionResult response = Unauthorized();
     
                if (!string.IsNullOrEmpty(id) && !string.IsNullOrEmpty(pw))
                {
                    var user = await _userManager.FindByNameAsync(id);
                    if (user != null && 
                        await _userManager.CheckPasswordAsync(user, pw))
                    {
                        var tokenString = BuildToken();
                        response = Ok(new { token = tokenString });
                    }
                }
     
                return response;
            }
     
     
            private string BuildToken()
            {
                var key = new SymmetricSecurityKey(
                    Encoding.UTF8.GetBytes(_config["Jwt:Key"]!));
     
                var creds = new SigningCredentials(
                    key, SecurityAlgorithms.HmacSha256);
     
                var token = new JwtSecurityToken(
                    issuer: _config["Jwt:Issuer"],
                    audience: _config["Jwt:Issuer"],
                    claims: null,
                    notBefore: null,
                    expires: DateTime.Now.AddMinutes(30),
                    signingCredentials: creds);
     
                return new JwtSecurityTokenHandler().WriteToken(token);
            }
        }
     
        public class LoginModel
        {
            public string? Username { get; set; }
            public string? Password { get; set; }
        }
    }
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.