locked
Session Timeout with AJAX redirects to login page only a partial view/Component RRS feed

  • Question

  • User1426684119 posted

    I need a session timeout for an asp net core website. The intention is, after X minuts without any user's action, when the user would makes some action that requires a request, the website will redirect the request to Login Page. As I've read in other posts, I create, in the ConfigureServices function in startup.cs this portion of code:

             services.AddSession(options =>
            {
                options.Cookie.Name = "_aspnetCoreSession";
                options.IdleTimeout = TimeSpan.FromMinutes(30);
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
            });
    

    In the same file (startup.cs) in the function Configure:

            app.UseSession();
            app.Use(async (context, next) =>
            {
                string CurrentUserIDSession = context.Session.GetString("token");
                if (!context.Request.Path.Value.Contains("/Index") && !context.Request.Path.Value.EndsWith("/"))
                {
                    if (string.IsNullOrEmpty(CurrentUserIDSession))
                    {
                        var path = "/Index";
                        context.Response.Redirect(path);
                        return;
                    }
                }
                await next();
            });
    

    This works fine unless in the AJAX calls. In the AJAX calls, the request only modifies one component and the Login Page is loaded inside this component. I use AJAX calls to modify one component but when the session is timeout, the Login page is loaded inside the component when the AJAX call is executed. You can see this in the following picture.

    enter image description here

    I understand that the request only modifies the component. My question is if exists some other instruction similar to context.Response.Redirect(path) in server side (as you can see in the second portion of code, I use it in Configure function in Startup.cs) that lets me submit all the page or, if it's not possible, if exists some similar alternative that works when using AJAX calls for timeouts?

    Thursday, April 8, 2021 12:04 PM

