ForgeRock IdentityLive APAC

Last month, ForgeRock hosted two IdentityLive events in the Asia-Pacific region.

One in Sydney on August 7 and 8

Sydney Australia

And the second one in Singapore the week after.

Singapore

This was my first participation to the events in this region (somehow I managed to convince my family to move our vacation earlier so I could attend), and it was great meeting in person with many customers and prospects I’ve interacted with over the phone, as well as meeting the ForgeRock colleagues I hadn’t seen for a while. As usual, the conversations around our products and the customers solutions were very rich and open, and I came back with great inputs and confirmations for our roadmaps.

You can find my photos of the events in the following Flickr albums:

The next IdentityLive events will take place in London on October 30-31, and Paris on November 13-14. I hope to see you there!

The OAuth2 Apartment Building

Understand core OAuth2 concepts by analogy and learn how the various ForgeRock Identity Platform components relate to OAuth2.

I live in a modern apartment building. It’s a very nice place – pet friendly, upscale furnishings, prime location. One of the best parts about my apartment building, though, is that it has electronic locks available for all the doors. This is pretty similar to most new hotels; each door opens only by using a key card that was issued by the front-desk. The thing that sets it apart from hotels is that it isn’t just the main apartment door that is opened by a key card – each of the inside doors is too. Every internal door in the entire building will only open for you if your key card is authorized for it.

Surprising thing to consider the best feature, right? You might think having doors like this is actually inconvenient and unnecessary – what value is there to having such a locked-down home? What is wrong with just using a plain-old key to open the front door? Let me explain some of the advantages that this door setup offers.

The other day I was walking through the lobby and I noticed that there was an item on the community bulletin board – an advertisement for “Clint’s Dog-Walking Service”. For a small fee, this company offered to make regular stops up to my apartment to pick up my dog (Fido) and take him for walks, whether I’m at home or not. I felt bad for leaving my pooch at home all day while I was at work, so this sounded like a great deal! I called them up for a trial.

This was a small company, and so they sent Clint himself to meet me in the lobby. I filled out the paperwork for my initial trial and then we walked up to the front-desk for Clint to get his key card to my place. The attendant working the desk was named Amy. The first thing Amy needed to see from me was my driver’s license – she wanted to make sure I really was a tenant in the building and also find out which apartment was mine. Next, as is building policy for all key cards issued to non-tenants, Amy asked Clint for his company information along with which doors of mine he would like to be able to open – it’s important that these details are on file with building management, for liability purposes.

Once she was able to verify that Clint’s company was properly registered, she had me look over a form listing the doors that Clint was asking permission to access. For his dog-walking service, he only needed to open my front door and the “dog room” (like I said, this is a very pet-friendly apartment building). I certainly didn’t want him to be able to open my bedroom or office door – he has no business in there, especially when I’m not at home! Fortunately he was only asking for the doors he needed, so I signed Amy’s form. She filed this away for record-keeping and then produced a brand-new key card, which she then handed over to Clint. This key card was only good for a month; this is another building policy designed to reduce the risk of it getting lost or stolen.

Clint then started his regular service walking my dog. Every time he opened one of my doors, the software managing the door logged his entries. I had peace of mind knowing that he could enter my apartment but only to the areas I had approved. I was very happy with the convenience of the whole thing and confident that my privacy was secure.

After the first month, his card expired and so he stopped by the front-desk for a new one. Amy checked to make sure that he was still allowed access; since I was apparently happy with the service at this point (as far as Amy could tell), there was no reason to refuse his request for a new card. Service continued uninterrupted.

Sadly, I eventually decided that Clint’s service wasn’t really worth the money he was asking. In addition, I was working from home more so I didn’t leave my dog alone as often. I contacted Clint and told him I wanted to cancel my account. I also called up Amy at the front-desk and told her that I would like to deactivate Clint’s current key card, and also prevent him from getting any more cards in the future.

This is why my apartment building really is awesome – if I had an old-school physical key and lock on my door, I would have had to make a copy of my key for Clint. In that case, I would have had no idea when he came and left, which rooms he went into, or if he made any other copies of that key for anyone else. When the time came for me to cancel his service, I would have had to take his word for it that he hadn’t made any additional copies of my key when I asked for it back. To have complete peace of mind that he couldn’t come back in without my approval I would have had to change the locks on my door (and if I had changed the locks, anyone else that I had given a key would need to get a new one). These are major problems! I would have never accepted that much hassle and risk if I had been using an old door lock. As it turns out, Clint’s business was really only possible in an environment where I can control these factors.

This is not really my apartment building, it’s OAuth2. This analogy explains exactly why OAuth2 was created and covers the basic way it works.

