I have experience setting up Auth0 with Xamarin.Forms, but I’m taking my first stab at configuring a Blazor Client Side (WASM) app to work with Auth0 and also authenticate against my aspnet core webapi backend.
So far I have followed a number of blog posts (too many to list), but as the Blazor landscape is changing so much, I’m no longer confident in their relevance. Here’s the scenario that I have personally at a high level.
Data stored in MongoDB Atlas
API Hosted in Azure using aspnet core webapi (net5.0)
Blazor WASM also on Azure, also on net5.0
Future (Maui iOS/Android)
The goal that I have is to have dynamic Roles, stored in MongoDB along with the rest of my Tenant information, and to have all client side apps (Blazor & Maui) be able to authenticate against Auth0, receive an access token and refresh token, and be able to access protected data in my API.
This all seems really straightforward, but I’m really struggling with getting everything to mesh.
note: I’m going to leave my
Roles
questions for a future post and focus primarily on authentication at this point in time.
in my Blazor app, I have configured the following
builder.Services.AddOidcAuthentication(options =>
{
builder.Configuration.Bind("Auth0", options.ProviderOptions);
options.ProviderOptions.ResponseType = "code";
options.ProviderOptions.DefaultScopes.Add("offline_access");
});
I have not configured any custom AuthenticationStateProvider
as I’m not sure if it’s necessary or just muddying the waters.
In my API I have added
// Configure Services
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = $"https://{Configuration["Auth0:Authority"]}/";
options.Audience = Configuration["Auth0:Audience"];
// If the access token does not have a `sub` claim, `User.Identity.Name` will be `null`. Map it to a different claim by setting the NameClaimType below.
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = ClaimTypes.NameIdentifier
};
});
services.AddCors(opts =>
{
opts.AddDefaultPolicy(builder =>
{
builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
// Configure
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
When I launch my Blazor app, I am able to successfully authenticate and see the appropriate values on a page as follows
<AuthorizeView>
<Authorized>
You're logged in
</Authorized>
<NotAuthorized>
You have yet to authenticate
</NotAuthorized>
</AuthorizeView>
The trouble comes when I try and make an authenticated request to the server. I don’t know how to configure Blazor to pass my bearer token along with my api request. All of my requests result in a 401 response.
When I open the chrome developer tools after a sucessful authentication, I do see two entries in the “session storage”
oidc.user:[authority]:[clientId]
Microsoft.AspNetCore.Components.WebAssembly.Authentication.CachedAuthSettings
though I’m pretty sure I want these values in “local storage” and not simply session storage.