I have protected my .NET 8 Blazor app using Microsoft Identity. In my application I want to fetch data from my API which is also protected using Microsoft Identity. I use the DownstreamAPI to send a request on behalf of the user. I followed a tutorial from Microsoft to setup my application. This tutorial is based on .NET 7, and there it works fine so my setup seems to be right.
Program.cs
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration)
.EnableTokenAcquisitionToCallDownstreamApi(
new string[] {
builder.Configuration.GetSection("DownstreamApi:Scopes:Read").Get<string>()!,
builder.Configuration.GetSection("DownstreamApi:Scopes:Write").Get<string>()!
}
)
.AddDownstreamApi("DownstreamApi", builder.Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
builder.Services.AddControllersWithViews()
.AddMicrosoftIdentityUI();
builder.Services.AddAuthorization(options =>
{
// By default, all incoming requests will be authorized according to the default policy
options.FallbackPolicy = options.DefaultPolicy;
});
// Add services to the container.
builder.Services.AddRazorPages();
Appsettings.json
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/<DIRECTORY>/",
"ClientId": "<CLIENT_ID>",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath ": "/signout-oidc",
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret": "<CLIENT_SECRET>"
}
]
},
"DownstreamApi": {
"Scopes": {
"Read": "api://<CLIENT_ID>/ToDoList.Read",
"Write": "api://<CLIENT_ID>/ToDoList.ReadWrite"
},
"BaseUrl": "https://localhost:7281"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
Sending request
@inject IDownstreamApi DownstreamApi;
...
@code
{
...
private async Task GetFromApi()
{
try
{
Console.WriteLine("Getting token");
var auth = await DownstreamApi.CallApiForUserAsync(
ServiceName,
options => options.RelativePath = "/api/authTest");
Console.WriteLine(auth.StatusCode);
Console.WriteLine(auth.Content.ReadAsStringAsync().Result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
The problem is that the bearer token it is sending to the API does not seem to be right. When I destruct the bearer tokens using jwt.io these are the results:
.NET 7 (Working token):
.NET 8 (Invalid token)
I can't seem to find out what I am missing or doing wrong.


Just like what you mentioned, the token looks to be the incorrect token.
I had codes below to generate 2 tokens, let's see the differences.
I used
ITokenAcquisitionservice to generate access token we required to call external APIs which is also secured by AAD, the first token is used to call MS Graph API, the second token is for my custom API.Since you didn't share any codes to prove what kind of Blazor App you are having, so that I can only share all my related codes and settigns. What I used is a blazor web app .net 8 which is converted from blazor server project .net 7. You can take a look at this answer to see what I changed in the migration.
In the
Index.razor, injectITokenAcquisitionservice to generate access token, because we already haveEnableTokenAcquisitionToCallDownstreamApiin Program.cs.Although I had downstream API settings with Graph API, it doesn't affect me to use On_behalf_flow to generate another access token for other scopes.
I trust a correct access token can help solve your error. Here's my test result for the token generation.