How to keep user logged in when using OpenID Connect & Cookies in dotnet core

authenticationcookiesoauth2openid

I'm working on an OpenID Connect Hybrid flow, basically the response type in my case is: code id_token
Problem: I can't seem to persist the session of the user when logged in using the id_token.

I built the app using .Net Core's built in OpenID Connect authentication handler and Cookies handler.
However, the cookies are session cookies, so they expire the moment the browser is closed, in which case the user is logged out and has to login again when he opens the browser.
Which got me thinking, that I haven't been using refresh tokens even though I've been asking for them from the Authorization server.
So, the question to rule them all: How do I persist the user's login on the browser so he will have to login just once? I realize Cookies should have an expiry date and not be regular session cookies and I also realize that I should be using refresh tokens to re-authenticate the user again behind the scenes and thus produce a new cookie in the process. However, Is my thinking right? If yes, how to do that ? If not, what did I get wrong?

Update: I solved the problem of the session cookie expiring but adding an "IsPersistent" property in the authentication challenge I used to login, and the OpenID Connect authentication handler took care of the rest. However, the Cookie only lasts 60 mintues, which is the duration of the id_token. So, we still have the problem of not being able to ask for a new token using the refresh token?!

Best Answer

I did this myself recently and it's a bit of a pain, largely due to the limitations on the extension method setup methods which restrict your control over the component, forcing you to use CookieAuth when you don't really want to.

What I setup was Cookie, JWT and OpenIdConnect authentication. in the cookie auth we forward events to the JWT or OpenId auth

.AddCookie(options =>
{
    options.ForwardAuthenticate = JwtBearerDefaults.AuthenticationScheme;
    options.ForwardChallenge = OpenIdConnectDefaults.AuthenticationScheme;
    options.Events = new CookieAuthenticationEvents()
    {
        OnRedirectToAccessDenied = async ctx =>
        {
            ctx.Response.StatusCode = 401;
        },
    };

})

In the JWT auth we check our own cookie:

options.Events = new JwtBearerEvents()
{
    OnMessageReceived = async ctx =>
    {
        //get the token from the cookie rather than the header
        var token = ctx.HttpContext.Request.Cookies["access_token"];
        ctx.Token = token;
    },
};

In the OpenId auth we set the cookie

ctx.Response.Cookies.Append("access_token", tokenResponse.AccessToken);
Related Topic