Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Core cookie authentication with AWS Lambda not persisting

Tags:

I am unable to get cookie authentication working with an AWS Lambda function using .NET Core 2.1 MVC.

I have tried lots of variations of the cookie options. I am able to login and see the asp cookie being created in the response, but I am returned to the login screen usually after I refresh or click on any link, e.g. the next request to the server. *Update: It seems I have it in a state where I only have to login twice initially now and it stays logged in. This is also the second Lambda function using .net 2.1 where I've noticed this behavior.

I have API gateway configured with the defaults that get set up when deploying using the AWS extension for visual studio.

My current startup.cs code, which works on localhost:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        // Cookie settings
        options.Cookie.SameSite = SameSiteMode.Lax;
        options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
        options.LoginPath = "/Login";
        options.LogoutPath = "/Logout";
        options.AccessDeniedPath = "/Login";
        options.Cookie.Name = "myapp.auth";
        options.Cookie.HttpOnly = true;
        options.Cookie.Expiration = TimeSpan.FromDays(1);
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings, only this changes expiration
        options.SlidingExpiration = true;
        options.ExpireTimeSpan = TimeSpan.FromDays(1);
    });
services.AddAntiforgery(options => { options.Cookie.Expiration = TimeSpan.Zero; });

and

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseAuthentication();

    app.UseMvc();
}

I've tried using the following when logging in as well:

    await HttpContext.SignInAsync(principal, new AuthenticationProperties
    {
        ExpiresUtc = DateTime.UtcNow.AddHours(12),
        IsPersistent = true
    });

Simply using the following will keep me logged in, but I have to log in twice before the cookie persists (once more after clicking on anything and being redirected to login again):

await HttpContext.SignInAsync(principal);
like image 922
user1854458 Avatar asked Apr 28 '19 02:04

user1854458


1 Answers

@Alex Nazarevych's answer is correct in that you need to set up Data Protection storage. However, the linked article describes how to store the Data Protection keys in the AWS Systems Manager Parameter Store, not the file system. And it makes sense, since the Lambda function will continuously exit and lose its file storage.

I use the AWS Parameter store on my own website, and it works perfectly well. Here's what you need to do:

  1. Add a NuGet package reference to Amazon.AspNetCore.DataProtection.SSM to your project.
  2. In your Startup.ConfigureServices method, add the following code. You can change the "/DataProtection" to whatever you like; this just defines what your key names will start with in the Parameter Store:
services.AddDataProtection()
   .PersistKeysToAWSSystemsManager("/DataProtection");
  1. Make sure that your Lambda function has the AddTagsToResource, PutParameter, and GetParametersByPath permissions to the AWS Parameter Store. As an IAM Policy, it would look like the following. Note that if you used something other than "/DataProtection" in the code above, then you need to change the resource in the policy below to match. (And don't forget the asterisk at the end.)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ssm:AddTagsToResource",
                "ssm:GetParametersByPath",
                "ssm:PutParameter"
            ],
            "Resource": "arn:aws:ssm:*:*:parameter/DataProtection*",
            "Effect": "Allow"
        }
    ]
}

After the code has run once, you can use the AWS Console to view the keys yourself. Just log into the AWS Console and navigate to the Systems Manager Parameter Store.

like image 152
JamesQMurphy Avatar answered Oct 12 '22 03:10

JamesQMurphy