Before OAuth2, when you needed to give software services access to your account to do things on your behalf you had to give that service your username and password. This is exactly like the physical door key – there is no way to tell whether the agent accessing your data is a third party doing so on your behalf rather than you doing it yourself. As with the physical key, they would have complete access to everything in your account (similar to how a person with a single physical key to the main apartment door would have access to everything inside). If you want to cancel your service, you would need to change your password to be sure they wouldn’t be able to use it again without your permission.

OAuth2 solves this in the same way that my fictitious apartment building solves the physical key problem.

The apartment you wish to visit is an OAuth2 “resource“. Every apartment has an owner; in OAuth2, every resource has a “resource owner” that is authorized to grant access to it. These are the users in your systems; their data are the resources. ForgeRock Identity Management defines an API for operating on user data that may be exposed in this context.

Just how my apartment building replaced physical keys with electronic key cards, in OAuth2 usernames and passwords have been replaced with “access tokens“.

Similar to opening an apartment door with a key card, you request resources using an access token. Likewise, in the way that you would expect a key card to only be able to open certain doors, access tokens are only usable for specific things. In OAuth2, the particular things an access token is capable of being used for are called “scopes“. In my analogy, the doors within my apartment are all coded to require a specific scope (such as “main door”, “dog room”, “bedroom”, “office”, etc…). Any access token presented to one of them which does not have the required scope will fail to open it.

Clint is an example of an OAuth2 “client“. A client is any entity which has been given an access token. Clients vary based on their relationship to the other parties and the ways in which they are able to get an access token. Regardless of these details, all clients essentially behave the same after they have a token – they use it to request protected resources. Clients are the software applications that you bring into your systems to provide benefits to your users. For software without native OAuth2 client capabilites, ForgeRock Identity Gateway offers an easy way to operate as an OAuth2 client.

The building front-desk and associated door tracking software is the OAuth2 “authorization server” (or AS). It is chiefly responsible for issuing access tokens to clients. For that to be possible, some of the same steps that were taken in my story are also required in OAuth2. For example, by presenting my driver’s license I was able to “authenticate” to the front-desk; OAuth2 authorization servers also require an authentication step (usually a username and password prompt but often other prompts too). After Amy at the front-desk checked my ID, she then looked up the details for Clint’s company. This is part of OAuth2 as well – the client needs to be registered with the AS before any tokens are issued to it. The client is responsible for telling the AS which scopes it would like, similar to the way Clint told Amy which doors he wanted to be able to open. The AS shows the resource owner a list of those scopes, as a means of obtaining informed consent regarding what the client will be able to do with their token. If the resource owner approves, then the AS returns the access token to the client. ForgeRock Access Management implements the role of the authorization server.

Every time the client uses its token to request a protected resource, there is a check made by the software protecting the resource (in OAuth2 terms, this software is called a “resource server“) to verify that the token is legitimate, not expired, and has the necessary scopes for the request. This is called “token introspection“. Usually, token introspection involves a call to the AS that issued the token. In the same way that the door checks with the building management software when a key card is presented, this is something that happens without the client’s involvement. The client only sees if the request is granted; the door either opens or it doesn’t. ForgeRock Identity Gateway offers an easy solution to act as a resource server, with several means of token introspection available to choose from.

Access tokens expire in the same way that the key cards were described. Depending on the agreement made between the client, the resource owner, and the AS there may be a way for the client to obtain new access tokens without having to ask the resource owner every time it expires. This is just like the way Clint was able to get a new key card from Amy after his first expired. In OAuth2, this process involves the “refresh token“. The refresh token is only usable to get new access tokens; it’s not usable directly to access protected resources. The point of this token is to try to limit the risk of lost or stolen access tokens. Both refresh tokens and access tokens can be revoked by the resource owner on the AS, in the same way that I described calling Amy when I wanted to cancel my service with Clint. Revoked access tokens will be detected during token introspection, which will prevent their continued use.

OAuth2 enables new businesses and practices to thrive in a trusted environment where it would be impossible otherwise. By establishing this consent relationship between the clients and the resource owners, people have the tools necessary to maintain their privacy and security to the degree they demand. The ForgeRock Identity Platform is the best means to offer that relationship – go forth and build your own OAuth2 apartment building!

Special thanks to Aaron Parecki for the basic “access token as hotel key card” analogy, which I heard him mention in a user group presentation similar to the one he gives here: Using OAuth2 and OpenID Connect in your Applications.

Update: Read the follow-up which describes how the OAuth2 Apartment Building relates to the OpenID Connect Neighborhood

Documenting ForgeRock DS HTTP APIs

