Search code examples
c#.netazure-active-directoryopenid-connectclaims

Adding Custom Claim to AAD OpenIDConnect Authenticated User


I have an MVC app, .NET v. 4.5.2, within which I have a need to add custom claims to AAD OpenIDConnect authenticated users.

Authentication code (Startup.cs):

    string clientId = System.Configuration.ConfigurationManager.AppSettings["ClientId"];
    string redirectUrl = System.Configuration.ConfigurationManager.AppSettings["redirectUrl"];
    static string tenant = System.Configuration.ConfigurationManager.AppSettings["Tenant"];
    string authority = String.Format(System.Globalization.CultureInfo.InvariantCulture, System.Configuration.ConfigurationManager.AppSettings["Authority"], tenant);

    public void Configuration(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
            ClientId = clientId,
                Authority = authority,
                RedirectUri = redirectUrl,

            PostLogoutRedirectUri = redirectUrl,

            Scope = OpenIdConnectScope.OpenIdProfile,

            ResponseType = OpenIdConnectResponseType.IdToken,

            TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuer = true
                },

            Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthenticationFailed = OnAuthenticationFailed,
                    AuthorizationCodeReceived = async context =>
                    {
                        var id = new ClaimsIdentity(context.AuthenticationTicket.Identity.AuthenticationType);
                        //var id = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationType);

                        id.AddClaims(context.AuthenticationTicket.Identity.Claims);
                        var appToken = context.ProtocolMessage.AccessToken;
                        id.AddClaim(new Claim("MyTestClaim", appToken));
                        id.AddClaim(new Claim("MyTestClaim2", "TestValue"));

                        context.AuthenticationTicket = new AuthenticationTicket
                        (
                             new ClaimsIdentity(id.Claims, context.AuthenticationTicket.Identity.AuthenticationType),
                               context.AuthenticationTicket.Properties
                        );
                    }
               }
            }
        );

The following line in the home controller is always null:

var userClaims = User.Identity as System.Security.Claims.ClaimsIdentity;
var test = userClaims?.FindFirst("MyTestClaim")?.Value;

All of the claims which come through from the user being authenticated are shown, but I cannot get the "MyTestClaim" to show up.


Solution

  • Turns out my code was in the wrong OpenIdConnectAuthenticationNotifications section. Instead of using AuthorizationCodeReceived, I should have been using SecurityTokenValidation. Adding custom claims here has also (so far) ensured that the custom claims do not disappear when the user navigates to different pages in the app.

     Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthenticationFailed = OnAuthenticationFailed,
                        SecurityTokenValidated = async (x) =>
                        {
                            var identity = x.AuthenticationTicket.Identity;
                            identity.AddClaim(new Claim("test", "test"));
    
                            await Task.FromResult(0);
                        }
                     }
    

    Credit