Setting up a ForgeRock Access Manager instance for production may be a cumbersome task as instructions to harden the instance for production may be located all over the documentation.

This post aims to consolidate all the hardening recommendations with more detailed steps and short video guides to achieve them. Ultimately, being the go to reference for how to harden an AM instance.

Note that this post will include some of the recommendations on both ForgeRock documentation and from our own experience. We will be using the latest version of AM as of this post, 6.5.2.3.

If you are here just for the checklist, you can download it by clicking here.


1. Do Not Use /am Or /openam As Deployment Path

IMPORTANCE: BASELINE

Because this is a well-known path for AM, it will be easy for malicious hackers to crawl a domain for it. During installation, rename the war file to a path where it does not seem like ForgeRock AM.

Rename the war file to something that is not obvious.

2. Use Delegated Admin Users Rather Than The Default amadmin Super Admin User

IMPORTANCE: BASELINE

It is insecure to continue to use amadmin user to configure AM as there will not be accountability. This will guide you through the creation of users and groups with privileges similar to amadmin user.

  1. Create the user if they do not already exist:
    Navigate to: Realms > [Realm Name] > Identities, click Add Identity and enter details for the user
  2. Create a new group to represent this type of admin user:
    Navigate to: Realms > [Realm Name] > Identities > Groups, click Add Group and enter an ID for the group
  3. Add your admin user to this new group:
    Navigate to: Realms > [Realm Name] > Identities > Groups > [Group Name] and add the user you selected/created in step 1 as a member
  4. Give this group the required privileges:
    Navigate to: Realms > [Realm Name] > Identities > Groups > [Group Name] > Privileges and enable the required privileges. For full read and write access (including via the REST API), enable Realm Admin
  5. The new admin user now has access according to the privileges assigned to them. If you gave them full read and write access, they have full read and write access to the console

3. Changing The Password Of amadmin To A Strong One

IMPORTANCE: RECOMMENDED

Since amadmin is a default super admin username on all AM instances that can and should not be disabled, it is almost mandatory to set a very strong password.

Although recommended to already have initially set a strong password during initial setup, if you did not, here are the steps to change it later on

  1. Log in as amadmin user
  2. Navigate to: User avatar image (top right of XUI) > Change Password.
  3. Enter your old password
  4. Enter your desired new password twice
  5. Click Save to update the password

4. Restrict goto And gotoOnFail URL

IMPORTANCE: BASELINE

By default, AM redirects the user to the URL specified in the goto and gotoOnFail query string parameters supplied to the authentication interface in the login URL likely to aid in development.

To increase security against possible phishing attacks through open redirect, you can specify a list of valid URL resources against which AM validates these URLs. AM only redirects a user if the goto and gotoOnFail URL matches any of the resources specified in this setting. If no setting is present, it is assumed that the goto or gotoOnFail URL is valid.

When setting valid goto URLs, you can use the "*" wildcard, where "*" matches all characters except "?"

4.1. Global level

  1. Navigate to: Configure > Global Services > Validation Service
  2. Add the valid goto URL resources to whitelist

4.2. Realm level

  1. Navigate to: Realms > [Realm Name] > Services
  2. Add a service
  3. Select Validation Service
  4. Add one or more valid goto URLs
  5. Click Create.

5. Set Higher Maximum File Descriptors And Process Per User To Prevent Denial Of Service

IMPORTANCE: BASELINE

By default, the values set are too low to handle high number of connections by ForgeRock AM, it is required to set this to a higher value (recommendation of 65536)
Assuming a Linux system:

  1. su to the user where AM is installed under
su - ${AM_USERNAME}
  1. Change the file descriptor limit to 65536
ulimit -n 65536
  1. To make this persist across reboots you should run this command to these two lines to /etc/sysctl.conf as root
cat >> /etc/sysctl.conf <<- EOF
fs.file-max=65536
fs.inotify.max_user_watches=524288
EOF

