Expand my Community achievements bar.

Adobe Summit 2025: AEM Session Recordings Are Live! Missed a session or want to revisit your favorites? Watch the latest recordings now.
SOLVED

AEM Authentication Details

Avatar

Level 8

Hello all,

 

1. How and where is AEM authenticated?

2. Also, when authenticated, how to pass user name and password? Obviously hard coding is not an option.

3. How is the session gotten with such authentication passed to other components?

4. If I am writing an AEM component, how will I know that AEM was already authenticated? How to get the session?

 

Appreciate all your replies.

 

Thanks,

RK.

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

1 Accepted Solution

Avatar

Correct answer by
Community Advisor

Hey,@nsvsrk great follow-up question and it's smart to break this down into the high-level flow before getting into the code. Here's how it works, step by step.

FYI: Username and password are never passed to AEM in a SAML flow — they go to the IDP.

SAML Setup via OSGi Configs
First, we configure the SAML Authentication Handler using AEM’s OSGi console. This includes:

  • IDP URL (e.g., Okta, Azure AD)

  • AEM SP entity ID

  • Assertion Consumer Service (ACS) path (e.g., /saml_login)

  • Attribute mapping (like email, uid, etc.)
    Once this is set, AEM will automatically redirect unauthenticated users to the configured IDP.

User Logs In
When an end user visits the portal (built on AEM), they're redirected to the IDP login page. The user enters their username and password on the IDP side not in AEM.

After a successful login, the IDP posts a signed SAML assertion to AEM, which then validates it and creates an authenticated session for the user.

So to clarify your point , AEM never receives the username or password directly. It only gets the identity via the assertion from the IDP.

ResourceResolver Usage Post Authentication
Once authentication is complete, AEM maintains the user session internally via session cookies. On every subsequent request, AEM ties the session to the appropriate user.

From that point on, any AEM component (Sling Model, Servlet, Filter, etc.) can access the authenticated user's session via:

request.getResourceResolver();

This is already tied to the user and doesn’t need to be explicitly created unless you’re in a background thread or doing system-level operations. So no, each component does not need to create a ResourceResolver from scratch. If you’re in the context of a request, use the one AEM already provides.
so overall you don’t need to share or reuse resolvers across components, use the one tied to the current request.

When and Where Should You Close the ResourceResolver?

This depends on how you obtained it:

  • If you created it manually using a service user:

  • try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(params)) {
        // use resolver
    }
    

     

  • Then yes, you should close it — and ideally within a try-with-resources block. 

  • If you got it from the request, like:

    request.getResourceResolver();
    
    Then no, do not close it. AEM handles it internally as part of the request lifecycle.
  • So the general rule is: only close resolvers that you explicitly open coz, Only manually created resolvers should be closed, and they should be scoped tightly to avoid leaks.


hope that helps 
Thanks

 

Partyush. 

View solution in original post

5 Replies

Avatar

Level 8

5. In Sling Models for populating Java variables with JCR values, they access JCR.

Which account is used for this? How this authentication takes place?

 

Thanks,

RK.

Avatar

Community Advisor

Hey @nsvsrk 
I’ve added answers I’d go with if I had the same questions — take a look below and let me know what you think!

 

How and where is AEM authenticated?

Answer: AEM authenticates users via the Sling Authentication Framework at the server level.

Where: Login happens at the AEM instance (e.g., /libs/granite/core/content/login.html) or Dispatcher/web server for SSO.
How: Username/password, SAML, or OAuth. Most common is SAML for enterprise setups.
Simple Setup: Use AEM’s default login or configure SAML in OSGi (/system/console/configMgr, search for “SAML Authentication Handler”).

How to pass username and password after authentication? (No hardcoding)

Answer: Don’t pass credentials directly. Use service users for backend access or OSGi configs for external APIs.
Service User:
  1. Create a service user in /useradmin (e.g., my-service-user).
  2. Map it in OSGi (/system/console/configMgr, “Apache Sling Service User Mapper”):
  3. my.bundle:service-id=my-service-user
  4. Get a ResourceResolver in code.
  5. @Reference
    ResourceResolverFactory resolverFactory;
    
    ResourceResolver getResolver() throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put(ResourceResolverFactory.SUBSERVICE, "service-id");
        return resolverFactory.getServiceResourceResolver(params);
    }
  6. External APIs: Store credentials in OSGi config (/apps/myapp/config)
  7. @Reference
    ConfigurationAdmin configAdmin;
    
    String getApiKey() throws IOException {
        Configuration config = configAdmin.getConfiguration("my.api.config");
        return (String) config.getProperties().get("api.key");
    }
How to pass the authenticated session to other components?
Answer: Pass the ResourceResolver (which holds the session) to other components.
From a Servlet
@SlingServlet(paths = "/bin/my/servlet")
public class MyServlet extends SlingSafeMethodsServlet {
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
        ResourceResolver resolver = request.getResourceResolver();
        MyComponent component = new MyComponent(resolver); // Pass it
    }
}
In the Component:
public class MyComponent {
    private final ResourceResolver resolver;

    public MyComponent(ResourceResolver resolver) {
        this.resolver = resolver;
    }

    public void doWork() {
        Resource resource = resolver.getResource("/content/my/path");
    }
}
Close Resolver: If you create a new resolver, close it.
try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(null)) {
    // Use resolver
}


How to know if AEM is authenticated in a component? How to get the session?

