Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

Get User from SlingHttpServletRequest -> ResourceResolver -> Session in Servlet

Avatar

Level 3

Hi there community,

 

I am looking to get the current logged in user from the SlingHttpServletRequest.  I am using a POST servlet that extends the SlingAllMethodsServlet.

 

I can confirm that the login-token cookie is being sent with the request:

String tokenCookie = TokenCookie.fromRequest(request).toString();

The tokenCookie string is populated with the correct login-token value. I have tried both GET and POST requests, and the cookie value is always correct.  And, if I push that cookie into a browser and visit /crx/de I see the respective user logged in.

 

I have tried using the trusty resourceResolver adapted to a session to get the user:

final ResourceResolver resolver = request.getResourceResolver();
final Session session = resolver.adaptTo(Session.class);
final String username = session.getUserID();

This always returns anonymous

 

I have tried using the request attribute:

String userSessionName = (String)request.getAttribute("org.osgi.service.http.authentication.remote.user");

This always returns anonymous

 

I have tried using the request principal

Principal principal = request.getUserPrincipal();
String principalName = principal.getName();

This always returns anonymous

 

I did try using a service user session, as some have suggested, but as I expected that approach returns the service user rather than the actual request user.

 

What am I missing? I have been scratching my head all day on this issue, and I hope I am just missing something simple.


Thanks in advance

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hi @jarvislukow 

 

You are doing it correct. I don't see any issue with the code and the same code even I tried to use and it works perfectly fine for me.

 

@Component(service = Servlet.class, property = {"process.label=Test Servlet",
Constants.SERVICE_DESCRIPTION + "=" + "This Servlet is responsible for getting User Id",
ServletResolverConstants.SLING_SERVLET_PATHS + "=" + HttpConstants.METHOD_GET,
ServletResolverConstants.SLING_SERVLET_PATHS + "=/bin/getuser"})
public class TestServlet extends SlingSafeMethodsServlet {

private static final long serialVersionUID = 1L;

private static final Logger log = LoggerFactory.getLogger(TestServlet.class);

@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
log.info("***** :: doGet :: Start :: *****");

String tokenValue = TokenCookie.fromRequest(request).toString();
log.info("Token Value --> {}", tokenValue);

ResourceResolver resourceResolver = request.getResourceResolver();
Session session = resourceResolver.adaptTo(Session.class);
String userID = session.getUserID();
log.info("User Id from Session --> {}", userID);

String userFromRequestAttr = (String) request.getAttribute(HttpContext.REMOTE_USER);
log.info("User Id from Request Attribute --> {}", userFromRequestAttr);

Principal userPrincipal = request.getUserPrincipal();
String principalName = userPrincipal.getName();
log.info("User Id from User Principal --> {}", principalName);

log.info("***** :: doGet :: End :: *****");
}
}

 

This is what I see in the log:

 

20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet ***** :: doGet :: Start :: *****
20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet Token Value --> 34f0ab69-2f2e-4db4-99ae-6c99ca725a64%3a9bffb662-e7e2-49c3-b16a-17639e6efecd_ea05f9202272a988fb0b2f1a9db07e6c%3acrx.default%3b7adb6be4-c538-4689-ab8f-236ddd613c5e%3abecbf06b-212b-4924-aa7b-967473d84dad_a0e48ed735c2c4d839ba9e3101678478%3acrx.default
20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet User Id from Session --> user-one
20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet User Id from Request Attribute --> user-one
20.11.2021 19:35:43.384 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet User Id from User Principal --> user-one
20.11.2021 19:35:43.384 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet ***** :: doGet :: End :: ***** 

 

 

Make sure when this code is executed, the user is always logged in and an anonymous user is not making this request.

View solution in original post

7 Replies

Avatar

Correct answer by
Community Advisor

Hi @jarvislukow 

 

You are doing it correct. I don't see any issue with the code and the same code even I tried to use and it works perfectly fine for me.

 

