ASP.NET Persisting or Adding custom claim to access_token for Protected API

Nitish Chauhan 71 Reputation points
2022-01-13T22:42:42.837+00:00

I am using OIDC/OAuth with Azure Active Directory as the IDP to allow users to login to an ASP.NET 4.6.2 MVC App with their organizational account that calls a Protected Web API. This involves authorization code flow. My code is based off the sample app provided by the Sample App=[https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect]. In the sample, instead of a Protected API, it is calling Microsoft's Graph API. I am attempting to add a custom claim to the JWT token sent to the Protected API to store some user information. Now my question...

How do I add or persist a claim to an access token obtained for the Protected API?

This is necessary for my use-case since we are integrating with an existing IDP (ourselves) and we have FK relationships based on the user_id.

Currently, I am able to obtain an access token to authorize the Client MVC App to the Protected Web API using the following code:

IConfidentialClientApplication app = MsalAppBuilder.BuildConfidentialClientApplication();

var accounts = (await app.GetAccountsAsync()).ToList();

string TodoListScope = "api://{client_id}/access_as_user";
string[] Scopes = { TodoListScope };
var tokenResult = await app.AcquireTokenSilent(Scopes, accounts.FirstOrDefault())
.ExecuteAsync()
.ConfigureAwait(false);
This code is enabled by a middleware added to Notifications object on the IAppBuilder.UseOpenIdConnectAuthentication function.

app.UseOpenIdConnectAuthentication{ new OpenIdConnectAuthenticationOptions{
...,
...,
Notifications = new OpenIdConnectAuthenticationNotifications
{
AuthorizationCodeReceived = OnAuthorizationCodeReceived,
AuthenticationFailed = OnAuthenticationFailed,
RedirectToIdentityProvider = OnRedirectToIdentityProvider,
SecurityTokenValidated = OnSecurityTokenValidated
}
}
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
{
// Upon successful sign in, get the access token & cache it using MSAL
IConfidentialClientApplication clientApp =
MsalAppBuilder.BuildConfidentialClientApplication();
AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[]
{ "api://{client_id}/access_as_user" }, context.Code).ExecuteAsync();
}
I have found proposed solutions to add claims to an access token but this only adds these claims to the access_token associated with the MVC Client App Controllers NOT the Protected API. So when these claims are searched for on the claims of the JWT token for the Protected API, they are not found.

private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> arg)
{
arg.AuthenticationTicket.Identity.AddClaim(new Claim("customClaim", "customValue"));
var claimsPrincipal = new ClaimsPrincipal(arg.AuthenticationTicket.Identity);
arg.OwinContext.Request.User = claimsPrincipal;
return Task.FromResult(0);
}
If there is a solution, I assume it's on the OnAuthorizationCodeReceived function.

Thanks for any help, definitely grey-hairing a bit on this problem.

ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,272 questions
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
19,563 questions
0 comments No comments
{count} votes

Accepted answer
  1. Bruce (SqlWork.com) 56,766 Reputation points
    2022-01-14T17:42:04.8+00:00

    in your application you can add custom claims to the principle because your app is creating the principle on each request. To add a custom claim to an access token, the code must be in the producer of the access token.

    typically the authentication software that produces the access token allows creating custom scopes that can return additional claims. see your authentication software/

    if you are using a 3rd party authentication software, and can not add the claim, then one option is to create a new authentication endpoint. you would pass it the access token which it verified. if valid it would create a new access token with the additional claims. this token would be used instead of the original. the consumer of the new token would validate against this new endpoint rather than the original.

    the endpoints could be hosted by server both sites can access. if both sites can access each other, the original site could host the endpoints.

    0 comments No comments

0 additional answers

Sort by: Most helpful