How to expire the login info

I’m used the CredentialsAuthProvider method to login in, I want to close the browser, the user info logout or expired. how to set ?

        Plugins.Add(new AuthFeature(() => new CustomUserSession(),
          new IAuthProvider[]
          {
              new BasicAuthProvider(AppSettings) {PersistSession = true},    //Sign-in with Basic Auth
              new CredentialsAuthProvider(AppSettings) {SkipPasswordVerificationForInProcessRequests = true,  PersistSession =true},

The CredentialsAuthProvider is an auth service, using it with a browser is one option, but it isn’t inherently tied to a browser, be it open or closed. You would have to manage that behavior yourself. Eg, by using something like Window.close() with whatever logic you think is right for your use case. If you are trying to force a logout, you will need to get your client (browser) to call the /auth/logout endpoint as well to ensure the use is logged out.

thanks, If I set SessionExpiry , It will expired 10 seconds later even if busy, But I want a setting like the session IdleTimeOut, how to set the idletimeout in authprovider?

        Plugins.Add(new AuthFeature(() => new CustomUserSession(),
          new IAuthProvider[]
          {
              new BasicAuthProvider(AppSettings) {PersistSession = true},    //Sign-in with Basic Auth
              new CredentialsAuthProvider(AppSettings) {SkipPasswordVerificationForInProcessRequests = true,  PersistSession =true,   SessionExpiry = TimeSpan.FromSeconds(10)},
        services.AddSession(options =>
        {
            // Set a short timeout for easy testing.
            options.IdleTimeout = TimeSpan.FromMinutes(20); 
            options.Cookie.HttpOnly = true;
        });

Ahh, I think what you might be describing is a Sliding Session?

Our docs have the following implementation you can use for your services in a response filter attribute:

public class SlidingSessionAttribute : ResponseFilterAsyncAttribute
{
    public TimeSpan? Expiry { get; set; }

	public SlidingSessionAttribute(int expirySecs=0)
	{
		this.Expiry = expirySecs <= 0
            ? (TimeSpan?)null 
            : TimeSpan.FromSeconds(expirySecs);
	}

    public override async Task ExecuteAsync(IRequest req, IResponse res, object response)
    {
        var session = await req.GetSessionAsync();
        if (session != null) 
            await req.SaveSessionAsync(session, this.Expiry);
    }
}

By resaving the session, we can update it with the new expiring to the configured ICacheClient, eg Redis/InMemory/etc.

Hope that helps!

I have copy the code , but

        Plugins.Add(new SessionFeature()
        {
            SessionExpiry = TimeSpan.FromSeconds(10),
            PermanentSessionExpiry = TimeSpan.FromSeconds(10),
        });
public class SlidingSessionAttribute : ResponseFilterAsyncAttribute
{
    public TimeSpan? Expiry { get; set; }

    public SlidingSessionAttribute(int expirySecs = 0)
    {
        this.Expiry = expirySecs <= 0
            ? (TimeSpan?)null
            : TimeSpan.FromSeconds(expirySecs);
    }
    static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); 
    public override async Task ExecuteAsync(IRequest req, IResponse res, object response)
    {
        var session = await req.GetSessionAsync();
        logger.Info($"session:{session?.SerializeToString()}");
        if (session != null)
        {
            logger.Info($"req.SaveSessionAsync(session):{session.SerializeToString()}");
            await req.SaveSessionAsync(session, this.Expiry);
        }
    }
}
[Authenticate]
[SlidingSession(10 * 60)] //= 10 minutes
public class GYService : AppService
{
    public string Any(IsValidOAUser request)
    {
        var zggh = request.ZGGH;
        var password = request.PASSWORD;
        var md5Password = "";
     
        var bExist = md5Password.IsNullOrEmpty()
            ? Db_WEIXIN.Exists<OA_RSGL_ZGDA>(p => p.ZGGH == zggh && (p.DLKL == null))
            : Db_WEIXIN.Exists<OA_RSGL_ZGDA>(p => p.ZGGH == zggh
                                                                    && (p.DLKL == md5Password));

        return bExist.ToString();
    }
}
        GlobalResponseFiltersAsync.Add(async (req, res, dto) =>
        {
            var session = await req.GetSessionAsync();
            logger.Info($"session:{session?.SerializeToString()}");
            if (session != null)
            {
                logger.Info($"req.SaveSessionAsync(session):{session.SerializeToString()}");
                await req.SaveSessionAsync(session, TimeSpan.FromSeconds(10));
            }
        });

in HomeController called this function, not invoke SlidingSession or GlobalResponseFilters, will expired in 10 seconds. Is there any setting is wrong?

        var helloRequest = new IsValidOAUser { ZGGH = "123" };
        var response = Gateway.Send(helloRequest);
        var httpReq = base.Request.ToRequest();
        var sessionKey = SessionFeature.GetSessionKey(httpReq.GetSessionId());
        var session = await httpReq.GetCacheClientAsync().GetAsync<IAuthSession>(sessionKey);

By HomeController I assume you mean a separate MVC controller you have setup? The response filter attribute will only be activated here when the user is interacting with services in your GYService class since that is what it is applied to. The use of GlobalResponseFiltersAsync will be applied to all Servicestack services. How are you declaring your HomeController? Are to using a ServiceStackController as a base class shown in the example in the documentation?

If you can provide a way for me to reproduce the issue in a GitHub repository, I can take a closer look.

the below code is interacting with services ‘GYService’ , right? but the response filter attribute not activated.

   var helloRequest = new IsValidOAUser { ZGGH = "123" };
        var response = Gateway.Send(helloRequest);

the HomeController is derived from ServiceStackController

public class HomeController : MpController
{
    public async Task<IActionResult> Index()
    {
        var isLogin = ZGGH.NotNullOrEmpty();
        ViewData["isLogin"] = isLogin;
        ViewBag.isDemo = g.IsDemo;
 
        HttpContext.Session.SetString("JWToken", "xxxxxxx");
        CookieHelper.WriteCookie("Name", "wenzhili");

        var helloRequest = new IsValidOAUser { ZGGH = "123" };
        var response = Gateway.Send(helloRequest);
        var httpReq = base.Request.ToRequest();
        var sessionKey = SessionFeature.GetSessionKey(httpReq.GetSessionId());
        var session = await httpReq.GetCacheClientAsync().GetAsync<IAuthSession>(sessionKey);
        
        ViewData["session"] = session;
        ViewData["response"] = response;
        return View();
     }
}
public class MpController : ServiceStackController<CustomUserSession>
{
}

Calling a service like from the server side will not fire a request/response filter as these are Internal Requests. Your GlobalResponseFilter should be firing since your Controller is inheriting from the ServiceStackController, however, since it is a response filter, it will only fire on the way out, so your ViewData will not be updated in that way, but the following response should reflect that your session expiry is sliding from the previous request.

I founded I changed the code like below, not Internal Requests, GlobalResponseFilter works. but I want only user view the page can extend the user session expire time, not to call other external request, is there any way?

    var request = new Hello { Name = "abc" };
    var client = new JsonServiceClient("http://localhost:5001/");
    var response = client.Send<HelloResponse>(request);

This shouldn’t be required if users are hitting your controller when they view a page for example. If you can produce a minimal reproduction of what you have and share it on GitHub, I can take a look.

Thanks, I had found that can extend the session timeout in the controller dispose.

public class MpController : ServiceStackController<CustomUserSession>
{
 protected async override void Dispose(bool disposing)
 {
     base.Dispose(disposing);
     if (Request.ToRequest().IsPermanentSession().Not())  
         await SaveSessionAsync(userSession, TimeSpan.FromMinutes(30));  
 }
}