@Component(service = Servlet.class, property = {"process.label=Test Servlet",
Constants.SERVICE_DESCRIPTION + "=" + "This Servlet is responsible for getting User Id",
ServletResolverConstants.SLING_SERVLET_PATHS + "=" + HttpConstants.METHOD_GET,
ServletResolverConstants.SLING_SERVLET_PATHS + "=/bin/getuser"})
public class TestServlet extends SlingSafeMethodsServlet {

private static final long serialVersionUID = 1L;

private static final Logger log = LoggerFactory.getLogger(TestServlet.class);

@Override
protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
log.info("***** :: doGet :: Start :: *****");

String tokenValue = TokenCookie.fromRequest(request).toString();
log.info("Token Value --> {}", tokenValue);

ResourceResolver resourceResolver = request.getResourceResolver();
Session session = resourceResolver.adaptTo(Session.class);
String userID = session.getUserID();
log.info("User Id from Session --> {}", userID);

String userFromRequestAttr = (String) request.getAttribute(HttpContext.REMOTE_USER);
log.info("User Id from Request Attribute --> {}", userFromRequestAttr);

Principal userPrincipal = request.getUserPrincipal();
String principalName = userPrincipal.getName();
log.info("User Id from User Principal --> {}", principalName);

log.info("***** :: doGet :: End :: *****");
}
}

 

This is what I see in the log:

 

20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet ***** :: doGet :: Start :: *****
20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet Token Value --> 34f0ab69-2f2e-4db4-99ae-6c99ca725a64%3a9bffb662-e7e2-49c3-b16a-17639e6efecd_ea05f9202272a988fb0b2f1a9db07e6c%3acrx.default%3b7adb6be4-c538-4689-ab8f-236ddd613c5e%3abecbf06b-212b-4924-aa7b-967473d84dad_a0e48ed735c2c4d839ba9e3101678478%3acrx.default
20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet User Id from Session --> user-one
20.11.2021 19:35:43.383 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet User Id from Request Attribute --> user-one
20.11.2021 19:35:43.384 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet User Id from User Principal --> user-one
20.11.2021 19:35:43.384 *INFO* [[0:0:0:0:0:0:0:1] [1637417143382] GET /bin/getuser HTTP/1.1] com.test.core.servlet.TestServlet ***** :: doGet :: End :: ***** 

 

 

Make sure when this code is executed, the user is always logged in and an anonymous user is not making this request.

Avatar

Level 3

@Asutosh_Jena_ Thanks for validating this for me.  I thought I was doing this right

Something must be interfering with the request processing flow.  I'll keep looking and update the thread once I find the resolution.

Avatar

Community Advisor

Hi @jarvislukow 

 

Are you trying in author or publish? Here is the difference it makes

In author instance: Request is always made via the user who is logged in (ex: admin)

In publish instance: Request is always made via anonymous user (This could be the reason that you are facing the issue)

 

You are sending the token from request but its not necessary that the session created in your servlet using request is being created by the same user. Try in author instance once to validate.

 

Thanks,

Kiran Vedantam.

Avatar

Level 3

@Kiran_Vedantam Thanks for your reply.

Correct me if I am wrong, but if a request is made to AEM and it contains a valid login-token, won't the authentication hander log the respective user into that AEM instance?  

I can confirm that this behaviour is currently happening - if I add a valid login-token cookie in to the browser and visit /crx/de on author or publish the user is logged in.

However, in the servlet the session does not contain the logged in (authenticated) user based on the cookie.  I assume the auth mechanism is happening after my servlet is invoked?

Avatar

Level 3

Yes - this servlet would be invoked after the user has been logged in.

Avatar

Level 3

Just incase anyone else stubbles upon this in the future, I would like to add that this issue is caused by allowing the "authorization" header in the dispatcher to pass through to the publish server.  When the authorization header is passed, it will take priority over the login-token when the authentication mechanism kicks in.

In my case, I am using the authorization header to pass a JWT token for some requests, but when the token wasn't being included the authorization header resolved to user that didn't exist and therefore was anonymous