ForgeRock Logo This post is part of a series about how to get live reference documentation for ForgeRock REST APIs.

ForgeRock DS directory servers do not enable the CREST APIs to directory data by default, since you must first adapt the REST to LDAP mapping for your data. To get started with REST to LDAP, see To Set Up REST Access to User Data.

In the end, make sure that the API is enabled before trying to read its descriptor. For example, you can enable the default /api endpoint with the following command (adapted for your installation):

/path/to/opendj/bin/dsconfig \
 set-http-endpoint-prop \
 --hostname opendj.example.com \
 --port 4444 \
 --bindDN "cn=Directory Manager" \
 --bindPassword password \
 --endpoint-name /api \
 --set enabled:true \
 --no-prompt \
 --trustAll

The ForgeRock DS product does not currently include an API explorer, but you can get the OpenAPI-format API descriptor for any or all CREST endpoints. You pass the _api query string parameter to the endpoint. The resulting OpenAPI descriptor is a JSON document. Get available CREST APIs for directory data with a request to the /api endpoint:

curl -o ds.json -u kvaughan:bribery http://localhost:8080/api?_api

To try out the result, download and install Swagger UI, then move the JSON document into the Swagger UI directory. You can then browse the Swagger UI with ds.json as the descriptor:

DS Swagger UI.png

The API descriptor that you load from the server no doubt does not exactly match what you need to publish in your live documentation. Use the Swagger Editor to adapt it to your needs:

DS Swagger Editor.png

For more information, see Working With REST API Documentation.

Documenting ForgeRock IG HTTP APIs

ForgeRock Logo This post is part of a series about how to get live reference documentation for ForgeRock REST APIs.

The ForgeRock IG product does not currently include an API explorer, but you can get the OpenAPI-format API descriptor for any or all endpoints. You pass the _api query string parameter to the endpoint. The resulting OpenAPI descriptor is a JSON document. For example, you can start IG in development mode as described in Starting IG, and then get all available APIs with a request to the /openig/api endpoint:

curl -o ig.json http://localhost:8080/openig/api?_api

To try out the result, download and install Swagger UI, then move the JSON document into the Swagger UI directory. You can then browse the Swagger UI with ig.json as the descriptor:

IG Swagger UI.png

The API descriptor that you load from the server no doubt does not exactly match what you need to publish in your live documentation. Use the Swagger Editor to adapt it to your needs:

IG Swagger Editor.png

For more information, see Understanding IG APIs With API Descriptors.

12 Steps to Zero Trust Success

A Google search for “zero trust” returns ~ 195Million results.  Pretty sure some are not necessarily related to access management and cyber security, but a few probably are.  Zero Trust was a term coined by analyst group Forrester back in 2010 and has gained popularity since Google started using the concept with their employee management project called BeyondCorp.


It was originally focused on network segmentation but has now come to include other aspects of user focused security management.

Below is a hybrid set of concepts that tries to cover all the current approaches.  Please comment below so we can iterate and add more to this over time.


  1. Assign unique, non-reusable identifiers to all subjects [1], objects [2] and network devices [3]
  2. Authenticate every subject
  3. Authenticate every device
  4. Inspect, verify and validate every object access request
  5. Log every object access request
  6. Authentication should contain 2 of something you have, something you are, something you know
  7. Successful authentication should result in a revocable credential [4]
  8. Credentials should be scoped and follow least privilege [5]
  9. Credentials should be bound to a user, device, transaction tuple [6]
  10. Network communications should be encrypted [7]
  11. Assume all services, API’s and applications are accessible from the Internet [8]
  12. Segment processes and network traffic in logical and operational groups


[1] – Users of systems, including employees, partners, customers and other user-interactive service accounts
[2] – API’s, services, web applications and unique data sources
[3] – User devices (such as laptops, mobiles, tablets, virtual machines), service devices (such as printers, faxes) and network management devices (such as switches, routers)
[4] – Such as a cookie, tokenId or access token which is cryptographically secure.  Revocable shouldn't necessarily be limited to being time bound. Eg revocation/black lists etc.
[5] – Credential exchange may be required where access traverses network or object segmentation.  For example an issued credential for subject 1 to access object 1, may require object 1 to contact object 2 to fulfil the request.  The credential presented to object 2 may differ to that presented to object 1.
[6] – Token binding approach such as signature based access tokens or TLS binding
[7] – Using for example standards based protocols such as TLS 1.3 or similar. Eg Google's ALTS.
[8] – Assume perimeter based networking (either software defined or network defined) is incomplete and trust cannot be placed simply on the origin of a request




