The Adobe Experience Manager as a Cloud Service (AEM) GraphQL API for Content Fragment Delivery serves as a crucial solution for accepting external queries from third-party applications or services. The main objective is to enable secure headless content delivery by facilitating authenticated API access for remote queries.
This can be achieved by using Access Tokens for accessing GraphQL end-points.
Scenarios:
There are various scenarios for accessing an application:
- Consistent access setup: This involves a configuration where permissions remain relatively stable and do not change frequently.
- Dynamic access setup: In this scenario, authors have the ability to control access to specific folders. This approach is commonly implemented in conjunction with Closed User Groups (CUG) to provide granular access control.
In the following sections, we will explore both approaches. While the majority of the steps remain the same, there are some variations. For the “Consistent Access Set up,” you can bypass the “Setting up CUG” section and proceed directly to the “Generate Service Credentials” step.
1. Setting up CUG for access restrictions
CUG (Closed User Group) and permission-sensitive caching are essential features in Adobe Experience Manager (AEM) for enhancing content security and optimizing performance. CUG allows business-administrators to define access restrictions, ensuring that only authorized users can view and interact with specific content. Permission-sensitive caching leverages this information to intelligently cache and deliver content based on user permissions, resulting in faster page rendering and reduced server load. By combining CUG and permission-sensitive caching, AEM provides a robust solution that enhances content security while optimizing performance for authenticated users.
To configure such an area within your website you:
- Create closed user group and assign members.
- Apply this group to the required asset folders
- Bypass CDN caching for secured content
- Configure the Dispatcher for:
- CUG
- permission sensitive caching
- Use access token to access the restricted content
Using CUG to access secured content via GraphQL
When using GraphQL queries with Adobe Experience Manager (AEM), it is important to note that GraphQL respects the Closed User Group (CUG) setup. This means that even though the GraphQL endpoint may be accessible, only the content accessible to the user will be served.
In the case of an app-specific technical account user, whose token has been passed in the request, GraphQL queries will only retrieve and serve the content that the user has authorization to access. This ensures that content security and access restrictions set up through CUG are enforced, providing a secure and controlled environment for fetching data via GraphQL in AEM.
2. Generate Service Credentials
“Service Credentials” in AEM as a Cloud Service provide secure authentication for external systems or integrations to access AEM’s APIs and services, enabling controlled and fine-grained access control while protecting sensitive data and maintaining accountability. Service Credentials generation is broken into two steps:
- A one-time Technical Account creation by an Adobe IMS Org administrator
- The download and use of the Technical Account’s Service Credentials JSON
Note: For each external application, it is necessary to create a corresponding service user. These service users can be considered as a one-to-one mapping for each Closed User Group (CUG). This means that each CUG will have a dedicated service user associated with it.
2.1. Create a Technical Account
Service Credentials require a Technical Account to be created by an Adobe Org IMS Administrator before they can be downloaded. Discrete Technical Accounts should be created for each client that requires programmatic access to AEM.s IMS Product Profile on AEM Author.
For details on generating and downloading credentials, refer to “Fetch the AEM as a Cloud Service Credentials“
3. Configure access in AEM
In order to provide access to the service user that was created in the previous step, it is essential to assign them to a designated group. If you want to delegate permission control for external agencies to business administrators, you can utilize a Closed User Group (CUG). To grant access to the service user, follow the steps outlined below:
3.1. Create application specific user-groups
To ensure efficient management of access to AEM assets, application-specific groups should be pre-created. These groups should be utilized for granting access to AEM assets.
3.2. Assign technical users to app-specific groups
Once the technical account AEM user exists in AEM (after first HTTP request with the access token), this AEM user’s permissions can be managed the same as other AEM users.

