ForgeRock Identity Platform
ForgeRock Identity Cloud

FAQ: The AmService in IG routes

Last updated Jun 13, 2022

The purpose of this FAQ is to provide answers to commonly asked questions regarding the AmService in IG routes.

Frequently asked questions

Q. What is the purpose of the AmService?

A. The AmService holds information about the configuration of an instance of Identity Cloud or AM, and helps to support use-cases such as Single Sign On (SSO), Cross Domain SSO, Authorization and OAuth2 token validation. It also includes configuration items that deal with IG specific details, such as controlling how SSO token caching is managed and dealing with AM WebSocket notifications.

Q. How does the AmService communicate with Identity Cloud or AM?

A. By default, the AmService makes use of a handler called the ForgeRockClientHandler, which is itself defined by default within IG as a Chain with a single filter:

{  "name": "ForgeRockClientHandler",   "type": "Chain",   "config": {     "handler": "ClientHandler",     "filters": [ "TransactionIdOutboundFilter" ]   } }See ForgeRockClientHandler for further information.

Q. Is it better to have one shared AmService definition or one per route?

A. Every AmService that is defined in an IG configuration has a cost/overhead consideration when it is also making use of SSO token caching. Caches are not shared between the different AmService definitions, so if they make use of the same configuration, then there is a very high chance of caching duplicate SSO tokens, which could also result in higher memory usage. Having multiple AmService configurations is a valid use-case, for example, when some aspect of the configuration is different, like the realm.

By default, AmService enables a notification websocket connection to Identity Cloud or AM, one for each AmService. Notifications help keep the AmService cache consistent when the SSO token state changes outside of IG. For example, when a user's token expires on Identity Cloud or AM, the AmService cache entry should also be expired/removed. To support this, Identity Cloud or AM sends notification messages, via the websocket connection, to each AmService. The number of notification connections being maintained by Identity Cloud or AM will also have an impact on the timely sending of notification messages, as Identity Cloud or AM needs to iterate over every websocket connection for each new notification message to be sent. Any delays in sending notifications could have an impact on the consistency/accuracy of the AmService cache as it may not be aware of an expired token by the time a user next accesses an IG AmService enabled route.

As a general rule, if an AmService is being defined multiple times, for example, across different routes, and the settings are always the same, it would be better to define it once in the heap of the config.json and then refer to it by name in each route as needed. As part of this process (and established via testing), overriding the default AmService handler may be required to ensure that there are enough handler connections available to support many components across multiple routes making requests to Identity Cloud or AM for session info and/or policy evaluations.

Q. Why would I want to override the default AmService handler?

A. There are a number of reasons; here are the most common (often a mix of them all):

  • To change the performance/connection characteristics of the handler, such as timeouts or retries.
  • To support a TLS enabled AM service that uses self-signed certificates.
  • To avoid having a shared handler across multiple AmService instances.
  • To include some targeted capture logging to debug an issue.

Q. How can I override the default AmService handler?