Check Authentication: Use ResourceResolver.getUserID()
public void checkAuth(SlingHttpServletRequest request) {
    ResourceResolver resolver = request.getResourceResolver();
    String userId = resolver.getUserID();
    if (userId == null || "anonymous".equals(userId)) {
        // Not authenticated
        throw new IllegalStateException("Not logged in");
    }
    // Authenticated as userId
}
Get Session: Adapt the ResourceResolver to a JCR Session
Session session = resolver.adaptTo(Session.class);
if (session.isLive()) {
    Node node = session.getNode("/content/my/path");
}

 

In Sling Models, which account is used for JCR access? How does authentication work?

Answer: Sling Models use the ResourceResolver’s account:

  • Request-Based: Uses the logged-in user’s ResourceResolver (from the HTTP request).
  • Service-Based: Uses a service user’s ResourceResolver.
    @nsvsrk This is simple sling  model for your reference. 
    @Model(adaptables = Resource.class)
    public class MyModel {
        @SlingObject
        private Resource resource;
    
        private String title;
    
        @PostConstruct
        protected void init() {
            title = resource.getValueMap().get("jcr:title", String.class);
        }
    
        public String getTitle() {
            return title;
        }
    }​
The resource’s ResourceResolver is tied to the request’s user (or anonymous for public pages).

@nsvsrkalso for your reference this is service User Model.

0

@Model(adaptables = Resource.class)
public class MyServiceModel {
    @OSGiService
    private ResourceResolverFactory resolverFactory;

    private String title;

    @PostConstruct
    protected void init() {
        try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(
                Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, "service-id"))) {
            Resource resource = resolver.getResource("/content/my/path");
            title = resource.getValueMap().get("jcr:title", String.class);
        } catch (Exception e) {
            // Handle error
        }
    }

    public String getTitle() {
        return title;
    }
}
 The my-service-user mapped in the Service User Mapper.

I hope this will clear your doubts and make things easy for you. 
Feel free to reply for any further query. 
 
Best,
Partyush
 

 

Avatar

Level 8

Thanks partyush for the very detailed description.

 

I am looking for high level chronological flow first and then detailed code snippets in Phase-2.

 

1. First step is to set up/config SAML based on OSGI configurations.

 

2. For example when someone logs into AEM instance using OOB interface, he/she enters user name/pwd and authentication happens on the basis of these values.

 

Let us say we are building a portal based on AEM.

When an end user opens the portal, he enters user name/pwd and authentication happens on the basis of these values.

Let us say authentication means is SAML.

Since SAML is based on OSGI configurations that we did earlier, authentication happens.

 

Henceforth ResourceResolver is gotten in code.

Where are we passing the user name/passwd that we collected first from the user?

 

So, every components needs to use the code described in your response code to get ResourceResolver ? (which is equivalent to a session/) and do operations programmatically.

 

So, It is not obtaining a session and sharing it across various components that need it!

 

3. Where in the code do we Close Resolver? In which method? (This should be executes only once in the end).

 

Thanks,

RK.

Avatar

Level 8

@partyush , Please confirm my understanding.

 

Thanks,

RK.

Avatar

Correct answer by
Community Advisor

Hey,@nsvsrk great follow-up question and it's smart to break this down into the high-level flow before getting into the code. Here's how it works, step by step.

FYI: Username and password are never passed to AEM in a SAML flow — they go to the IDP.

SAML Setup via OSGi Configs
First, we configure the SAML Authentication Handler using AEM’s OSGi console. This includes:

  • IDP URL (e.g., Okta, Azure AD)

  • AEM SP entity ID

  • Assertion Consumer Service (ACS) path (e.g., /saml_login)

  • Attribute mapping (like email, uid, etc.)
    Once this is set, AEM will automatically redirect unauthenticated users to the configured IDP.

User Logs In
When an end user visits the portal (built on AEM), they're redirected to the IDP login page. The user enters their username and password on the IDP side not in AEM.

After a successful login, the IDP posts a signed SAML assertion to AEM, which then validates it and creates an authenticated session for the user.

So to clarify your point , AEM never receives the username or password directly. It only gets the identity via the assertion from the IDP.

ResourceResolver Usage Post Authentication
Once authentication is complete, AEM maintains the user session internally via session cookies. On every subsequent request, AEM ties the session to the appropriate user.

From that point on, any AEM component (Sling Model, Servlet, Filter, etc.) can access the authenticated user's session via:

request.getResourceResolver();

This is already tied to the user and doesn’t need to be explicitly created unless you’re in a background thread or doing system-level operations. So no, each component does not need to create a ResourceResolver from scratch. If you’re in the context of a request, use the one AEM already provides.
so overall you don’t need to share or reuse resolvers across components, use the one tied to the current request.

When and Where Should You Close the ResourceResolver?

This depends on how you obtained it:

  • If you created it manually using a service user:

  • try (ResourceResolver resolver = resolverFactory.getServiceResourceResolver(params)) {
        // use resolver
    }
    

     

  • Then yes, you should close it — and ideally within a try-with-resources block. 

  • If you got it from the request, like:

    request.getResourceResolver();
    
    Then no, do not close it. AEM handles it internally as part of the request lifecycle.
  • So the general rule is: only close resolvers that you explicitly open coz, Only manually created resolvers should be closed, and they should be scoped tightly to avoid leaks.


hope that helps 
Thanks

 

Partyush.