- First, locate the technical account’s AEM login name by opening the Service Credentials JSON downloaded from AEM Developer Console, and locate the integration.email value, which should look similar to: 12345678-abcd-9000-efgh-0987654321c@techacct.adobe.com.
- Log in to the corresponding AEM environment’s Author service as an AEM Administrator
- Navigate to Tools > Security > Users
- Locate the AEM user with the Login Name identified in Step 1, and open its Properties
- Navigate to the Groups tab, and add the user to corresponding application-specific group (whom as read access to assets)
- Tap Save and Close
4. Use Service Credentials to generate access tokens
To gain access to restricted resources in AEM, it is necessary to transmit the retrieved Access Token as a bearer token to AEM. This token will grant the corresponding service user access to resources in line with the access permissions configured for that user.
Service Credentials, which consist of a fully structured JSON object, can be employed to generate Access tokens. For a detailed breakdown of the steps involved, visit link .
4.1. Generate acess token via AEM-CS API Client Library
This repository contains code that can be used to exchange AEM-CS API Integration JSON for Access Tokens with IMS. It covers steps 4-6 from section 3.1. The output would look like this:
>> post /ims/exchange/jwt
<< post /ims/exchange/jwt 200
{
"token_type": "bearer",
"access_token": "eyJ4-REDACTED-F4MAA",
"expires_in": 86399999
}
4.2 Generate access token via Java code
The code sample that would help you generate access tokens is avilable on link
The expiration information provided in the output (while generating access token) can be leveraged by the consuming application to cache and reuse the same token. This approach eliminates the need to generate a fresh token for each request, enhancing efficiency and reducing unnecessary token generation
5. Bypass CDN cache for secured content
By default, all content in AEM is cached on the CDN. However, the CDN is not aware of authorization, which can pose security risks. To address this, it is necessary to disable caching in the CDN.
Note: In Section 6, “Enable Permission-Sensitive Caching,” we will explore how to configure the AEM Dispatcher to selectively cache secure content. This configuration ensures that content requiring authorization is not cached on the CDN, maintaining the appropriate level of security for sensitive assets.
- Default caching setting can be disabled by defining the DISABLE_DEFAULT_CACHING variable in global.vars:
Define DISABLE_DEFAULT_CACHING
Note: This can be useful, for example, when your business logic requires fine tuning of the age header (with a value based on calendar day) since by default the age header is set to 0. That said, please exercise caution when turning off default caching.
- To prevent specific content from being cached at the CDN, set the Cache-Control header to private. For example, the following would prevent assets content under a directory named secure from being cached at the CDN:
# No cache on CDN for GraphQL queries serving securing content
<LocationMatch "^/graphql/execute.json/.*">
Header unset Cache-Control
Header unset Expires
Header always set Cache-Control "private"
</LocationMatch>
6. Configure dispatcher for CUG
To permit the caching of authenticated documents, set the /allowAuthorized property under the /cache section to /allowAuthorized 1. See Caching When Authentication is Used for more details.
7. Enable permission sensitive caching
To implement permission-sensitive caching, perform the following tasks:
- Develop an Auth Checker servlet that performs authentication and authorization
- Configure dispatcher to enable permission sensitive caching on GraphQL endpoint. Example:
/auth_checker {
# request is sent to this URL with '?uri=<page>' appended
/url "/bin/permissioncheck"
# only the requested pages matching the filter section below are checked, all other pages get delivered unchecked
/filter {
/0000 {
/glob "*"
/type "deny"
}
/0001 {
/glob "/graphql/execute.json/wknd-shared/adventure-by-path;adventurePath=/content/dam/secure/*"
/type "allow"
}
}
# any header line returned from the auth_checker's HEAD request matching the section below will be returned as well
/headers {
/0000 {
/glob "*"
/type "deny"
}
/0001 {
/glob "Set-Cookie:*"
/type "allow"
}
}
}
For details refer to link
7. Optimizing Multi-Site Tenant Configuration for GraphQL Caching with CUG
When dealing with cached content that remains consistent across various third-party applications with valid tokens, you can efficiently use the same GraphQL endpoint along with an authentication checker for caching JSON on the dispatcher. This is feasible because the GraphQL results and consequently the cached content remain the same.
However, in scenarios where the cached content varies among different third-party applications following authentication, potentially due to Customer Groups (CUG), it’s recommended to explore the implementation of a multi-tenant setup for GraphQL endpoints. Alternatively, consider utilizing different endpoints for distinct applications. This strategic approach ensures that the cached results precisely align with the specific CUG requirements of each application.
Quick Notes:
When working with Closed User Groups (CUG) in Adobe Experience Manager (AEM), it is important to keep in mind the following considerations:
- CUG Groups Publishing: After deployment, ensure that the CUG groups created in the author environment are properly published to the publish environment. This step ensures that the necessary access restrictions are applied consistently across both environments.
- CUG Configuration Updates: When updating CUG configurations for a specific folder or content, remember to publish the affected folder or content. Publishing ensures that the changes in CUG settings take effect and are propagated correctly.
- CDN and Publicly Cached Content: If CUG is configured on content that was previously publicly available and has been cached on a Content Delivery Network (CDN), the content will continue to be served publicly by the CDN until its cache expires. It is important to factor in the cache expiry time when applying CUG to previously accessible content to ensure a smooth transition to restricted access.
By considering these points, you can effectively manage and implement Closed User Groups in AEM while ensuring consistent access restrictions and content availability across your environments.
3 thoughts on “Securing content for GraphQL queries via Closed user groups (CUG)”