The below is a list of companies referencing “zero trust” public documentation:

  • Akamai - https://www.akamai.com/uk/en/solutions/zero-trust-security-model.jsp
  • Palo Alto - https://www.paloaltonetworks.com/cyberpedia/what-is-a-zero-trust-architecture
  • Centrify - https://www.centrify.com/zero-trust-security/
  • Cisco - https://blogs.cisco.com/security/why-has-forresters-zero-trust-cybersecurity-framework-become-such-a-hot-topic
  • Microsoft - https://cloudblogs.microsoft.com/microsoftsecure/2018/06/14/building-zero-trust-networks-with-microsoft-365/
  • ScaleFT - https://www.scaleft.com/zero-trust-security/
  • zscaler - https://www.zscaler.com/blogs/corporate/google-leveraging-zero-trust-security-model-and-so-can-you
  • Okta - https://www.okta.com/resources/whitepaper-zero-trust-with-okta-modern-approach-to-secure-access/
  • ForgeRock  - https://www.forgerock.com/blog/zero-trust-importance-identity-centered-security-program
  • Duo Security - https://duo.com/blog/to-trust-or-zero-trust
  • Google’s Beyond Corp - https://beyondcorp.com/
  • Fortinet - https://www.fortinet.com/demand/gated/Forrester-Market-Overview-NetworkSegmentation-Gateways.html

12 Steps to Zero Trust Success

A Google search for “zero trust” returns ~ 195Million results.  Pretty sure some are not necessarily related to access management and cyber security, but a few probably are.  Zero Trust was a term coined by analyst group Forrester back in 2010 and has gained popularity since Google started using the concept with their employee management project called BeyondCorp.


It was originally focused on network segmentation but has now come to include other aspects of user focused security management.

Below is a hybrid set of concepts that tries to cover all the current approaches.  Please comment below so we can iterate and add more to this over time.


  1. Assign unique, non-reusable identifiers to all subjects [1], objects [2] and network devices [3]
  2. Authenticate every subject
  3. Authenticate every device
  4. Inspect, verify and validate every object access request
  5. Log every object access request
  6. Authentication should contain 2 of something you have, something you are, something you know
  7. Successful authentication should result in a revocable credential [4]
  8. Credentials should be scoped and follow least privilege [5]
  9. Credentials should be bound to a user, device, transaction tuple [6]
  10. Network communications should be encrypted [7]
  11. Assume all services, API’s and applications are accessible from the Internet [8]
  12. Segment processes and network traffic in logical and operational groups


[1] – Users of systems, including employees, partners, customers and other user-interactive service accounts
[2] – API’s, services, web applications and unique data sources
[3] – User devices (such as laptops, mobiles, tablets, virtual machines), service devices (such as printers, faxes) and network management devices (such as switches, routers)
[4] – Such as a cookie, tokenId or access token which is cryptographically secure.  Revocable shouldn't necessarily be limited to being time bound. Eg revocation/black lists etc.
[5] – Credential exchange may be required where access traverses network or object segmentation.  For example an issued credential for subject 1 to access object 1, may require object 1 to contact object 2 to fulfil the request.  The credential presented to object 2 may differ to that presented to object 1.
[6] – Token binding approach such as signature based access tokens or TLS binding
[7] – Using for example standards based protocols such as TLS 1.3 or similar. Eg Google's ALTS.
[8] – Assume perimeter based networking (either software defined or network defined) is incomplete and trust cannot be placed simply on the origin of a request




The below is a list of companies referencing “zero trust” public documentation:

  • Akamai - https://www.akamai.com/uk/en/solutions/zero-trust-security-model.jsp
  • Palo Alto - https://www.paloaltonetworks.com/cyberpedia/what-is-a-zero-trust-architecture
  • Centrify - https://www.centrify.com/zero-trust-security/
  • Cisco - https://blogs.cisco.com/security/why-has-forresters-zero-trust-cybersecurity-framework-become-such-a-hot-topic
  • Microsoft - https://cloudblogs.microsoft.com/microsoftsecure/2018/06/14/building-zero-trust-networks-with-microsoft-365/
  • ScaleFT - https://www.scaleft.com/zero-trust-security/
  • zscaler - https://www.zscaler.com/blogs/corporate/google-leveraging-zero-trust-security-model-and-so-can-you
  • Okta - https://www.okta.com/resources/whitepaper-zero-trust-with-okta-modern-approach-to-secure-access/
  • ForgeRock  - https://www.forgerock.com/blog/zero-trust-importance-identity-centered-security-program
  • Duo Security - https://duo.com/blog/to-trust-or-zero-trust
  • Google’s Beyond Corp - https://beyondcorp.com/
  • Fortinet - https://www.fortinet.com/demand/gated/Forrester-Market-Overview-NetworkSegmentation-Gateways.html

