Scenario
Many websites need to have private single page, a private bunch of pages or all private pages where private means accessible after authorization.
Authorization means allow a user to do something based on its identity (credentials or token).
Authentication is the process of verifying user identity, usually based on login with credentials (user+password) from a login page the first access and login with token further times.
CUGs
CUGs are an AEM feature for OOTB authorization implementation on dispatchers/publish instances (mainly allowing the visualization of pages).
CUGs DO NOT implements authentication.
Requirements to start:
- define protected paths: /content/mysite/protected-area/
- define which users and/or groups can access the protected area (ex. b2b-user)
- define a login page: /content/mysite/login-page.html (outside the protected paths).
The authentication logic inside the login page is out of CUGs’ scope
This is the schema in which only publish instance is involved in authorization, so the pages cannot be cached at dispatcher level.
Authorization settings on AEM Publish
These are the page properties to be configured on /content/mysite/protected-area page.
Enable CUGs and set login page:
These are the correspondent properties on /content/mysite/protected-area node:
Set the user/group enable for CUGs:
These are the correspondent properties on /content/mysite/protected-area/rep:cugPolicy node:
Shortening issue
When the following shortening is applied
mydomain/content/mysite/protected-area/ –> mydomain/protected-area/
CUGs don’t work well with sling mapping (/etc/map)
- probably due a bug (tested on AEM 6.5.8)
- Redirect to login page always lands to /
Proposed solution is to use URL Mappings field in Apache Resource Resolver Factory config
High Level Schema: dispatcher caching
This is the schema of how caching is implemented on dispatcher side.
Authorization is cheked also on dispatcher, allowing to have there cached contents served only after the verification that a user session is already present on dispatcher.
User Not Logged use case
This is the flow of a user not yet logged-in
Authorization on dispatcher fails.
Authorization on publish instance fails and the user is redirected to the login page
First access after login use case
This is the flow of a user that is already logged-in and requests the first page.
Authorization on dispatcher fails.
Authorization on publish instance succeeds because the token stored in the cookie is verified, the page is served from publish instance and a user session is created on dispatcher.
Further accesses after login use case
This is the flow of a user that is already logged-in and requests other pages.
Authorization on dispatcher succeeds because the user session already exists there, the page is served from dispatcher.
Authorization settings on dispatcher
On the dispatcher configuration side, a separate protected farm is required,
Here are the following.
/myprotectedfarm {
...
/virtualhosts {
"mydomain/content/mysite/*"
}
...
/cache {
/allowAuthorized "0"
...
}
...
/sessionmanagement
{
/directory "/home/sessions"
/encode "md5"
/header "Cookie:b2b-login-token"
/timeout "800"
}
....
}
This image shows the cookie in the browser
On the dispatcher OS in the session path directories and empty files are created
The file name is the MD5 of session cookie value in case that encoding is chosen.
B2b-token-login from cookie –> MD5 –> user session on dispatcher (2C280AD8A6914CAC0AEDED228128938E)
Performance possible issue
Adobe disclaimer says:
Closed user groups (CUGs) should always be created with performance in mind.
Although the number of users and groups in a CUG is not limited, a high number of CUGs on a page may slow down rendering performance.
The impact of CUGs should always be considered when doing performance testing.
For sure, the critical step in the process is the first page request after login.
To create a user session in the dispatcher, CUGs flow needs to request the page on publish instance even if a copy is already cached in the dispatcher.
This means that first access after each login bypasses the dispatcher cache and the page is served directly from publish instance.
This can be a problem is the traffic is really high and the user navigation is extremely short with lots of user the often perform logins.
This issue can be resolved integrating a CDN.
CUGs and CDN
Using Content Delivery Networks and CUGs together is possible.
On CDN a simple custom logic must be developed (ex Lamba@Edge Functions in AWS) calling a Permission Sensitive Cache Servlet on AEM.
The HEAD request contains the login-token used on AEM to identify the user
AEM can respond with HTTP RESPONSE CODE:
- 200: CDN can serve its cached content
- 401: CDN request the content to dispatcher
ACS Commons provides an OTTB Permission Sensitive Cache Servlet
References
- https://experienceleague.adobe.com/docs/experience-manager-65/administering/security/cug.html?lang=en
- https://joao.ws/aem-aws-cloudfront-cdn-and-closed-user-groups-cugs/
- https://helpx.adobe.com/experience-manager/kb/PSCachingDelivery.html
- https://experienceleague.adobe.com/docs/experience-manager-dispatcher/using/configuring/permissions-cache.html?lang=en
- https://adobe-consulting-services.github.io/acs-aem-commons/features/utils-and-apis/permission-sensitive-cache/index.html
Written by Aldo Caruso