1

ASP.NET Core JWT authentication stopped working after upgrading ASP.NET Core Web API from .NET Core 3.1 to .NET 8 (v8.0.100-preview.5.23303.2) when running in Docker container.

The JWT token generated by another service that I don't have access to the source code, while the project I working on supposed to validate authorization using said JWT token.

The project I working on was upgraded using .NET Upgrade Assistant and working fine on my Windows machine but doesn't work inside Docker container. I have try using JWTBearer 3.1.1 instead of the preview, tweaking Startup.cs (similar issue) but the API always returned "Invalid-Token" despite having HTTP status 200.

Here is the Startup.cs:

using System.Net;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using AppName.Models;

namespace AppName
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true,
                        ValidIssuer = new BaseUrls().getJwtIssuer(),
                        ValidAudience = new BaseUrls().getJwtAudience(),
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(new BaseUrls().getJwtKey()))
                    };
                });
            services.AddControllersWithViews();
            services.AddMemoryCache();
            services
                .AddMvc(option => option.EnableEndpointRouting = false)
                .AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())
                .AddNewtonsoftJson(options => options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local);
            services.AddSession();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStatusCodePages(async context => 
            {
                var request = context.HttpContext.Request;
                var response = context.HttpContext.Response;

                if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
                {
                    response.Redirect("/account/login");
                }
            });

            app.UseAuthentication();
            app.UseAuthorization();
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Here is the .csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ServerGarbageCollection>false</ServerGarbageCollection>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="EFCore.BulkExtensions" Version="3.1.0" />
    <PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
    <PackageReference Include="Microsoft.IdentityModel.Tokens" Version="6.31.0" />
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.31.0" />
    <PackageReference Include="Flurl.Http" Version="2.4.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.DataProtection" Version="8.0.0-preview.5.23302.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.0-preview.5.23302.2" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0-preview.5.23280.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.0-preview.5.23280.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0-preview.5.23280.1" />
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  </ItemGroup>
</Project>

The dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:8.0.0-preview.5-jammy-amd64 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:8.0.100-preview.5-jammy-amd64 AS build
WORKDIR /src
COPY ["AppName/AppName.csproj", "AppName/"]
RUN dotnet restore "AppName/AppName.csproj"
COPY . .
RUN find -type d -name bin -prune -exec rm -rf {} \; && find -type d -name obj -prune -exec rm -rf {} \;
WORKDIR "/src/AppName"
RUN dotnet build "AppName.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "AppName.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "AppName.dll"]
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

1

Turns out I should not use preview version of nuget packages. Switch packages version to latest stable and it's work as expected.