Using the ForgeRock IDM API Explorer

ForgeRock Logo This post is part of a series about how to get live reference documentation for ForgeRock REST APIs.

The ForgeRock IDM web-based console includes an API explorer.

The API explorer lets you try out the CREST HTTP APIs as you are building your service. You access the IDM API explorer from the question mark menu in the console. IDM makes many categories of endpoints available. The following example shows the Health category expanded:

IDM browse explorer.png

You can quickly try out one of the API calls. For example, expand /health/memory, and then click the Try it out and Execute buttons:

IDM try health memory endpoint.png

Notice that the API explorer displays everything but the credentials needed to access the REST API.

You can also get the OpenAPI-format API descriptor for the /health endpoint. You pass the _api query string parameter to the endpoint. The resulting OpenAPI descriptor is a JSON document:

curl -u openidm-admin:openidm-admin -o health-api.json http://localhost:8080/openidm/health?_api

To try out the result, download and install Swagger UI, then move the JSON document into the Swagger UI directory. You can then browse the Swagger UI with health-api.json as the descriptor:

IDM Swagger UI.png

The API descriptor that you load from the server no doubt does not exactly match what you need to publish in your live documentation. Use the Swagger Editor to adapt it to your needs:

IDM Swagger Editor.png

For more information, see API Explorer.

Using the ForgeRock AM API Explorer

ForgeRock Logo This post is part of a series about how to get live reference documentation for ForgeRock REST APIs.

The ForgeRock AM web-based console includes an API explorer. The API explorer lets you try out the CREST HTTP APIs as you are building your service.

You access the AM API explorer from the question mark menu in the console:

AM API explorer.png

By default, there are many APIs published in the top-level realm. A simple one that you can try right away when logged in as AmAdmin is an action on the /sessions endpoint. Click /sessions in the left menu, scroll down, and click /sessions#1.2_query_id_all:

AM browse API explorer.png

Next, scroll to and click the Try it out! button:

AM try sessions endpoint.png

Notice that the API explorer displays everything but the AM SSO details that your browser is using to authenticate with your AmAdmin session.

Suppose you want to get the OpenAPI-format API descriptor for the /sessions endpoint. You pass the _api query string parameter to the endpoint. The resulting OpenAPI descriptor is a JSON document:

curl -o sessions-api.json http://openam.example.com:8080/openam/json/sessions?_api

To try out the result, download and install Swagger UI, then move the JSON document into the Swagger UI directory.

For example, copy the Swagger UI dist folder into the same Apache Tomcat server used by OpenAM, add the descriptor, and restart Tomcat:

unzip swagger-ui-version.zip
cp -r swagger-ui-version/dist /path/to/tomcat/webapps/swagger-ui
mv sessions-api.json /path/to/tomcat/webapps/swagger-ui/
/path/to/tomcat/bin/shutdown.sh
/path/to/tomcat/bin/startup.sh

Now browse http://openam.example.com:8080/swagger-ui/ with http://openam.example.com:8080/swagger-ui/sessions-api.json as the descriptor:

AM Swagger UI.png

The API descriptor that you load from the server no doubt does not exactly match what you need to publish in your live documentation. Use the Swagger Editor to adapt it to your needs:

AM Swagger Editor.png

For more information, see Introducing the API Explorer. For details about authenticating to use the APIs outside the console, see Authentication and Logout.

About REST APIs and API Descriptors

ForgeRock Logo This post briefly describes the types of HTTP APIs available through the ForgeRock platform, and which ones come with live reference documentation.

The following categories of HTTP APIs are available in the ForgeRock platform:

ForgeRock Common REST (CREST) APIs

ForgeRock Common REST provides a framework for HTTP APIs. Each of the component products in the platform uses CREST to build APIs that do CRUDPAQ operations in the same ways.

ForgeRock platform component products generate live reference documentation in a standard format (Swagger, which has been standardized as OpenAPI) for CREST APIs. This is done through a mechanism referred to as API descriptors. You can use this documentation to try out the CREST APIs.

Standard HTTP APIs such as OAuth 2.0

Standard HTTP APIs are defined by organizations like the IETF for OAuth 2.0, the Kantara Initiative for UMA, and the OpenID Connect Working Group. These APIs have their own implementations and do not use CREST. They are documented where they are used in the product documentation.

The canonical documentation is the specifications for the standards. At present, the ForgeRock platform components do not generate live documentation for these standard APIs.

Non-RESTful, Challenge-Response HTTP APIs

Some APIs, such as the authentication API used in ForgeRock AM and the user self-service API used in ForgeRock IDM are not fully RESTful. Instead, they use challenge-response mechanisms that have the developer return to the same endpoint with different payloads during a session.