6. Disable The AM API Explorer

IMPORTANCE: OPTIONAL

You may want to disable the API explorer meant to help development to create ambiguity. Especially if it was set to dynamic before.

  1. Navigate to: Configure > Global Services > REST APIs
  2. Select Disabled in the API Descriptors drop-down list.

7. Disable Module-Based Authentication

IMPORTANCE: BASELINE

Module-based authentication lets users authenticate using specific chain modules with the module=module-name parameter which is only to aid development and must not be enabled in production.

  1. Navigate to:  Realms > [Realm Name] > Authentication > Settings > Security
  2. Clear the Module Based Authentication check box

8. Lock All Authentication To Resources To Use Specific Authentication Service

IMPORTANCE: BASELINE

By default, AM allows the user to choose their authentication service with the service=service-name parameter, this is also only to aid development and must not be enabled in production. You should set specific authentication tree/chain per realm.

  1. Navigate to: Authorization -> Policy Sets -> [Your Policy Set] -> [Your Policy] -> Environments
  2. Click on Add an Environment Condition
  3. Select Authentication by Service for the type
  4. Key in /[Realm of Tree]:[Tree Name] to enforce which tree from a realm that the user have to have authenticated against first before being able to access the resource
  5. Ensure all Policy Sets and Policies has this strictly set properly

IMPORTANCE: BASELINE

The default settings for cookies has the name set to iPlanetDirectoryPro. If malicious hackers are able to perform Cross-site scripting (XSS) attacks, they can easily look for that specific cookie name to steal the session data.

Assuming you have not set per server settings:

  1. Navigate to: Configure -> Server Defaults -> Security -> Cookie -> Cookie Name
  2. Change it to your specified value

10. Enable Unique SSO Token and Secure Cookies

IMPORTANCE: BASELINE

Configuring secure cookies with cookie hijacking protection for CDSSO is recommended, so messages for federated configurations perform signing and encryption as necessary, and AM accesses providers securely (for example using LDAP + StartTLS, or LDAPS to access directory services).

  1. Navigate to: Configure -> Server Defaults -> Advanced
  2. Set com.sun.identity.enableUniqueSSOTokenCookie to true

10.2. Enable Secure Cookies

  1. Ensure HTTPS is set up correctly as secure cookies only work with HTTPS
  2. Navigate to: Configure -> Server Defaults -> Security -> Cookie -> Secure Cookie
  3. Set it to true

IMPORTANCE: RECOMMENDED

You should also set specific cookie domain fully qualified domain name (FQDN) to the only ones you would access AM with so the cookie cannot be accepted on non-whitelisted domains.

  1. Navigate to: Configure -> Global Services -> Platform -> Cookie Domain
  2. Add domains as needed to the text field, press enter on every domain

12. Disable And Restrict Caching Entirely

IMPORTANCE: OPTIONAL

Note that this will cause the XUI to load slower for users as it will be requested from the server everytime.

Global

On the servlet application used, set the headers for all path:

Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0

JSON endpoints

Set Cache-Control: private on all endpoints that contain /json/ in their path on the servlet application except for the following:

