Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core authenticating with Azure Active Directory and persisting custom Claims across requests

I have a default ASP.NET Core website created within Visual Studio 2017. I have chosen to authenticate using an Azure Active Directory. I run the site and can successfully login using an account in the Active Directory.

I can retrieve Claim information provided by Active Directory, e.g. by calling the following line I get the 'name'.

User.Claims.FirstOrDefault(c => c.Type == "name")?.Value;

I want to add a custom claim - CompanyId = 123456 for the logged in user. I'm able to add a custom claim however it is only available on the page where the claim is set.

Claim claim = new Claim("CompanyId", "123456", ClaimValueTypes.String);
((ClaimsIdentity)User.Identity).AddClaim(claim);

My understanding is that I somehow need to update the token that has been issued by Active Directory or set the claim before the token is issued. I'm unsure how to do this.

I suspect this needs to be done in the AccountController at SignIn()

// GET: /Account/SignIn
[HttpGet]
public IActionResult SignIn()
{
    return Challenge(
            new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectDefaults.AuthenticationScheme);
}

I've read numerous articles and samples about this scenario (including https://github.com/ahelland/AADGuide-CodeSamples/tree/master/ClaimsWebApp) however have not managed to solve how to persist the Claim across requests.

I have successfully managed to persist custom Claims using ASP.NET Identity as the Authentication Provider, but this appears to be because the custom Claim is saved to the database..

like image 440
Fanetic Avatar asked Mar 09 '23 17:03

Fanetic


2 Answers

OnTokenValidated offers you the chance to modify the ClaimsIdentity obtained from the incoming token , code below is for your reference :

private Task TokenValidated(TokenValidatedContext context)
{
    Claim claim = new Claim("CompanyId", "123456", ClaimValueTypes.String);
    (context.Ticket.Principal.Identity as ClaimsIdentity).AddClaim(claim);

    return Task.FromResult(0);
}

Setting the OpenIdConnectEvents:

Events = new OpenIdConnectEvents
{
    OnRemoteFailure = OnAuthenticationFailed,
    OnAuthorizationCodeReceived = OnAuthorizationCodeReceived,

    OnTokenValidated = TokenValidated
}

Then in controller using :

var companyId=  User.Claims.FirstOrDefault(c => c.Type == "CompanyId")?.Value;
like image 199
Nan Yu Avatar answered Apr 26 '23 16:04

Nan Yu


For those who would like more detail, the code provided is placed in Startup.cs

In the Configure method add/edit:

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    ClientId = Configuration["Authentication:AzureAd:ClientId"],
    Authority = Configuration["Authentication:AzureAd:AADInstance"] + Configuration["Authentication:AzureAd:TenantId"],
    CallbackPath = Configuration["Authentication:AzureAd:CallbackPath"],
    Events = new OpenIdConnectEvents
    {
        OnTokenValidated = TokenValidated
    }
});

The private Task TokenValidated method is in the body of Startup.cs

The following sample is a good reference. https://github.com/Azure-Samples/active-directory-dotnet-webapp-openidconnect-aspnetcore-v2/blob/master/WebApp-OpenIDConnect-DotNet/Startup.cs

like image 40
Fanetic Avatar answered Apr 26 '23 14:04

Fanetic