These APIs are documented in the product documentation.

The ForgeRock API reference documentation published with the product docs is, necessarily, abstract. It does not provide you a sandbox to try out the APIs. Unlike a SaaS, with its fixed configuration, the ForgeRock platform components are highly configurable. ForgeRock HTTP APIs depend on how you decide to configure each service.

Live Reference Documentation

It is your software deployment or SaaS, built with the ForgeRock platform, that publishes concrete APIs.

You can capture the OpenAPI-format docs, and edit them to correspond to the APIs you actually want to publish. A browser-based, third-party application, Swagger UI, makes it easy to set up a front end to a sandbox service so your developers can try out your APIs.

Note that you still need to protect the endpoints. In particular, prevent developers from using the endpoints you do not want to publish.

The following posts in this series will look at how to work with the APIs when developing your configuration, and how to get the OpenAPI-format descriptors to publish live API documentation for your developers.

Using IG to Protect IDM For Secure and Standards-Based Integration

ForgeRock Identity Management (IDM) has a rich set of REST APIs capable of performing many actions; this is one of the great values that IDM has to offer. However, with such a broad set of APIs available out of the box, it is reasonable to want to limit which of those REST APIs are directly available to the public. The most common way to enforce that limit is to use an API gateway to act as a reverse proxy. In this way, only the requests which the gateway has been configured to allow will be sent to IDM.

In addition to offering a filter, API gateways can offer many powerful options for authentication and authorization which are not available directly within IDM. One important example of this need is for OAuth2 clients to be able to request IDM REST APIs using an access token that was obtained from ForgeRock Access Management (AM). In this way, the IDM endpoints would be able to be treated as standard OAuth2 resource server endpoints; the gateway can validate the presence of the access token and introspect it to ensure that there are appropriate scopes for the request. Being able to rely on an access token as the means by which clients work with the IDM REST API is often easier, more secure, and more inter-operable than other means available.

In this article I’m going to focus on how you could configure ForgeRock Identity Gateway (IG) to accomplish both of these goals. You will be able to use this configuration as a pattern for deploying IDM functionality in a secure and standards-based way, making it easy to integrate with your own applications. Some basic knowledge about installation and typical use for each product is assumed; please review the product documentation if you are unfamiliar with either product.

Securing the connection between IDM and IG

When IG is responsible for securing the requests to IDM, it is important to configure IDM so that it will only accept connections which originate from IG. One way to accomplish this is to configure your network topology and firewall rules to prevent anything besides IG from being able to make a connection; doing so will be specific to your environment, so I won’t cover how to do that here; ask your network administrator for help. In addition to the network level security, you should also secure the connection with an encrypted channel using client SSL certificates. Both methods used together will provide the most robust security.

Configuring IDM to accept connections from IG

Since IG will be handling the direct end-user authentication, IDM only needs to handle the authentication of the requests originating from IG. As they are separate processes, there must be a standard HTTPS interface between them (IG proxing the client requests to the IDM server). The main security challenge is to ensure that only IG is able to make these direct HTTPS requests to IDM. Essentially, IDM needs a way to first authenticate IG itself so that it can then operate on behalf of the actual user. There are a few details that need to considered in order to do this.

Static Users

First is the simple fact that IG is not a “user” in the sense that IDM normally expects – it is more of a service, and as such will probably not have a corresponding record available on the IDM router (in the way that users normally do).  Because authentication in IDM requires a route for every authenticated subject, we have to find a way to supply one. One simple way to do this is to create a custom endpoint that provides a sort of pseudo-route. For example, you can create a file named “conf/endpoint-staticuser.json” with this content:

{
    "type" : "text/javascript",
    "context" : "endpoint/static/user/*",
    "source" : "request.method === 'query' ? ([{_id: request.additionalParameters._id}]) : ({_id: context.security.authenticationId})"
}

This handy endpoint is designed to work with the authentication service. It simply reflects back the id provided (either as a query parameter or from the security context). Using this, we can define authentication modules for “users” which don’t have any other router entry, such as the case with IG.

Client Certificate Authentication

The next step is to actually configure the authentication module that IG will be using. In this case, we are going use the “CLIENT_CERT” authentication module, following a similar process to the one described in “Configuring Client Certification Authentication“. Example openssl commands and more background detail can be found there.

This module requires that the “client” (in this case, IG) has a particular SSL certificate that it is able to present to IDM when it connects via HTTPS. Using our above “static/user” endpoint, here’s the most basic example JSON configuration showing how this could be done:

{
    "name": "CLIENT_CERT",
    "properties": {
        "queryOnResource": "endpoint/static/user",
        "defaultUserRoles": [
            "openidm-cert"
        ],
        "allowedAuthenticationIdPatterns": [
            "CN=ig, O=forgerock"
        ]
    },
    "enabled": true
}

This declaration authenticates any request which has supplied a client certificate that meets two conditions:

  1. It is trusted in terms of SSL (either directly imported in the IDM truststore or signed by a CA which is within the IDM truststore).
  2. It has a “subject” which matches one of the patterns listed under “allowedAuthenticationIdPatterns”. In this example, the subject needs to exactly match “CN=ig, O=forgerock”.

If both of those conditions are met, then the request will be authenticated, and it will be recognized as a “static/user” type of entity with the “openidm-cert” role. The intent behind this configuration is that requests from IG are recognized within this context.

Run As

The final configuration necessary within IDM is to allow IG to make requests on behalf of the user it has authenticated. In IDM 6.0, there is a new feature available for every authentication module which supports this – “RunAs Authentication“. This feature allows privileged clients to supply an “X-OpenIDM-RunAs” header in order to specify the name of the user they would like to operate on behalf of. This is obviously a highly-sensitive type of operation – only the most trusted clients (such as IG) should be allowed to operate under the guise of other users. You will need to configure IDM in order to allow IG to do this. For example, you can expand the CLIENT_CERT authentication module configuration like so (added values in italics):

{
    "name": "CLIENT_CERT",
    "properties": {
        "queryOnResource": "endpoint/static/user",
        "defaultUserRoles": [
            "openidm-cert"
        ],
        "allowedAuthenticationIdPatterns": [
            "CN=ig, O=forgerock"
        ],
        "runAsProperties": {
            "adminRoles": [
                "openidm-cert"
            ],
            "disallowedRunAsRoles": [ ],
            "queryOnResource": "managed/user",
            "propertyMapping": {
                "authenticationId" : "userName",
                "userRoles": "authzRoles"
            },
            "defaultUserRoles" : [
                "openidm-authorized"
            ]
        }
    },
    "enabled": true
}

By using this configuration, any authenticated request which comes from IG should include an “X-OpenIDM-RunAs” header that identifies the “userName” value for the associated “managed/user” record. IG will be the only client capable of making this sort of request, because it is the only entity which has the private key associated with the trusted certificate.

Configuring IG to accept connections for IDM

Now that IDM is prepared to accept connections, IG needs to be configured to make them correctly.

Trusting IDM

Review the chapter in the IG configuration guide called “Configuring IG for HTTPS (client-side)“. If IDM is using a self-signed certificate, you will need to import that into IG’s truststore as described there.

Supplying a Client Certificate

All requests made by IG to a back-end are via a “ClientHandler“.  By default, there is no special behavior associated with a ClientHandler – it simply acts as a generic HTTP/S client. The best option for us is to define a new ClientHandler on the IG “heap” that is configured to perform client certification authentication. The most important declaration for this use is the “keyManager“; this is how you tell the ClientHandler where to get the keys to use when prompted for client certificates. Here is an example of a configured client that is ready to trust IDM’s certificate and supply its own:

{
    "name": "IDMClient",
    "type": "ClientHandler",
    "config": {
        "hostnameVerifier": "ALLOW_ALL",
        "sslContextAlgorithm": "TLSv1.2",
        "keyManager": {
            "type": "KeyManager",
            "config": {
                "keystore": {
                    "type": "KeyStore",
                    "config": {
                        "url": "file:///var/openig/keystore.jks",
                        "password": "changeit"
                    }
                },
                "password": "changeit"
            }
        },
        "trustManager": {
            "type": "TrustManager",
            "config": {
                "keystore": {
                    "type": "KeyStore",
                    "config": {
                        "url": "file:///var/openig/keystore.jks",
                        "password": "changeit"
                    }
                }
            }
        }
    }
}

In this example, the /var/openig/keystore.jks file contains both the public certificate needed to trust IDM and the private key needed to authenticate IG as a client. Make sure that all IG routes which forward requests to IDM use this ClientHandler.

Including the RunAs Header

Before the request is forwarded to IDM via the IDMClient, it needs to be modified to include the X-OpenIDM-RunAs header. This allows IDM to find the user that is actually making the request, via IG.

There are several ways to modify the request before it is sent to IDM, but all of them involve a filter on the route. The simplest example is to use the “HeaderFilter“, like so:

{
     "type": "HeaderFilter",
     "config": {
         "messageType": "REQUEST",
         "add": {
             "X-OpenIDM-RunAs": [ "${contexts.oauth2.accessToken.info.sub}" ]
         }
     }
}

