Cookie Auth: Redirecting to a different subdomain (works, but seems nasty)

cjard

Well-known member
Joined
Jan 25, 2012
Messages
963
Programming Experience
10+
So, I've a laravel app, and I'm developing a companion C# app that sits at a different url. Lets say that I have laravel.myhost.com and csharp.myhost.com

Laravel generates the cookie and does all the login stuff, and I don't want to get into C# doing all that too, so I'm happy for now to leave the laravel app alone to do the login, set the cookie etc in the user browser, it works across subdomains already, browser submits to c# and so long as c# can decode the cookie and look the user session up in the DB it's happy days. It can do this

This part works, but I'm looking to handle the case that no cookie is submitted, the C# app should just redirect the user back to https://laravel.myhost.com.login

The cookie handler reg looks like this:

C#:
builder.Services
    .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddScheme<CookieAuthenticationOptions, LaravelCookieAuthenticationHandler>(
        CookieAuthenticationDefaults.AuthenticationScheme,
        options =>
        {
        }
    );

The cookie handler looks like this:

C#:
        protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
        {
            // Custom logic to decrypt and process the cookie
            var cookie = Request.Cookies["session_cookie"];

            if (cookie == default) return AuthenticateResult.Fail("The request does not include a valid session cookie");

            // Decode the cookie value
            var encryptedData = Encoding.UTF8.GetString(Convert.FromBase64String(cookie));

            var laravelAuth = JsonSerializer.Deserialize<LaravelCookie>(encryptedData);

            if (laravelAuth == default) return AuthenticateResult.Fail("Deserializing the session cookie failed. Ensure the base64'd JSON contains 'iv' and 'value' properties");
            ... blah ...

It's the first `if` that will kick out if no cookie is sent. If no cookie is sent then it fails, but then request go berserk in a redirect loop because the browser is redirected to https://csharp.myhost.com/?ReturnUrl=https://csharp.myhost.com/where_i_was_before. This invokes the cookie handler again, which fails again, which redirects to https://csharp.myhost.com/?ReturnUrl=https://csharp.myhost.com/?ReturnUrl=https://csharp.myhost.com/where_i_was_before - as you can see this url will get longer and longer after a few tens of redirects, it explodes with "414 URI too long"

Naturally, because C# doesn;t know to redirect to https://laravel.myhost.com/login, because I never told it

I tried several ways, for example:

C#:
builder.Services
    .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddScheme<CookieAuthenticationOptions, LaravelCookieAuthenticationHandler>(
        CookieAuthenticationDefaults.AuthenticationScheme,
        options =>
        {
            options.LoginPath = "https://..."; //blows up because this must only ever be a relative URI. All paths on the csharp app go through the cookie handler. I suppose I could configure one that doesn't, and then have that redirect.. But that seems like hoop jumping
         
        }
    );

C#:
builder.Services
    .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddScheme<CookieAuthenticationOptions, LaravelCookieAuthenticationHandler>(
        CookieAuthenticationDefaults.AuthenticationScheme,
        options =>
        {
            options.Events = new CookieAuthenticationEvents
            {
                OnRedirectToLogin = context =>
                {
                    context.RedirectUri = "https://laravel.myhost.com/login");   //this just causes c# to issue a 200 OK in response to a request with no cookie
                    return Task.CompletedTask;
                }
            };
        }
    );

Eventually I got it working with:


C#:
builder.Services
    .AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddScheme<CookieAuthenticationOptions, LaravelCookieAuthenticationHandler>(
        CookieAuthenticationDefaults.AuthenticationScheme,
        options =>
        {
            //options.LoginPath = "/woot";
            options.Events = new CookieAuthenticationEvents
            {
                OnRedirectToLogin = context =>
                {
                    context.Response.Redirect("https://laravel.myhost.com/login");
                    return Task.CompletedTask;
                }
            };
        }
    );

but this seems nasty.. Has anyone any comments on how this might be achieved in a more "in line with the spirit of setting options and letting c# send the response itself" way?[/icode]


I feel like this must be possible because I've plenty of apps written that redirect from myhost.com to someazuread.onmicrosoft.com etc but I;ve never dug into the low level request stream to find out what it does..
 
Last edited:
Just guessing here, but I think that the framework code assumes that it is self-contained when using cookie auth and so the ability to use a different provider is much harder to get to.
 
Back
Top Bottom