I'm trying to create an Angular 10 front end that accesses a .NET Core 3.1 Web Api back end. Both of them secured under Azure AD using the MSAL Libraries. I created and SPA app usign Visual Studio 2019's SPA Angular Template for Web Apps. On the client app, I'm using msal-angular to log in and get an access token. I followed both the Quickstart, the Tutorial and finally I've tried withe the Single Page App Scenario (using the implicit flow). For the Web API, I followed what is explained in the Single Page App Scenario and also I've tried with the Protected web API Scenario and Web App that calls web APIs Scenario, but when I try to access any Web API endpoint that has an Authorize decorator, I get the following error: System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.
Anyone else has successfully created something like what I'm trying to do (SPA template, Angular 10, .NET Core 3.1 web API)? What am I doing wrong or missing?
For the purposes of my question, my apps registration data are as follows:
Tenant:
Tenant Id: 'tttttttt-tttt-tttt-tttt-ttttttttttt'
Domain: 'notrealdomain.onmicrosoft.com'
Client App:
Client Id: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
API App:
Client Id: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
App Id: 'api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/access_as_user'
My token looks something like the following:
{
"aud": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"iss": "https://login.microsoftonline.com/tttttttt-tttt-tttt-tttt-ttttttttttt/v2.0",
"iat": 1595531437,
"nbf": 1595531437,
"exp": 1595535337,
"aio": "ATQAy/8QAA01PbjYzolbeAAE6rlHrUQ5ndpD/CDAxneSI8BsXSdm3Sl7CBYWqoS+jyBUNtJ/Ovwe",
"groups": [
"gggggggg-gggg-gggg-gggg-gggggggggggg",
"ffffffff-ffff-ffff-ffff-ffffffffffff"
],
"name": "John Doe",
"nonce": "hhhhhhhh-hhhh-hhhh-hhhh-hhhhhhhhhhhh",
"oid": "iiiiiiii-iiii-iiii-iiii-iiiiiiiiiiii",
"preferred_username": "john@notrealdomain.onmicrosoft.com",
"sub": "hrhuh3UtYWRmuT-JnNWuFhFYvWjbJFmegz7k2ay0RbI",
"tid": "tttttttt-tttt-tttt-tttt-ttttttttttt",
"uti": "PAkaSoPlaWi_vBYklUKtAA",
"ver": "2.0"
}
app.module.ts
@NgModule({
declarations: [
... code ommited ...
],
imports: [
... code ommited ...
MsalModule.forRoot({
auth: {
clientId: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
authority: 'https://login.microsoftonline.com/tttttttt-tttt-tttt-tttt-ttttttttttt/',
postLogoutRedirectUri: "https://localhost:44000/signout",
redirectUri: "https://localhost:44000/",
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: isIE, // Set to true for Internet Explorer 11
},
framework: {
unprotectedResources: ['https://localhost:44000/api/Unsecured'],
protectedResourceMap: new Map([
['https://localhost:44375', ['api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/access_as_user']],
['https://graph.microsoft.com/v1.0/me', ['user.read']],
['api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', ['access_as_user']],
])
},
}, {
popUp: false,
consentScopes: [
'user.read',
'openid',
'profile',
'api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/access_as_user',
],
extraQueryParameters: {}
}),
... code ommited ...
providers: [
... code ommited ...
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
},
I'm logging in using the following method in one of my components where this.msalService is injected as private msalService: MsalService :
this.msalService.loginRedirect({
scopes: [
'api://xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/access_as_user',
]
});
On my Web API, I have the following configuration on my appsettings.json file:
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "notrealdomain.onmicrosoft.com",
"TenantId": "tttttttt-tttt-tttt-tttt-ttttttttttt",
"ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"Audience": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
},
... code ommited ...
}
And finally, my StartUp.cs looks like this:
public void ConfigureServices(IServiceCollection services)
{
// Autenticación
services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAd");
... code ommited ...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
... code ommited ...
app.UseRouting();
// Autorización
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
... code ommited ...
}

