1
votes

I have an existing MVC5 application I am converting from using AspNetIdentity to utilize ThinkTecture Identity Server 3 v2. The OpenID provider is not the biggest issue I'm having, as it seems to be working great. The security token is validated and I'm handling the SecurityTokenValidated notification in a method in order to get additional user info claims and add system-specific permission claims to the claim set, similar to the code below:

OWIN Middleware

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "https://localhost:44300/identity",
    Caption = "My Application",
    ClientId = "implicitclient",
    ClientSecret = Convert.ToBase64String(SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes("secret"))),
    RedirectUri = "http://localhost:8080/",
    ResponseType = "id_token token",
    Scope = "openid profile email roles",
    SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
    UseTokenLifetime = false,
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        SecurityTokenValidated = ClaimsTransformer.GenerateUserIdentityAsync
    }
});

Claims Transformer

public static async Task GenerateUserIdentityAsync(SecurityTokenValidatedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
{
    var identityUser = new ClaimsIdentity(
        notification.AuthenticationTicket.Identity.Claims,
        notification.AuthenticationTicket.Identity.AuthenticationType,
        ClaimTypes.Name,
        ClaimTypes.Role);

    var userInfoClient = new UserInfoClient(new Uri(notification.Options.Authority + "/connect/userinfo"),
        notification.ProtocolMessage.AccessToken);

    var userInfo = await userInfoClient.GetAsync();
    identityUser.AddClaims(userInfo.Claims.Select(t => new Claim(t.Item1, t.Item2)));

    var userName = identityUser.FindFirst("preferred_username").Value;
    var user = MembershipProxy.GetUser(userName);
    var userId = user.PersonID;
    identityUser.AddClaim(new Claim(ClaimTypes.Name, userId.ToString(), ClaimValueTypes.Integer));

    // Populate additional claims

    notification.AuthenticationTicket = new AuthenticationTicket(identityUser, notification.AuthenticationTicket.Properties);
}

The problem is that the ClaimsIdentity assigned to the authentication ticket at the end of the transformer is never populated in the System.Web pipeline. When the request arrives to my controller during OnAuthenticationChallenge, I inspect the User property to find an anonymous WindowsPrincipal with a similar WindowsIdentity instance assigned to the Identity property, as if the web config's system.web/authentication/@mode attribute were set to None (at least I believe that's the behavior for that mode).

What might cause a failure by the middleware to set the principal for the user, or for it to be replaced during System.Web's processing with an anonymous Windows identity? I haven't been able to track this down.

EDIT: This occurs irrespective of whether the SecurityTokenValidated notification is handled and claims augmented.

EDIT 2: The cause appears to be making use of ASP.NET State Service session state server in my web.config with cookies. The configuration entry is:

<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" timeout="30" cookieless="UseCookies" />

This looks to be related to a reported issue in Microsoft.Owin.Host.SystemWeb #197 where cookies are not persisted from the OWIN request context into the System.Web pipeline. There are an assortment of workarounds suggested but I'd like someone to authoritatively point me to a properly vetted solution for this problem.

2
hi, were you able to resolve this problem? I'm having similar one in web forms app and still unable to find any resolution. ThanksAntonin Jelinek

2 Answers

0
votes

If you were to capture a fiddler trace, do you see the any .AspNet.Cookies. I suspect the cookies are not being written. You can use a distributed cache and do away with cookies.

0
votes

I think you need to include cookie authentication middleware because .AspNet.Cookies thing is written by that middleware. This is how you can integrate that middleware

app.UseCookieAuthentication(new CookieAuthenticationOptions());

Note: Please make sure it should be on top of openid connect middleware

for more details about CookieAuthenticationOptions please goto this link https://msdn.microsoft.com/en-us/library/microsoft.owin.security.cookies.cookieauthenticationoptions(v=vs.113).aspx.