ASP.NET Core JWT Authentication Returning Unauthorized(invalid-token 401) for Authenticated Requests in Controller Actions

Antonio Simonetti 0 Reputation points
2024-07-24T16:02:32.3133333+00:00

Hi everyone,

I'm encountering an issue with JWT authentication in my ASP.NET Core 8.0 application. While the token generation and authentication seem to work correctly in my AuthenticationController, any requests to other controllers requiring authorization are returning 401 Unauthorized.

The JWT token is generated and validated successfully in the AuthenticationController. However, when I try to access other controllers that require authorization, I receive a 401 Unauthorized response. The JWT issuer, audience, and secret are configured correctly in Azure and are being used successfully in the AuthenticationController.

For testing purposes, I added the action that I want to use in the other controller (which doesn't work) inside the AuthenticationController, and it works even without the [Authorize] attribute on that controller.

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,912 questions
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,606 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,505 questions
ASP.NET API
ASP.NET API
ASP.NET: A set of technologies in the .NET Framework for building web applications and XML web services.API: A software intermediary that allows two applications to interact with each other.
342 questions
{count} votes

4 answers

Sort by: Most helpful
  1. Antonio Simonetti 0 Reputation points
    2024-07-24T16:04:49.0933333+00:00
    using Expenses.Data;
    using expensesBE.Data.DTO.Interfaces;
    using expensesBE.Data.DTO;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.IdentityModel.Tokens;
    using System.Text;
    var builder = WebApplication.CreateBuilder(args);
    var jwtIssuer = Environment.GetEnvironmentVariable("JWT_ISSUER");
    var jwtSecret = Environment.GetEnvironmentVariable("JWT_SECRET");
    var jwtAudience = Environment.GetEnvironmentVariable("JWT_AUDIENCE");
    if (string.IsNullOrEmpty(jwtIssuer) || string.IsNullOrEmpty(jwtSecret) || string.IsNullOrEmpty(jwtAudience))
    {
    	throw new ArgumentNullException("JWT configuration is missing");
    }
    var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
    builder.Services.AddDbContext<AppDbContext>(options =>
    	options.UseSqlServer(connectionString));
    // Configura Identity
    builder.Services.AddDefaultIdentity<IdentityUser>(options =>
    {
    	options.SignIn.RequireConfirmedAccount = true;
    }).AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<AppDbContext>();
    builder.Services.AddAuthentication(options =>
    {
    	options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    	options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    }).AddJwtBearer(options =>
    {
    	options.TokenValidationParameters = new TokenValidationParameters
    	{
    		ValidateIssuer = true,
    		ValidateAudience = true,
    		ValidateLifetime = true,
    		ValidateIssuerSigningKey = true,
    		ValidIssuer = jwtIssuer,
    		ValidAudience = jwtIssuer,
    		IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret))
    	};
    });
    builder.Services.AddScoped<IUserService, UserService>();
    builder.Services.AddScoped<IExpensesServices, ExpensesServices>();
    builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
    builder.Services.AddCors(options =>
    {
    	options.AddPolicy("AllowAllOrigins", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
    });
    // Add services to the container.
    builder.Services.AddControllers();
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    builder.Services.AddControllersWithViews();
    var app = builder.Build();
    if (!app.Environment.IsDevelopment())
    {
    	app.UseExceptionHandler("/Home/Error");
    	app.UseHsts();
    }
    app.UseSwagger(); // Enable Swagger
    app.UseSwaggerUI(); // Enable Swagger UI
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseCors("AllowAllOrigins");
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapRazorPages();
    app.MapControllers();
    app.MapControllerRoute(
    	name: "default",
    	pattern: "{controller=Home}/{action=Index}/{id?}"
    );
    app.Run();
    

  2. Bruce (SqlWork.com) 66,461 Reputation points
    2024-07-24T21:22:58.0666667+00:00

    authentication is only required if you specify that controller needs authentication. when your javascript ajax calls the controller is it passing the bearer token?

    const rs = await fetch(
        url,
        {
            headers: {Authorization: `Bearer ${token}`}
        }).then(resp => resp.json());  
    
    0 comments No comments

  3. SurferOnWww 3,041 Reputation points
    2024-07-25T01:39:13.94+00:00

    Please try the followings. If you could complete (1) through (7) I will add the description and code to generate the JWT required for authentication, send the JWT to the API and obtain the JSON response

    (1) Create project

    Use template of Visual Studio 2022. Select the ASP.NET Core Web API:

    enter image description here

    Set the Authentication type to none:

    enter image description here

    (2) Install NuGet package

    Install the Microsoft.AspNetCore.Authentication.JwtBearer:

    enter image description here

    (3) Register JWT Authntocation

    Open the Program.cs and add the service and middleware for the JWT-based authentication, as follows:

    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.IdentityModel.Tokens;
    using System.Text;
    
    namespace WebApiJwtCors
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var builder = WebApplication.CreateBuilder(args);
    
                // Add services to the container.
    
                // Add service for JWT-based 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"]!))
                        };
                    });
    
                builder.Services.AddControllers();
                // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
                builder.Services.AddEndpointsApiExplorer();
                builder.Services.AddSwaggerGen();
    
                var app = builder.Build();
    
                // Configure the HTTP request pipeline.
                if (app.Environment.IsDevelopment())
                {
                    app.UseSwagger();
                    app.UseSwaggerUI();
                }
    
                app.UseHttpsRedirection();
    
                // Add middleware for JWT-based authentication
                app.UseAuthentication();
    
                app.UseAuthorization();
    
    
                app.MapControllers();
    
                app.Run();
            }
        }
    }
    

    (4) Add Key and Issuer

    Add Jwt element to the appsettings.json so that the TokenValidationParameters constractor in the above (3) code can obtain the values of Key and Issuer:

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "AllowedHosts": "*",
      "Jwt": {
        "Key": "veryVerySecretKeyWhichMustBeLongerThan32",
        "Issuer": "https://localhost:44344"
      }
    }
    

    (5) Add CORS, only if required

    Open the Program.cs and add the service and middleware for the CORS as follows:

    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.IdentityModel.Tokens;
    using System.Text;
    
    namespace WebApiJwtCors
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                var builder = WebApplication.CreateBuilder(args);
    
                // Add services to the container.
    
                // Add service for CORS 
                var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
                builder.Services.AddCors(options =>
                {
                    options.AddPolicy(name: MyAllowSpecificOrigins,
                                      policy =>
                                      {
                                          policy.AllowAnyOrigin()
                                                .AllowAnyHeader()
                                                .AllowAnyMethod();
                                      });
                });
    
                // Add service for JWT-based 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"]!))
                        };
                    });
    
                builder.Services.AddControllers();
                // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
                builder.Services.AddEndpointsApiExplorer();
                builder.Services.AddSwaggerGen();
    
                var app = builder.Build();
    
                // Configure the HTTP request pipeline.
                if (app.Environment.IsDevelopment())
                {
                    app.UseSwagger();
                    app.UseSwaggerUI();
                }
    
                app.UseHttpsRedirection();
    
                // Add middleware for CORS 
                app.UseCors(MyAllowSpecificOrigins);
    
                // Add middleware for JWT-based authentication
                app.UseAuthentication();
    
                app.UseAuthorization();
    
    
                app.MapControllers();
    
                app.Run();
            }
        }
    

    (6) Build and confirm

    Confirm that the WeatherForecast controller returns the JSON response as expected:

    enter image description here

    (7) Add [Authorize] attribute

    Add [Authorize] attribute to the Get() method of WeatherForecastController as shown below:

    enter image description here

    Confirm that the WeatherForecast controller returns HTTP 401 Unauthorized response:

    enter image description here


  4. SurferOnWww 3,041 Reputation points
    2024-07-25T03:21:53.3566667+00:00

    deleted because duplicated

    0 comments No comments

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.