4

I've created a DEFAULT ASP.NET Core 6 React app with Individual Accounts enabled and SQLite as the default database:

dotnet new react -au Individual -o core-react-sqlite

But then when I run the app, register a new user, confirm the user, login, navigate to "Fetch data" (https://localhost:44480/fetch-data) I get a 401 Unauthorized error:

enter image description here

Any ideas why?

I've checked the docs (here, here, and here) but it doesn't say much about authorization when using React or maybe I'm just reading it wrong?

Here's my Program.cs (default):

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.EntityFrameworkCore;
using core_react_sqlite.Data;
using core_react_sqlite.Models;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddIdentityServer()
    .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

builder.Services.AddAuthentication()
    .AddIdentityServerJwt();

builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");
app.MapRazorPages();

app.MapFallbackToFile("index.html");;

app.Run();
PussInBoots
  • 11,028
  • 9
  • 52
  • 84

2 Answers2

0

In the configuration for AddJwtBearer in the API, you can set the following flag to true:

.AddJwtBearer(opt =>
{
     opt.IncludeErrorDetails = true;
     ...

If you do this, then you will get an extra header in the 401 error response that can give you some clues why the request failed:

HTTP/1.1 401 Unauthorized
Date: Sun, 02 Aug 2020 11:19:06 GMT
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"

To complement this answer, I wrote a blog post that goes into more detail about this topic: Troubleshooting JwtBearer authentication problems in ASP.NET Core

Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40
  • AddJwtBearer() doesn't exist in my project. See question; I've added the Program.cs. – PussInBoots Aug 07 '22 at 17:37
  • aha, missed that. But as a starting point ,my recommendation is not to mix the react backend with IdentityServer, because it will so much harder to reason about and debug. Better to put IdentityServer in its own service. – Tore Nestenius Aug 07 '22 at 19:22
  • Ah, Saw you used AddIdentityServerJwt() and that one indirectly uses the JwtBearer handler (see https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?view=aspnetcore-6.0#addidentityserverjwt ) – Tore Nestenius Aug 07 '22 at 19:26
  • In the request to the WeatherForecast endpoint, are there any token included in that request? and if so, what does it contain? 401 means that you are not authenticated, either token error or token missing. – Tore Nestenius Aug 07 '22 at 19:28
  • I've noticed some weird behavior in the react template. Sometimes fetching the weather forecast data works, sometimes it doesn't. For instance I deleted the entire node_modules folder once and then it started working again - it seems to be related to the proxy that is spun up somehow. I've no idea how all of these pieces work and it's very hard to debug. – PussInBoots Aug 08 '22 at 16:33
  • Yes, is so much harder to debug when all is one service, a better approach is keep them apparat, following the single responsibility principle – Tore Nestenius Aug 09 '22 at 06:07
-1

After a lot of reading I've learned that in 99% of all cases you should opt for a managed identity provider.

In my case I went with Azure AD B2C since it's the most generous, I already have the rest of my infrastructure on Azure, and docs seem ok.

PussInBoots
  • 11,028
  • 9
  • 52
  • 84