All replies

  • User-474980206 posted

    the modern approach is to use jwt tickets for ajax calls, but you can use cookie. on the server use middleware to detect that the request is an ajax call (either use a header, or /api path) and that authentication redirected to the login page:

      public class AjaxApiMiddleware
        {
            private readonly RequestDelegate _next;
    
            public AjaxApiMiddleware(RequestDelegate next)
            {
                _next = next;
            }
    
            public async Task InvokeAsync(HttpContext context)
            {
    
                await this._next(context);
    
                var isJson = context.Request.Headers["Accept"].Any(a => a.Contains("json"));
                var isApipath = context.Request.Path.Value.ToLower().StartsWith("/api/");
                var isLoginRedirect = context.Response.Headers["location"].Any(l => l.ToLower().StartsWith(MyLoginUrl));
    
                if (context.Response.StatusCode == 302 && isLoginRedirect && (isApipath || isJson))
                {
                    context.Response.StatusCode = 401; //UnAuthorized
                    await context.Response.WriteAsync("access denied - ajax call");
                    return;
                }
               
            }
        }

    Thursday, April 8, 2021 3:14 PM
  • User1686398519 posted

    Hi negu, 

    What are you using for authentication?

    Are you using Identity?

    1. In this case, you can configure application cookies in Startup.ConfigureServices.
    2. services.ConfigureApplicationCookie(options =>
      {
      ... ... options.ExpireTimeSpan = TimeSpan.FromMinutes(60); options.LoginPath = "/Identity/Account/Login";
      ... ... });

    Here are some links that can help you.

    1. Cookie settings
    2. Introduction to Identity on ASP.NET Core

    Best Regards,

    YihuiSun

    Monday, April 12, 2021 6:28 AM
  • User1426684119 posted

    Hello bruce, thank's for your answer.

    I understand the idea (now, I'm using a middelware to intercept the requests and redirects to Login page if the sesión is timed out) but I don't know how to redirect if is an AJAX request without the same problem that I have now, because I understand that I will have the problem that the redirection only will update the component updated in the request (not all the page).

    Monday, April 12, 2021 1:25 PM
  • User475983607 posted

    Your client code will look for the 401 and redirect.   Can you explain or show code that illustrates the problem?

    Monday, April 12, 2021 1:33 PM
  • User1426684119 posted

    Hello YihuiSun,

    Now I will do the authentication through an API. The API uses de Active Directory to check the credentials. If the authentication is ok, I use Microsoft.AspNetCore.Session 

    services.AddSession(options =>
    {
    	options.Cookie.Name = "_aspnetCoreSession";
            options.IdleTimeout = TimeSpan.FromMinutes(1);
            options.Cookie.HttpOnly = true;
            options.Cookie.IsEssential = true;                
    });

    Do you know if there is a similar option to use in sessions?
     

    Monday, April 12, 2021 1:37 PM
  • User-474980206 posted

    session is just a cache tied to a cookie. if the cookie expires, the session can not be accessed, and the server just creates a new one. if the session data is not recoverable, then you should store it in a database.

    Monday, April 12, 2021 6:39 PM
  • User475983607 posted

    negu

    Do you know if there is a similar option to use in sessions?

    The AJAX application is responsible for redirecting to the login page.  Your middleware needs to return something to the AJAX application to let the AJAX function know the request was not authorized.  Typically, that's a 401 which was illustrated above.

    You can use Session but you need to design and write logic.  Your first code sample returns a redirect.  The AJAX method follows the redirect which results in /Index.  So your AJAX function needs to check if /Index was returned.  if so, the request was not authorized.  From there do a window.location = "/Index" or whatever the login is.

    Or are you using Windows authentication and need to re-populate Session?

    Monday, April 12, 2021 7:48 PM
  • User1426684119 posted

    Hello mgebhard, I'm using Windows authentication through an API and yes, I need to re-populate Session.

    The AJAX application is responsible for redirecting to the login page.  Your middleware needs to return something to the AJAX application to let the AJAX function know the request was not authorized.  Typically, that's a 401 which was illustrated above.

    Thank you. With this explanation, I understand a little bit more the code above. 

    You can use Session but you need to design and write logic.  Your first code sample returns a redirect.  The AJAX method follows the redirect which results in /Index.  So your AJAX function needs to check if /Index was returned.  if so, the request was not authorized.  From there do a window.location = "/Index" or whatever the login is.

    Thank you for this solution. I was searching for a solution that not involves client side for security, but if it is not posible, I will develope the client side solution that you gives me.

    Thank you all for your replies and sorry if I didn't understand some of them.

    Tuesday, April 13, 2021 8:52 AM
  • User475983607 posted

    I'm using Windows authentication through an API and yes, I need to re-populate Session.

    Windows authentication does not use a login page.  The login is automatic when using a compatible browser like IE.  Chrome, for example, will prompt the user for Windows credentials.

     It is not clear how Session is populated or why you are unable to repopulate Session since the user is always known.  

    Tuesday, April 13, 2021 10:40 AM
  • User1426684119 posted

    True, I'm using System.DirectoryServices.AccountManagement with PrincipalContext class to validate credentials with Active Directory.

    Tuesday, April 13, 2021 12:40 PM
  • User475983607 posted

    negu

    True, I'm using System.DirectoryServices.AccountManagement with PrincipalContext class to validate credentials with Active Directory.

    I do not understand the design. 

    If you wrote code that forces the user to enter credentials and authenticate, then it is also up to you to write code that detects when the user's authentication has expired.  As explained above, this is typically handled using the built-in cookie authentication library or the built-in JWT (Bearer token) library.  Using the built-in libraries gives access to the built-in authorization libraries like the [Authorize] attribute.  I recommend using the built-in tools/libraries.

    If you must continue with Session then it is up to you to write custom authorization code.  just like the example code above, you'll want to write middleware code that detects an empty Session and return a 401 to the AJAX caller.  Your AJAX application will detect the 401 and redirect. 

    Keep in mind, this problem has been solved many times over and the code shown above is a very good template.  You'll have to make modifications to suite your custom needs.

    Tuesday, April 13, 2021 1:06 PM