If you have more complex logic around your user behavior, you might want to use a ScriptableFilter, within which you could set the header with code like so:

String sub = contexts.oauth2.accessToken.info.sub
request.getHeaders().add('X-OpenIDM-RunAs', sub)
return next.handle(context, request)

Operating as an OAuth2 resource server

While there are many potential benefits provided by IG, the main one explored in this article is to operate as an OAuth2 resource server. The core feature is well documented – see both the IG gateway guide and the configuration reference. The main detail to consider in this specific context is about how you want to manage scopes. In order for requests to successfully pass through the OAuth2ResourceServerFilter, the token must have the correct scopes associated with it. What constitutes as a “correct” scope value for any given request is up to you to decide. You will need to consider which IDM endpoints and methods you want to make available and how to express that availability in terms of a scope. For example, if you want to allow OAuth2 clients to be able to make calls to the “/openidm/endpoint/usernotifications” endpoint, you could define a scope called “notifications” and require it with a route like so:

{
    "name": "notificationsRoute",
    "baseURI": "https://idm.example.com:8444",
    "condition": "${matches(request.uri.path, '^/openidm/endpoint/usernotifications')}",
    "handler": {
        "type": "Chain",
        "config": {
            "filters": [
                {
                    "type": "OAuth2ResourceServerFilter",
                    "config": {
                        "scopes": [
                            "notifications"
                        ],
                        "accessTokenResolver": "AccessTokenResolver"
                    }
                },
                {
                     "type": "HeaderFilter",
                     "config": {
                         "messageType": "REQUEST",
                         "add": {
                             "X-OpenIDM-RunAs": [ "${contexts.oauth2.accessToken.info.sub}" ]
                         }
                     }
                }
            ],
            "handler": "IDMClient"
        }
    },
    "heap": [
        {
            "name": "AccessTokenResolver",
            "type": "TokenIntrospectionAccessTokenResolver",
            "config": {
                "endpoint": "https://am.example.com/openam/oauth2/introspect",
                "providerHandler": {
                    "type": "Chain",
                    "config": {
                        "filters": [
                            {
                                "type": "HeaderFilter",
                                "config": {
                                    "messageType": "request",
                                    "add": {
                                        "Authorization": [
                                            "Basic ${encodeBase64('openidmClient:openidmClient')}"
                                        ]
                                    }
                                }
                            }
                        ],
                        "handler": "ClientHandler"
                    }
                }
            }
        },
        {
            "name": "IDMClient",
            "type": "ClientHandler",
            "config": {
                "hostnameVerifier": "ALLOW_ALL",
                "sslContextAlgorithm": "TLSv1.2",
                "keyManager": {
                    "type": "KeyManager",
                    "config": {
                        "keystore": {
                            "type": "KeyStore",
                            "config": {
                                "url": "file:///var/openig/keystore.jks",
                                "password": "changeit"
                            }
                        },
                        "password": "changeit"
                    }
                },
                "trustManager": {
                    "type": "TrustManager",
                    "config": {
                        "keystore": {
                            "type": "KeyStore",
                            "config": {
                                "url": "file:///var/openig/keystore.jks",
                                "password": "changeit"
                            }
                        }
                    }
                }
            }
        }
    ]
}

The details about how to validate the access token are shown here via the “AccessTokenResolver” heap object. There are a lot of legitimate configuration options worth exploring for the “OAuth2ResourceServerFilter” filter; see the reference documentation to see the full range. In this example, it is calling out to a standard OAuth2 token introspection endpoint provided by AM, authenticated with a registered client called “openidmClient”. See the documentation regarding how to configure AM to operate as a token introspection service. Be sure that the client you register for the IG resource server filter has the “am-introspect-all-tokens” scope included within it.

You will want to define similar route entries as this for each scope requirement you want to declare. To reduce the amount of duplicated route configuration, I suggest you move the common parts between each route (such as the IDMClient and AccessTokenResolver heap objects) into the global IG “config.json” file. See more details about route definition in the IG gateway guide section on the subject.

Complete configuration example

There is a full sample configuration available as part of the “ForgeOps” project which follows these patterns. This sample brings up AM configured to operate as an OAuth2 AS, providing token creation and introspection. It configures IG to act as an OAuth2 RS, and configures IDM to accept connections exclusively from IG. By reviewing the “rs” and “idm” sub-folders included within that sample, you should recognize many of the points described in this article. See the included README.md file within that sample for details regarding how to start it up. This sample configuration will be used as the basis for subsequent articles which will discuss how you can use specific OAuth2 client libraries to make requests to IDM endpoints.

Go forth and build your secure, standards-based applications, integrated with the ForgeRock Identity Platform!