/serverinfo/*
/serverinfo/version
/serverinfo/cookieDomains

13. Enable HTTP Strict-Transport-Security (HSTS)

IMPORTANCE: RECOMMENDED

HTTP Strict-Transport-Security header helps to protect websites against man-in-the-middle attacks by enforcing only HTTPS connection

HSTS Policy specifies a period of time during which the user agent should only access the server in a secure fashion. Websites using HSTS often do not accept clear text HTTP.

  1. Ensure HTTPS is set up correctly
  2. Uncompress AM WAR file
  3. Navigate to: [Uncompressed AM WAR folder] -> WEB-INF -> web.xml
  4. Search for <!-- filter declaration -->
  5. Add this before that line:
<filter>
    <filter-name>EnableHSTS</filter-name>
    <filter-class>org.forgerock.openam.headers.SetHeadersFilter</filter-class>
    <async-supported>true</async-supported>
    <init-param>
        <param-name>Strict-Transport-Security</param-name>
        <param-value>max-age=31536000; includeSubDomains; preload</param-value>
    </init-param>
</filter>
  1. Search for <!-- filter mapping -->
  2. Add this before that line:
<filter-mapping>
    <filter-name>EnableHSTS</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
  1. Navigate back to [Uncompressed AM WAR folder] and run jar -cvf * [Desired name of output WAR file] to compress the folder back to a WAR file
  2. Place the updated WAR file back to the servlet application server deployment folder

14. Set X-Frame-Options To SAMEORIGIN

IMPORTANCE: RECOMMENDED

The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe>, <embed> or <object>. Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites. Consequently, user-agent not capable of doing TLS will not be able to connect to the site, however this issue is almost non-existent at this point.

  1. Ensure HTTPS is set up correctly
  2. Uncompress AM WAR file
  3. Navigate to: [Uncompressed AM WAR folder] -> WEB-INF -> web.xml
  4. Search for <!-- filter declaration -->
  5. Add this before that line:
<filter>
    <filter-name>SetXFrameOptions</filter-name>
    <filter-class>org.forgerock.openam.headers.SetHeadersFilter</filter-class>
    <async-supported>true</async-supported>
    <init-param>
        <param-name>X-Frame-Options</param-name>
        <param-value>sameorigin</param-value>
    </init-param>
</filter>
  1. Search for <!-- filter mapping -->
  2. Add this before that line:
<filter-mapping>
    <filter-name>SetXFrameOptions</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
  1. Navigate back to [Uncompressed AM WAR folder] and run jar -cvf * [Desired name of output WAR file] to compress the folder back to a WAR file
  2. Place the updated WAR file back to the web application deployment folder

15. Turn On HTTP-Only Cookies

IMPORTANCE: BASELINE

This will disallow JavaScript to manipulate or retrieve the cookie and will help prevent cross-site scripting (XSS) attacks.

  1. Navigate to Configure -> Server Defaults -> Advanced
  2. Set com.sun.identity.cookie.httponly property value to true.
  3. Save

16. Make Sure HTTPS Connections Are Set Up

IMPORTANCE: BASELINE

This can be done either on the servlet application server or the reverse proxy that points to your AM instance.

Since configuring these is out of this post's scope, we will not be covering it here.

17. Ensure Firewall Is Set Up

IMPORTANCE: BASELINE

Ensure unused ports are properly protected by the firewall. Using a hardware firewall is recommended, but software firewall like UFW and firewall-cmd is also good to have.

You can deploy a reverse proxy within demilitarized zone (DMZ) firewalls to limit exposure of service URLs to the end user as well as block access to back end configuration and user data stores to unauthorized users.

18. Use Reverse Proxy To Proxy AM

IMPORTANCE: BASELINE

After securing the server using a firewall, you could use a whitelist system and only whitelist the reverse proxy to connect with the AM port. This will allow more configuration for requests that comes in. Configuring HTTPS and certificates are easier too.

You have wide range of choices like ForgeRock Identity Gateway, Apache HTTPD, HAProxy, Nginx and many others.

Since configuring these is out of this post's scope, we will not be covering it here.

19. Specify An Appropriate TLS Protocol For Communication With LDAP

IMPORTANCE: RECOMMENDED

It is generally recommended to enforce TLS1.2 for communication.

Between AM and one or more of the following:

  • An external AM configuration store
  • An external CTS token store
  • An external user store
  • An Active Directory repository used for AM authentication with the Active Directory module
  • An LDAP repository used for AM authentication with the LDAP module
  • A repository used for AM certificate authentication with the certificate module

To enforce the TLS protocol for AM connections with LDAP, use the -Dorg.forgerock.openam.ldap.secure.protocol.version JVM setting.

20. Ensure That Authentication Inner Trees Are Unable To Authenticate Users On It's Own

IMPORTANCE: OPTIONAL

If not restricted, users can select the authentication trees they want to use by using the service=service-name parameter. However, if already restricted, this is optional. It is recommended to restrict than just rely on this alone.

Ensure that inner trees do not take in both username and password together will aid to not allow users to use only inner trees to authenticate.

21. Separate Administrative Access From Client Access

IMPORTANCE: BASELINE

Create realms for the organization(s) and separate administrative users from end users.

  1. Create Realm for organisation
  2. To direct relevant users to the correct realms in AM you can use either:
  • Use the realm=realm-name query string parameter
  • Specify FQDN DNS aliases for the realms

22. Bind To LDAP Using Specific Administrative Accounts Rather Than A Root DN (i.e. CN=Directory Manager)

IMPORTANCE: BASELINE

Example configuration using specific LDAP administrative accounts per store

It is not a good idea to bind using the root DN as essentially the account has read/write privileges on the entire LDAP. You should create specific administrative accounts per different base DN and use those instead. This will be covered in the Directory Services post in the future and set up using profiles.

23. Replace All Test Keys In Keystore With Your Own Keys

IMPORTANCE: BASELINE

The default keystore that AM uses is located at [AM Config Directory]/openam/keystore.jceks. It includes several test keys that are pre-generated and should not to be used in production.

You should add in your own keys either by a keystore explorer application or keytool CLI and change the reference in AM admin console to point to your key alias.

The store password is a hidden file located at [AM Config Directory]/openam/.storepass which is randomly generated during setup. The password for the keys in the store is always changeit and if changed, you should change it in [AM Config Directory]/openam/.keypass too.

  1. Navigate to: Configure -> Secret Stores -> default-keystore -> Mappings
  2. Change all the aliases to your own keys' aliases

Settings That Should Not Be Changed

1. Do not enable allow encoded slash

Ensure the servlet application server configuration do not allow encoded slash in the application URL. It should be disabled by default in Tomcat and JBOSS.

2. Content Security Policy can not be hardened

XUI will break as it relies heavily on in-line scripts. Unless you are planning to use a completely customized UI, this can not be hardened although it helps protects against XSS attacks.

3. Do not disable Cross-Site Request Forgery (CSRF) Protection

AM includes a global filter to harden AM's protection against CSRF attacks. The filter applies to all REST endpoints under json/ and requires that all requests other than GET, HEAD, or OPTIONS include, at least, one of the following headers:

  • X-Requested-With This header is often sent by JavaScript frameworks, and the XUI already sends it on all requests.
  • Accept-API-Version This header specifies which version of the REST API to use. Use this header in your requests to ensure future changes to the API do not affect your clients.
  1. Navigate to: Configure -> Global Services -> REST APIs
  2. Ensure Enable CSRF Protection is turned on

The list of hardening recommendations can be non-exhaustive, but we have provided the few most important ones that we have come across.

We have consolidated all of this post into a checklist that you can download, print and use for your own deployments, you can download it by clicking here.

We hope that this post was able to help you determine and perform security hardening on your AM instances more efficiently.

Disclaimer

The document and content made available by Nebulas Tree in no way conveys any right, title, interest or license in any intellectual property rights (including but not limited to patents, copyrights, trade secrets or trademarks) contained herein. Nebulas Tree reserves the right to vary the terms of the document and content in response to changes to the specifications or information made available to Nebulas Tree.

Nebulas Tree does not assume liability for any errors or omissions in the content of this document or any referenced or associated third party document, including, but not limited to, typographical errors, inaccuracies or outdated information.  This document and all information within it are provided on an "as is" basis without any warranties of any kind, express or implied.  Any communication required or permitted in terms of this document shall be valid and effective only if submitted in writing. Reliance of any information provided herein this document is solely at your own risk.