A. There are a number of approaches that can be used in IG; use the one that best fits the use-case:

  • Override the handler named ForgeRockClientHandler in the route's heap or in a parent heap, and it will be picked up automatically by an AmService instance:{ "heap": [{        "name": "CustomHeader",         "type": "HeaderFilter",         "config": {             "messageType": "REQUEST",             "add": {                 "x-custom-header": ["from-ig"]             }         }     }, {         "name": "ForgeRockClientHandler",         "type": "Chain",         "config": {             "filters": [                 "CustomHeader",                 "TransactionIdOutboundFilter"             ],             "handler": {                 "name": "CustomClientHandler",                 "type": "ClientHandler",                 "config": {                     "soTimeout": "20 seconds",                     "retries": {                         "count": 5,                         "delay": "1 second"                     }                 }             }         }     }, {         "name": "AmService",         "type": "AmService",         "config": {             "url": "http://host1.example.com:8080/sso",             "agent": {                 "username": "ig-agent",                 "passwordSecretId": "agent.secret.id"             }         }     }] }
  • Add a reference in the AmService configuration to a custom handler set in the route's heap or in a parent heap:"heap": [{            "name": "CustomForgeRockClientHandler",             "type": "Chain",             "config": {                 "filters": [                     "TransactionIdOutboundFilter"                 ],                 "handler": "ClientHandler"             }         },         {             "name": "ReferenceAmService",             "type": "AmService",             "config": {                 "url": "http://host1.example.com:8080/sso",                 "agent": {                     "username": "ig-agent",                     "passwordSecretId": "agent.secret.id"                 },                 "amHandler": "CustomForgeRockClientHandler"             }         }     ]
  • Add an inline definition as part of the AmService configuration:"heap": [{        "name": "InlineAmService",         "type": "AmService",         "config": {             "url": "http://host1.example.com:8080/sso",             "agent": {                 "username": "ig-agent",                 "passwordSecretId": "agent.secret.id"             },             "amHandler": {                 "type": "Chain",                 "config": {                     "filters": [                         "TransactionIdOutboundFilter"                     ],                     "handler": "ClientHandler"                 }             }         }     }]
  • Use the delegate approach to add a capture decorator to the handler:"heap": [{        "name": "DelegateAmService",         "type": "AmService",         "config": {             "url": "http://host1.example.com:8080/sso",             "agent": {                 "username": "ig-agent",                 "passwordSecretId": "agent.secret.id"             },             "amHandler": {                 "type": "Delegate",                 "name": "DelegateAmServiceHandler",                 "config": {                     "delegate": "ForgeRockClientHandler"                 },                 "capture": "all"             }         }     }]
  • Based on the ClientHandler example, add TLS support to the handler of the AmService:"heap": [{        "name": "TLSClientHandler",         "type": "ClientHandler",         "config": {             "hostnameVerifier": "STRICT",             "tls": {                 "type": "ClientTlsOptions",                 "config": {                     "sslContextAlgorithm": "TLSv1.2",                     "keyManager": {                         "type": "KeyManager",                         "config": {                             "keystore": {                                 "type": "KeyStore",                                 "config": {                                     "url": "file://${env['HOME']}/keystore.jks",                                     "passwordSecretId": "keymanager.keystore.secret.id",                                     "secretsProvider": "SystemAndEnvSecretStore"                                 }                             },                             "passwordSecretId": "keymanager.secret.id",                             "secretsProvider": "SystemAndEnvSecretStore"                         }                     },                     "trustManager": {                         "type": "TrustManager",                         "config": {                             "keystore": {                                 "type": "KeyStore",                                 "config": {                                     "url": "file://${env['HOME']}/truststore.jks",                                     "passwordSecretId": "truststore.secret.id",                                     "secretsProvider": "SystemAndEnvSecretStore"                                 }                             }                         }                     }                 }             }         }     }, {         "name": "TLSAmHandler",         "type": "Chain",         "config": {             "filters": [                 "TransactionIdOutboundFilter"             ],             "handler": "TLSClientHandler"         }     }, {         "name": "TLSAmService",         "type": "AmService",         "config": {             "url": "https://host1.example.com/sso",             "agent": {                 "username": "ig-agent",                 "passwordSecretId": "agent.secret.id"             },             "amHandler": "TLSAmHandler"         }     }]

The final handler used in a customized AmService handler should always be a ClientHandler rather than a ReverseProxyHandler. A ClientHandler is better suited when working with a service/API and the ReverseProxyHandler is better suited when working with proxied applications as the ReverseProxyHandler will return a 502 Bad Gateway response when a downstream connection times out.

Q. What does the TransactionIdOutboundFilter do?

A. The TransactionIdOutboundFilter is a filter that ensures a unique Transaction ID is included in the headers of any request where this filter is applied. It is included by default in the handler used by the AmService so that this header is included in requests to Identity Cloud and AM, and can be used to trace an IG interaction that also makes use of AM services. When customizing the AmService handler, it is important to include this filter to ensure this header is included.

An example of the header is:

X-ForgeRock-TransactionId: 11f5e1ec-d13d-4166-9d81-d7e511c8325e-60/0See TransactionIdOutboundFilter for further information.

Q. How do I change the login URL used when users are sent to Identity Cloud or AM to authenticate?

A. This can be configured via the loginEndpoint configuration item in the SingleSignOnFilter. By default, the SingleSignOnFilter will use the value of the url configuration item from the AmService as the basis for this value.

See SingleSignOnFilter for further information.

Q. How do I change the login journey, service or tree triggered when users are sent to Identity Cloud or AM to authenticate?

A. Since IG 7, the SingleSignOnFilter and CrossDomainSingleSignOnFilter both include a configuration item called authenticationService, that allows the triggering of a specific Identity Cloud journey, or AM service or tree during authentication.

See SingleSignOnFilter and CrossDomainSingleSignOnFilter for further information.

See Also



Single Sign-On and Cross-Domain Single Sign-On

Enforce Policy Decisions From AM

Act As an OAuth 2.0 Resource Server

Trigger An Authentication Service

Trusting Transaction IDs From Other Products

AM Configuring the Trust Transaction Header System Property

Cross-Domain Single Sign-On With the ForgeRock Identity Cloud

FAQ: SSL certificate management in AM and Agents

Copyright and Trademarks Copyright © 2022 ForgeRock, all rights reserved.