I'm integrating Microsoft Entra ID into Svelte SPA and ASP.NET Core Web API. The goal is to secure the API and implement user-specific permissions dynamically.
Current configuration:
Authentication setup in Entra ID
http://localhost:3000/auth-callback
.Expose an API setup in Entra ID:
api://fxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
.AdminTool.Read
ASP.NET Core Web API configuration:
Startup (in Program.cs
):
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
appsettings.json
:
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret": "xxxxxxxxxxxxxxxxxxx"
}
],
"Scopes": "api://fxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/AdminTool.Read"
}
Frontend (Svelte):
When requesting a token, I pass the following scopes:
const scopes = ['openid', 'profile', 'api://fxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/AdminTool.Read'];
If I don't include the custom scope (AdminTool.Read
), the API rejects the request.
Questions
What exactly do these API scopes do?
How can I implement user-specific permissions dynamically?
Is there a way to manage these scopes dynamically for individual users rather than defining them statically under "Expose an API"? Best Practices?
Note: API scopes in Entra ID control access at an application level, but user-specific permissions can be managed dynamically using app roles.
Scopes are primarily used to manage access to the API at the application level, but they can also be applied on a per-user basis by checking the claims in the JWT token that is sent to your backend API.
AdminTool.Read
are defined at the application level, you can dynamically manage user-specific permissions by including app roles in the user's token.Dashboard.Read
role will be granted access to the dashboard feature in your app.To implement it, check the below:
Created API app and exposed and API:
In SPAapp, granted API permissions like below:
As you are making use of two applications (API app and SPA app), you need to create app roles in both the applications and assign the user to it on both of them.
Create app role Dashboard.Read
in both API app and SPA app:
Now assign users to the app role in both applications in Enterprise application under users and groups blade:
For sample, I generated access token by using below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id: ClientID
grant_type: authorization_code
code: Code
redirect_uri: RedirectURL
code_verifier: xxx
scope: api://xxx/AdminTool.Read
When decoded, the access token will be containing both scp and roles claim:
This depicts that the user with scope AdminTool.Read
with role Dashboard.Read
will be able to read the dashboard.
AdminTool.Read
, which grants them permission to access the AdminTool in your API.Dashboard.Read
, which grants them permission to read the dashboard.I tried to generate access token and did not assign the role to the user:
Dashboard.Read
, hence the user will not be able to read the dashboard.Reference: