Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.
SOLVED

CSRF token.json Request Keeps Session Alive

Avatar

Level 2

I am setting the session timeout to 15 minutes (via the Apache Felix Jetty Based Http Service configuration).  However, the call to /libs/granite/csrf/token.json every 5 minutes seems to be keeping it active.  Should I adjust how often token.json is called?

1 Accepted Solution

Avatar

Correct answer by
Level 2

I've come a long way in understanding session management in AEM since my post so I'll share what I learned. I should have stated this in my first post, that our requirement is to be able to set a session idle timeout (the user lets their browser sit for X minutes and then they are logged out) and a session max age timeout (even if the user is active, they will be logged out).


First of all, the "Apache Felix Jetty Based Http Service" settings for Session Timeout and Session Max Age apply only to the java session (JSESSIONID), not to anything related to AEM login/logout.

 

AEM maintains a user's login/logout status in the "login-token" cookie. It is configured in the OSGi setting "Apache Jackrabbit Oak TokenConfiguration." Here you can set the token expiration. With "Token Refresh" enabled, the token expiration time is extended with each click. In this case, the expiration time acts as an idle timeout. With "Token Refresh" disabled, the token expiration time is not extended as the user clicks through the site. In this case, the expiration time acts as max session/max age timeout. It is not possible to set both an idle timeout and max timeout.

 

To further complicate things, there are two issues with token refresh. (https://helpx.adobe.com/experience-manager/kb/login-session-refresh-not-working.html)
#1: If "Enable encapsulated token support" is enabled on "Adobe Granite Token Authentication Handler," the token refresh does not work. If you are using multiple publish servers and do not have sticky sessions enabled, you probably have encapsulated tokens enabled.
#2: Even with encapsulated tokens disabled, the login token for AEM doesn't get refreshed if they don't click during the 2nd half of half of the timeout.  So for a 15 minute token expiration, they can be clicking along during the first 7.5 minutes.  If they let it sit for the next 7.5 minutes, it will timeout after 15 minutes from their initial login, not 15 minutes from their last click (say 20 minutes). I understand it's done for performance reasons (I think because the token is stored in the repository and you want to avoid reading that with every click). However, you never can guarantee when the session expires. I would think most customers have a requirement for a fixed amount of time.

 

At the end of it, we built a custom solution for timeout. This seems like a very basic requirement especially since these options are available in the "Apache Felix Jetty Based Http Service" for JSESSIONID. As such, I have asked Adobe for the following features:
1. Support both idle timeout AND max age/timeout. Currently only 1 can be enforced by toggling the token refresh setting. The "Apache Felix Jetty Based Http Service" supports both, so I think the login token should also.
2. Token refresh support for encapsulated tokens.
3. A reliable way to guarantee token expiration when it's refreshed. I understand the 50% rule is for performance reasons, but I would think most customers would want a specific idle timeout.

 

Finally, getting back to my original question, the call to /libs/granite/csrf/token.json does *not* refresh the AEM session because it is specifically excluded in the "Adobe Granite Token Authentication Handler" configuration. Adobe recommends against it, but should you need to update the interval that token.json is called, it is hard-coded in /libs/clientlibs/granite/jquery/granite/csrf/source/csrf.js under:
    setInterval(function() {
        getToken();
    }, 300000);

View solution in original post

3 Replies

Avatar

Employee Advisor

You can configure CSRF token validation using a osgi property at [1]. It can give you the expiration time with csrf.token.expires.in property.

 

[1] - com.adobe.granite.csrf.impl.CSRFServlet

Avatar

Level 2

I think that sets the expiration of the token within the response of the call to /libs/granite/csrf/token.json.  For example: {"token":"jsueUWBDOjE2NzgzODYyOTMsImlhdCI6MTY38DE34TY5M30.jdEhcW3JBPvdCyDOxfFM938EucIvIhKNF6VkeHmP5g"}

 

I don't think it's related to session or login token expiration.

Avatar

Correct answer by
Level 2

I've come a long way in understanding session management in AEM since my post so I'll share what I learned. I should have stated this in my first post, that our requirement is to be able to set a session idle timeout (the user lets their browser sit for X minutes and then they are logged out) and a session max age timeout (even if the user is active, they will be logged out).


First of all, the "Apache Felix Jetty Based Http Service" settings for Session Timeout and Session Max Age apply only to the java session (JSESSIONID), not to anything related to AEM login/logout.

 

AEM maintains a user's login/logout status in the "login-token" cookie. It is configured in the OSGi setting "Apache Jackrabbit Oak TokenConfiguration." Here you can set the token expiration. With "Token Refresh" enabled, the token expiration time is extended with each click. In this case, the expiration time acts as an idle timeout. With "Token Refresh" disabled, the token expiration time is not extended as the user clicks through the site. In this case, the expiration time acts as max session/max age timeout. It is not possible to set both an idle timeout and max timeout.

 

To further complicate things, there are two issues with token refresh. (https://helpx.adobe.com/experience-manager/kb/login-session-refresh-not-working.html)
#1: If "Enable encapsulated token support" is enabled on "Adobe Granite Token Authentication Handler," the token refresh does not work. If you are using multiple publish servers and do not have sticky sessions enabled, you probably have encapsulated tokens enabled.
#2: Even with encapsulated tokens disabled, the login token for AEM doesn't get refreshed if they don't click during the 2nd half of half of the timeout.  So for a 15 minute token expiration, they can be clicking along during the first 7.5 minutes.  If they let it sit for the next 7.5 minutes, it will timeout after 15 minutes from their initial login, not 15 minutes from their last click (say 20 minutes). I understand it's done for performance reasons (I think because the token is stored in the repository and you want to avoid reading that with every click). However, you never can guarantee when the session expires. I would think most customers have a requirement for a fixed amount of time.

 

At the end of it, we built a custom solution for timeout. This seems like a very basic requirement especially since these options are available in the "Apache Felix Jetty Based Http Service" for JSESSIONID. As such, I have asked Adobe for the following features:
1. Support both idle timeout AND max age/timeout. Currently only 1 can be enforced by toggling the token refresh setting. The "Apache Felix Jetty Based Http Service" supports both, so I think the login token should also.
2. Token refresh support for encapsulated tokens.
3. A reliable way to guarantee token expiration when it's refreshed. I understand the 50% rule is for performance reasons, but I would think most customers would want a specific idle timeout.

 

Finally, getting back to my original question, the call to /libs/granite/csrf/token.json does *not* refresh the AEM session because it is specifically excluded in the "Adobe Granite Token Authentication Handler" configuration. Adobe recommends against it, but should you need to update the interval that token.json is called, it is hard-coded in /libs/clientlibs/granite/jquery/granite/csrf/source/csrf.js under:
    setInterval(function() {
        getToken();
    }, 300000);