skip to Main Content

I am playing around with aspnetboilerplate.com’s template for dotnet core. What I am trying to do is to deploy the template on a shared hosting (windows) server running Plesk (note, I have no control over the server at all).

The template works perfect locally, can log in, add users, roles, etc. Deploying it the shared hosting server gave some issues, but that was resolved relative quickly (configuring for dotnet core and had to drop to dotnet core 2.1 as 2.2 is not yet supported on the server).

The problem now is after logging in, within a minute I re-directed to the login page. I have had a similar problem with ASP.NET MVC5, but providing a Machine Key in the web.config and making use of a database for session data fixed that problem. So I am reasoning it is the same problem with the dotnet application.

But seeing as dotnet core does not use machine keys and DataProtectionApis a different approach is needed.

So I have tried adding services.AddDataProtection(); to StartUp.Configure()

I have read Distributed caching in ASP.NET Core and just about all the links coming off there as well as tried multiple code examples, but either I do not know what I am doing (high probability) or I am not doing something right.

So, how do I prevent the user being signed out unexpectedly using dotnet core 2.1 on a shared hosting server?

EDIT – 2019-01-25

Some new information: Tried setting timeouts as suggested, but this either does nothing or is not possible. For the dotnet application to run on Plesk, I had to disable ASP.NET support so that .NET core gets No Managed Code Application Pool. Trying to access ASP.Net settings on Plesk the (where you’d have access to Application Pool setting, etc) gives an error saying ‘ASP.NET support is switched off for this website’.

One thing that does not happen is the App_Data/Logs folder never gets created when publishing. I had to manually create and set permissions so that log4net can create a log file. The log file provided me with additional information:

ERROR 2019-01-25 09:33:03,005 [6    ] .Antiforgery.Internal.DefaultAntiforgery - An exception was thrown while deserializing the token.
Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The antiforgery token could not be decrypted. ---> System.Security.Cryptography.CryptographicException: The key {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} was not found in the key ring.

Searching for this error only once again lead me to documentation about adding services.AddDataProtection() to the ConfigureServices method, but this drones on about Azure Key Vaults (or other external providers) or writing info to a shared UNC so that other servers can access cached key info (and this is probably what I need). But seeing as all of these options are not available to me, I found an extension method which allows the key to be stored on an MSSQL server. Busy setting this up now to test.

If anybody wants to give their opinion, please be my guest.

UPDATE 2 – 2019-01-25 – SUCCESS (for now)

It would appear that making use of DataProtectionAPI is the way to go. Logs are not reporting any AntiforgeryValidationException, yet. I am going to let it run for a while and if all is good, I’ll post the solution and how it has been implemented.

3

Answers


  1. Chosen as BEST ANSWER

    The problem, it turns out was not the session expiring, but rather, when another server takes over the load of the my site, it has no session context. Data Protection services allows for the creation of a database to store session info in and it shared across servers in the farm. Similar to the session state attribute from web.config in MVC projects:

    <sessionState mode="SQLServer" sqlConnectionString="Data Source=000.000.000.000;Initial Catalog=session_db;User Id=user;Password=password;" allowCustomSqlDatabase="true" timeout="480" />
    

    This is how I solved the problem:

    Within ConfigureServices I added:

    services.AddDataProtection()
                .SetApplicationName("MyApplicationName")
                .SetDefaultKeyLifetime(TimeSpan.FromDays(14)) 
                .PersistKeysToSqlServer(_config["DataProtection:SqlServerConnectionString"]);
    

    I also had to create a separate database which is responsible for storing the session information. The DataProtextion:SqlServerConnectionString is an entry in the appsettings.json file:

    "DataProtection":
        {
            "SqlServerConnectionString": "Server=server; Database=database; User=user; Password=password;"
        }
    

    There are ways to probably solve this problem (eg with Redis), but seeing as I have no control over the server my site is hosted on, Data Protection services works just fine.


  2. Based off the information you provided above, I believe your session is timing out.

    When the session times out the user will be redirected to the login page to reauthenticate. I am not overly familiar with plesk but from very quick googling it seems that you should be able to increase the session timeout.

    Of course, if you are setting the sessiontimeout yourself in configurservices you could just adjust it there as well I would assume (again unfamiliar with the plesk setup fully).

    If you do that, the problem should resolve itself. Perhaps the session timeout is set to a short time period for testing?

    .net session state

    services.AddSession(options =>
            {
                // Set a short timeout for easy testing.
                options.IdleTimeout = TimeSpan.FromSeconds(10);
                options.Cookie.HttpOnly = true;
            });
    
    Login or Signup to reply.
  3. As PersistKeysToSqlServer is not supported in dot net core 3.1, we can use .PersistKeysToDbContext<AppDBContext>() or PersistKeysToFileSystem as it is shown here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search