Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenId Connect middleware not setting auth cookie in an WebForms app

I'm trying to integrate OpenId Connect into long-time existing webforms application. I was able to migrate the app to use OWIN and I'm using OpenIdConnectAuthenticationMiddleware to authenticate against my IdP provider. All goes fine until the point where I need to construct new identity obtained from IdP and set the cookie - which part I think is not happening.

Important parts of my Startup.Configure method:

app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/login.aspx"),
    CookieManager = new SystemWebCookieManager() //custom cookie manager
});


app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "https://[development_domain]/core",
    ClientId = "VDWeb",
    ResponseType = "code id_token token",
    Scope = "openid profile",
    UseTokenLifetime = true,
    SignInAsAuthenticationType = "Cookies",
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        SecurityTokenValidated = async n =>
        {
            var userInfo = await EndpointAndTokenHelper.CallUserInfoEndpoint(n.ProtocolMessage.AccessToken);

            //now store Preferred name :
            var prefNameClaim = new Claim(
                Thinktecture.IdentityModel.Client.JwtClaimTypes.PreferredUserName,
                userInfo.Value<string>("preferred_username"));

            var myIdentity = new ClaimsIdentity(
                n.AuthenticationTicket.Identity.AuthenticationType,
                Thinktecture.IdentityModel.Client.JwtClaimTypes.PreferredUserName,
                Thinktecture.IdentityModel.Client.JwtClaimTypes.Role);

            myIdentity.AddClaim(prefNameClaim);

            //add unique_user_key claim
            var subjectClaim = n.AuthenticationTicket.Identity.FindFirst(Thinktecture.IdentityModel.Client.JwtClaimTypes.Subject);

            myIdentity.AddClaim(new Claim("unique_user_key", subjectClaim.Value));
            myIdentity.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

            var ticket = new AuthenticationTicket(myIdentity, n.AuthenticationTicket.Properties);
            var currentUtc = new SystemClock().UtcNow;
            ticket.Properties.IssuedUtc = currentUtc;
            ticket.Properties.ExpiresUtc = currentUtc.Add(TimeSpan.FromHours(12));
            n.AuthenticationTicket = ticket;                
        },
    }
});

I can confirm AuthentocationTicket is populated properly but auth cookie is NOT set. I do know about this issue https://katanaproject.codeplex.com/workitem/197 and I have tried all workarounds offered for this issue but none helped. Interestingly enough, when I try to drop my own cookie inside of SecurityTokenValidated event - n.Response.Cookies.Append("Test", "Test");, I can see the cookie is set properly.

One of the workarounds suggest implementing your own CookieManager. What makes me curious is that when I put a breakpoint into cookie setter in this custom manager, it is not hit, i.e. middleware seems not even trying to set the cookie. So the main question I have - at what point exactly the middleware will try to set the cookie? Is it when I set my AuthenticationTicket?

Edit 1: adding more information. I tried to compare with another web app, this time MVC, that I configured to use the same IdP and that works as expected. Startup code for both apps is the same. When debugging thru SecurityTokenValidated event, I can see that MVC app (working) has created System.Security.Principal.WindowsPrincipal identity while webforms app (non-working) created System.Security.Principal.GenericIdentity identity.

I have also added this little snipped

app.UseStageMarker(PipelineStage.Authenticate);
app.Use((context, next) =>
{
    var identity = context.Request.User.Identity;
    return next.Invoke();
});

just to see what identity get populated on this pipeline stage. For MVC app (working) I see the identity I added by setting AuthenticationTicket, for webforms app I still see non-authenticated GenericIdentity.

like image 277
Antonin Jelinek Avatar asked Sep 26 '15 08:09

Antonin Jelinek


1 Answers

OK, this is embarrassing - the problem was in CookieAuthenticationOptions, apparently AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie is NOT the same as AuthenticationType = "Cookies". Once set this later way, it is working fine.

like image 178
Antonin Jelinek Avatar answered Nov 24 '22 03:11

Antonin Jelinek