16

I have questions upon using the new ASP.Net OpenID Connect framework while adding new Claims during the authentication pipeline as shown in the code below. I'm not sure just how much 'magic' is happening behind the scenes. I think most of my questions center around not knowing much about OWIN authentication middleware as opposed to OpenID Connect.

Q1. Should I be manually setting HttpContext.Current.User and Thread.CurrentPrincipal from OwinContext.Authentication.User?

Q2. I want the ability to add object types to claims like I used to with System.IdentityModel.Claims.Claim. The new System.Security.Claims.Claim class only accepts string values?

Q3. Do I need to use the new SessionSecurityToken wrapper for my ClaimsPrincipal in System.Security.Claims.CurrentPrincipal for serializing into a cookie - I am using app.UseCookieAuthentication(new CookieAuthenticationOptions()); but now sure what that does exactly in terms of maintaining any additional claims I added during SecurityTokenValidated event?

    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectUri,

                Notifications = new OpenIdConnectAuthenticationNotifications()
                {
                    SecurityTokenValidated = (context) =>
                    {
                        // retriever caller data from the incoming principal
                        var UPN = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.Name).Value;
                        var db = new SOSBIADPEntities();

                        var user = db.DomainUser.FirstOrDefault(b => (b.EntityName == UPN));

                        if (user == null)
                        {
                            // the caller was not a registered user - throw to block the authentication flow
                            throw new SecurityTokenValidationException();
                        }

                        var applicationUserIdentity = new ClaimsIdentity();
                        applicationUserIdentity.AddClaim(new Claim(ClaimTypes.Name, UPN, ""));
                        applicationUserIdentity.AddClaim(new Claim(ClaimTypes.Sid, user.ID.ToString(CultureInfo.InvariantCulture)));


                        var applications =
                            db.ApplicationUser
                            .Where(x => x.ApplicationChild != null && x.DomainUser.ID == user.ID)
                            .Select(x => x.ApplicationChild).OrderBy(x => x.SortOrder);

                        applications.ForEach(x =>
                            applicationUserIdentity.AddClaim(new Claim(ClaimTypes.System, x.ID.ToString(CultureInfo.InvariantCulture))));

                        context.OwinContext.Authentication.User.AddIdentity(applicationUserIdentity);

                        var hasOutlook = context.OwinContext.Authentication.User.HasClaim(ClaimTypes.System, "1");

                        hasOutlook = hasOutlook;

                        HttpContext.Current.User = context.OwinContext.Authentication.User;
                        Thread.CurrentPrincipal = context.OwinContext.Authentication.User;

                        var usr = HttpContext.Current.User;

                        var c =  System.Security.Claims.ClaimsPrincipal.Current.Claims.Count();


                        return Task.FromResult(0);
                    },
                }
            }
        );
    }
abatishchev
  • 98,240
  • 88
  • 296
  • 433
puri
  • 1,829
  • 5
  • 23
  • 42

2 Answers2

19

Is there a specific reason for which you are adding a new ClaimsIdentity?

The simplest way of doing what you are aiming at is to retrieve the ClaimsIdentity that was generated by validating the incoming token, via ClaimsIdentity claimsId = context.AuthenticationTicket.Identity; once you have it, just add claims to it. The rest of the middleware will take care of serializing it in the session cookie along with everything else, place the result in the current ClaimsPrincipal, and all those other things you appear to be trying to do manually.
HTH
V.

BenV
  • 12,052
  • 13
  • 64
  • 92
vibronet
  • 7,364
  • 2
  • 19
  • 21
0

When performing the token validation you can SignIn with new Identity:

private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> n)
{
    var claimIdentity = new ClaimsIdentity(n.AuthenticationTicket.Identity);
    // Custom code...
    claimIdentity.Claims.Append(new Claim("TEST","1234"));
    n.OwinContext.Authentication.SignIn(claimIdentity);
    return Task.FromResult(0);
}

Another option make the assignment directly, not working for me:

private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> n)
{
    var claimsPrincipal = new ClaimsPrincipal(n.AuthenticationTicket.Identity);
    // Custom code...
    // TEST:
    n.OwinContext.Response.Context.Authentication.User = claimsPrincipal;
    n.OwinContext.Request.User = claimsPrincipal;
    n.OwinContext.Authentication.User = claimsPrincipal;
    return Task.FromResult(0);
}
mainmind83
  • 491
  • 4
  • 7