Developing Client Applications

Client applications access OpenAM services for authentication, authorization, and single sign-on/single logout through the use of sessions. Client applications can also be allowed to manage authorization policies.

Client application integration with OpenAM can be coupled loosely, as in the case of an application running in a web server with an OpenAM policy agent to handle interaction with OpenAM service, more directly, as in the case where the client interacts with OpenAM over protocol, or tightly, as in the case of an application using the OpenAM Java or C API to interact with OpenAM services.

This chapter covers client interaction with OpenAM using OpenAM APIs over supported protocols.

Using the REST API

This section shows how to use the OpenAM RESTful interfaces for direct integration between web client applications and OpenAM.

About the RESTful APIs

Representational State Transfer (REST) is an architectural style that sets certain constraints for designing and building large-scale distributed hypermedia systems.

As an architectural style, REST has very broad applications. The designs of both HTTP 1.1 and URIs follow RESTful principles. The World Wide Web is no doubt the largest and best known REST application. Many other web services also follow the REST architectural style. Examples include OAuth 2.0, OpenID Connect 1.0, and User-Managed Access (UMA) 1.0.

Open Identity Platform Common REST (CREST) applies RESTful principles to define common verbs for HTTP-based APIs that access web resources and collections of web resources.

Native OpenAM REST APIs in version 11.0.0 and later use the CREST verbs. (In contrast, OAuth 2.0, OpenID Connect 1.0 and UMA 1.0 APIs follow their respective standards.) APIs covered in Deprecated REST APIs predate CREST, do not use the CREST verbs, and are deprecated in OpenAM 15.1.5.

When using a CREST API, you use the common verbs as query string parameters in resource and resource collection URIs.

CREST APIs use these verbs:

create

Add a new resource.

Create maps to HTTP POST (or PUT).

read

Retrieve a single resource.

Read maps to HTTP GET.

update

Replace an existing resource.

Update maps to HTTP PUT.

delete

Remove an existing resource.

Delete maps to HTTP DELETE.

patch

Modify part of an existing resource

Patch maps to HTTP PATCH.

_action

Perform a predefined action.

Action maps to HTTP POST.

The generic _action verb extends the API’s capabilities where none of the other standard CREST verbs fit, as in _action=logout.

query

Search a collection of resources.

Query maps to HTTP GET.

CRUDPAQ is an acronym for the verbs. Notice that reserved words in CREST, such as the verbs, start with underscores (_).

In CREST, you can address resources in collections of resources by their unique identifiers, their IDs. IDs are exposed in the resource URIs as in /users/id and /groups/id. The ID is also in the _id field of the resource.

In CREST, resources are versioned using revision numbers. A revision is specified in the resource’s _rev field. Revisions make it possible to figure out whether to apply changes without resource locking and without distributed transactions.

In CREST, you can explicitly request API versions. This means that OpenAM can continue to support older API versions as well as newer API versions as developers migrate their applications to take advantage of capabilities provided by newer APIs.

Interface Stability: Evolving

OpenAM offers RESTful APIs for access and identity management as follows:

In this section, long URLs are wrapped to fit the printed page, as some of the output is formatted for easier reading.

REST API Versioning

In OpenAM 12.0.0 and later, REST API features are assigned version numbers.

Providing version numbers in the REST API helps ensure compatibility between OpenAM releases. The version number of a feature increases when OpenAM introduces a non-backwards-compatible change that affects clients making use of the feature.

OpenAM provides versions for the following aspects of the REST API.

resource

Any changes to the structure or syntax of a returned response will incur a resource version change. For example changing errorMessage to message in a JSON response.

protocol

Any changes to the methods used to make REST API calls will incur a protocol version change. For example changing _action to $action in the required parameters of an API feature.

Supported REST API Versions

The REST API version numbers supported in OpenAM 15.1.5 are as follows:

Supported protocol versions

The protocol versions supported in OpenAM 15.1.5 are:

  • 1.0

Supported resource versions

The resource versions supported in OpenAM 15.1.5 are shown in the following table.

Supported resource Versions
Base End Point Supported Versions

/json

/authenticate

1.1, 2.0

/users

1.1, 1.2, 2.0, 2.1, 3.0

/groups

1.1, 2.0, 2.1, 3.0

/agents

1.1, 2.0, 2.1, 3.0

/realms

1.0

/dashboard

1.0

/sessions

1.1

/serverinfo/*

1.1

/users/{user}/devices/trusted

1.0

/users/{user}/uma/policies

1.0

/applications

1.0, 2.0

/resourcetypes

1.0

/policies

1.0, 2.0

/applicationtypes

1.0

/conditiontypes

1.0

/subjecttypes

1.0

/subjectattributes

1.0

/decisioncombiners

1.0

/subjectattributes

1.0

/xacml

/policies

1.0

/frrest

/token

1.0

/client

1.0

Specifying an Explicit REST API Version

You can specify which version of the REST API to use by adding an Accept-API-Version header to the request, as in the following example, which is requesting resource version 2.0 and protocol version 1.0:

$ curl \
 --request POST \
 --header "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: changeit" \
 --header "Accept-API-Version: resource=2.0, protocol=1.0" \
 https://openam.example.com:8443/openam/json/authenticate

You can configure the default behavior OpenAM will take when a REST call does not specify explicit version information. For more information, see "Configuring REST APIs" in the Administration Guide.

REST API Versioning Messages

OpenAM provides REST API version messages in the JSON response to a REST API call. You can also configure OpenAM to return version messages in the response headers. See "Configuring REST APIs" in the Administration Guide.

Messages include:

  • Details of the REST API versions used to service a REST API call.

  • Warning messages if REST API version information is not specified or is incorrect in a REST API call.

The resource and protocol version used to service a REST API call are returned in the Content-API-Version header, as shown below:

$ curl \
 -i \
 --request POST \
 --header "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: changeit" \
 --header "Accept-API-Version: resource=2.0, protocol=1.0" \
 https://openam.example.com:8443/openam/json/authenticate

HTTP/1.1 200 OK
Content-API-Version: protocol=1.0,resource=2.0
Server: Restlet-Framework/2.1.7
Content-Type: application/json;charset=UTF-8

{
 "tokenId":"AQIC5wM...TU3OQ*",
 "successUrl":"/openam/console"
}

If the default REST API version behavior is set to None, and a REST API call does not include the Accept-API-Version header, or does not specify a resource version, then a 400 Bad Request status code is returned, as shown below:

$ curl \
 --header "Content-Type: application/json" \
 --header "Accept-API-Version: protocol=1.0" \
 https://openam.example.com:8443/openam/json/serverinfo/*

{
 "code":400,
 "reason":"Bad Request",
 "message":"No requested version specified and behavior set to NONE."
}

If a REST API call does include the Accept-API-Version header, but the specified resource or protocol version does not exist in OpenAM, then a 404 Not Found status code is returned, as shown below:

$ curl \
 --header "Content-Type: application/json" \
 --header "Accept-API-Version: protocol=1.0, resource=999.0" \
 https://openam.example.com:8443/openam/json/serverinfo/*

{
 "code":404,
 "reason":"Not Found",
 "message":"Accept-API-Version: Requested version \"999.0\" does not match any routes."
}

For more information on setting the default REST API version behavior, see "Configuring REST APIs" in the Administration Guide.

Token Encoding

Valid tokens in OpenAM requires configuration either in percent encoding or in C66Encode format. C66Encode format is encouraged. It is the default token format for OpenAM, and is used in this section. The following is an example token that has not been encoded:

AQIC5wM2LY4SfczntBbXvEAOuECbqMY3J4NW3byH6xwgkGE=@AAJTSQACMDE=#

This token includes reserved characters such as +, /, and = (The @, #, and * are not reserved characters per se, but substitutions are still required). To c66encode this token, you would substitute certain characters for others, as follows:

  • + is replaced with -

  • / is replaced with _

  • = is replaced with .

  • @ is replaced with *

  • # is replaced with *

  • * (first instance) is replaced with @

  • * (subsequent instances) is replaced with # In this case, the translated token would appear as shown here:

AQIC5wM2LY4SfczntBbXvEAOuECbqMY3J4NW3byH6xwgkGE.*AAJTSQACMDE.*

Specifying Realms in REST API Calls

This section describes how to work with realms when making REST API calls to OpenAM.

Realms can be specified in three ways when making a REST API call to OpenAM:

DNS Alias

When making a REST API call, the DNS alias of a realm can be specified in the subdomain and domain name components of the REST endpoint.

To list all users in the top-level realm use the DNS alias of the OpenAM instance, for example the REST endpoint would be:

https://openam.example.com:8443/openam/json/users?_queryId=*

+ To list all users in a realm with DNS alias suppliers.example.com the REST endpoint would be:

https://suppliers.example.com:8443/openam/json/users?_queryId=*

+

Path

When making a REST API call, the realm, or realm alias, can be specified in the path component of the REST endpoint.

To authenticate a user in the top-level realm the REST endpoint would be:

https://openam.example.com:8443/openam/json/authenticate

+ To authenticate a user in a realm named customers the REST endpoint would be:

https://openam.example.com:8443/openam/json/customers/authenticate

+

+ Subrealms are supported and should be separated with a forward slash (/).

+ For example, to authenticate to a subrealm named europe of a realm named partners, the REST endpoint would be:

+

https://openam.example.com:8443/openam/json/partners/europe/authenticate
Query Parameter

When making a REST API call the realm, or realm alias, can be specified as the value of a query parameter named realm.

To list the groups in the top-level realm the REST endpoint would be:

https://openam.example.com:8443/openam/json/groups?_queryId=*

+ To list the groups in a realm named partners the REST endpoint would be:

https://openam.example.com:8443/openam/json/groups?realm=/partners&_queryId=*

+

+

When working with a named subrealm of the top-level realm a forward slash preceeding the realm name is required. You should not use a forward slash when using a realm alias.

+ Subrealms are supported and should be separated with a forward slash (/).

+ To authenticate a user in a subrealm named europe of a realm named partners the REST endpoint would be:

+

https://openam.example.com:8443/openam/json/authenticate?realm=/partners/europe

If more than one of the above methods is used to specify realms in a REST endpoint, OpenAM applies the following rules to determine the realm to use.

  1. If realms are specified using both the DNS alias and path methods, they are concatenated together.

    For example, the following REST endpoint returns users in a subrealm named europe of a realm with DNS alias suppliers.

    https://suppliers.example.com:8443/openam/json/europe/users?_queryId=*
  2. If realms are specified using the realm query parameter, they override anything specified in either the DNS alias or path method.

    For example, the following REST endpoint returns users in a subrealm of the customers realm, named asia.

    https://suppliers.example.com:8443/openam/json/europe/users?realm=/customers/asia&_queryId=*

Authentication and Logout

You can use REST-like APIs under /json/authenticate and /json/sessions for authentication and for logout.

The /json/authenticate endpoint does not support the CRUDPAQ verbs and therefore does not technically satisfy REST architectural requirements. The term REST-like describes this endpoint better than REST.

The simplest user name/password authentication returns a tokenId that applications can present as a cookie value for other operations that require authentication. The type of tokenId returned varies depending on whether stateless sessions are enabled in the realm to which the user authenticates:

  • If stateless sessions are not enabled, the tokenId is an OpenAM SSO token.

  • If stateless sessions are enabled, the tokenId is an OpenAM SSO token that includes an encoded OpenAM session.

Developers should be aware that the size of the tokenId for stateless sessions—2000 bytes or greater—is considerably longer than for stateful sessions—approximately 100 bytes. For more information about stateful and stateless session tokens, see "Session Cookies" in the Administration Guide.

When authenticating with a user name and password, use HTTP POST to prevent the web container from logging the credentials. Pass the user name in an X-OpenAM-Username header, and the password in an X-OpenAM-Password header:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: changeit" \
 --data "{}" \
 https://openam.example.com:8443/openam/json/authenticate
{ "tokenId": "AQIC5w...NTcy*", "successUrl": "/openam/console" }

To use UTF-8 user names and passwords in calls to the /json/authenticate endpoint, base64-encode the string, and then wrap the string as described in RFC 2047:

encoded-word = "=?" charset "?" encoding "?" encoded-text "?="

For example, to authenticate using a UTF-8 username, such as ɗëɱø, perform the following steps:

  1. Encode the string in base64 format: yZfDq8mxw7g=.

  2. Wrap the base64-encoded string as per RFC 2047: =?UTF-8?B?yZfDq8mxw7g=?=.

  3. Use the result in the X-OpenAM-Username header passed to the authentication endpoint as follows:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: =?UTF-8?B?yZfDq8mxw7g=?=" \
    --header "X-OpenAM-Password: changeit" \
    --data "{}" \
    https://openam.example.com:8443/openam/json/authenticate
         {
          "tokenId": "AQIC5w...NTcy*",
          "successUrl": "/openam/console"
          }

This zero page login mechanism works only for name/password authentication. If you include a POST body with the request, it must be an empty JSON string as shown in the example. Alternatively, you can leave the POST body empty. Otherwise, OpenAM interprets the body as a continuation of an existing authentication attempt, one that uses a supported callback mechanism.

The authentication service at /json/authenticate supports callback mechanisms that make it possible to perform other types of authentication in addition to simple user name/password login.

Callbacks that are not completed based on the content of the client HTTP request are returned in JSON as a response to the request. Each callback has an array of output suitable for displaying to the end user, and input which is what the client must complete and send back to OpenAM. The default is still user name/password authentication:

$ curl \
 --request POST \
 https://openam.example.com:8443/openam/json/authenticate
{
    "authId": "...jwt-value...",
    "template": "",
    "stage": "DataStore1",
    "callbacks": [
        {
            "type": "NameCallback",
            "output": [
                {
                    "name": "prompt",
                    "value": " User Name: "
                }
            ],
            "input": [
                {
                    "name": "IDToken1",
                    "value": ""
                }
            ]
        },
        {
            "type": "PasswordCallback",
            "output": [
                {
                    "name": "prompt",
                    "value": " Password: "
                }
            ],
            "input": [
                {
                    "name": "IDToken2",
                    "value": ""
                }
            ]
        }
    ]
}

The authID value is a JSON Web Token (JWT) that uniquely identifies the authentication context to OpenAM, and so must also be sent back with the requests.

To respond to the callback, send back the JSON object with the missing values filled, as in this case where the user name is demo and the password is changeit:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --data '{ "authId": "...jwt-value...", "template": "", "stage": "DataStore1",
   "callbacks": [ { "type": "NameCallback", "output": [ { "name": "prompt",
   "value": " User Name: " } ], "input": [ { "name": "IDToken1", "value": "demo" } ] },
   { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Password: " } ],
   "input": [ { "name": "IDToken2", "value": "changeit" } ] } ] }' \
 https://openam.example.com:8443/openam/json/authenticate

{ "tokenId": "AQIC5wM2...U3MTE4NA..*", "successUrl": "/openam/console" }

The response is a token ID holding the SSO token value.

Alternatively, you can authenticate without requesting a session using the noSession query string parameter:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --data '{ "authId": "...jwt-value...", "template": "", "stage": "DataStore1",
   "callbacks": [ { "type": "NameCallback", "output": [ { "name": "prompt",
   "value": " User Name: " } ], "input": [ { "name": "IDToken1", "value": "demo" } ] },
   { "type": "PasswordCallback", "output": [ { "name": "prompt", "value": " Password: " } ],
   "input": [ { "name": "IDToken2", "value": "changeit" } ] } ] }' \
 https://openam.example.com:8443/openam/json/authenticate?noSession=true

{ "message": "Authentication Successful", "successUrl": "/openam/console" }

OpenAM can be configured to return a failure URL value when authentication fails. No failure URL is configured by default. The Default Failure Login URL can be configured for the "Configuring Core Authentication Attributes" in the Administration Guide authentication module. Alternatively, failure URLs can be configured per authentication chain, which your client can specify using the service parameter described below. On failure OpenAM then returns HTTP status code 401 Unauthorized, and the JSON in the reply indicates the failure URL:

$ curl \
 --request POST \
 --header "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: badpassword" \
 https://openam.example.com:8443/openam/json/authenticate
{
  "code":401,
  "reason":"Unauthorized",
  "message":"Invalid Password!!",
  "failureUrl": "http://www.example.com/401.html"
}

To specify a realm in your request, first make sure that the name of your realm does not match an endpoint name to avoid any potential routing errors. Then, specify the realm in one of two ways. For example, if you have a realm titled myRealm, you can use it in your request as follows:

  • Using the realm in the URI to the endpoint (preferred method):

    https://openam.example.com:8443/openam/json/myRealm/authenticate
  • Using the realm query string parameter:

    https://openam.example.com:8443/openam/json/authenticate?realm=myRealm

You can use the authIndexType and authIndexValue query string parameters as a pair to provide additional information about how you are authenticating. The authIndexType can be one of the following types:

composite

Set the value to a composite advice string.

level

Set the value to the authentication level.

module

Set the value to the name of an authentication module.

resource

Set the value to a URL protected by an OpenAM policy.

role

Set the value to an OpenAM role.

service

Set the value to the name of an authentication chain.

user

Set the value to an OpenAM user ID.

You can use the query string parameter, sessionUpgradeSSOTokenId=tokenId, to request session upgrade. For an explanation of session upgrade, see "Authentication Levels and Session Upgrade" in the Administration Guide. OpenAM uses the following callback types depending on the authentication module in use:

  • ChoiceCallback: Used to display a list of choices and retrieve the selected choice.

  • ConfirmationCallback: Used to ask for a confirmation such as Yes, No, or Cancel and retrieve the selection.

  • HiddenValueCallback: Used to return form values that are not visually rendered to the end user.

  • HttpCallback: Used for HTTP handshake negotiations.

  • LanguageCallback: Used to retrieve the locale for localizing text presented to the end user.

  • NameCallback: Used to retrieve a name string.

  • PasswordCallback: Used to retrieve a password value.

  • RedirectCallback: Used to redirect the client user-agent.

  • ScriptTextOutputCallback: Used to insert a script into the page presented to the end user. The script can, for example, collect data about the user’s environment.

  • TextInputCallback: Used to retrieve text input from the end user.

  • TextOutputCallback: Used to display a message to the end user.

  • X509CertificateCallback: Used to retrieve the content of an x.509 certificate.

Authenticated users can log out with the token cookie value and an HTTP POST to /json/sessions/?_action=logout:

$ curl \
 --request POST \
 --header "iplanetDirectoryPro: AQIC5wM2...U3MTE4NA..*" \
 "https://openam.example.com:8443/openam/json/sessions/?_action=logout"

{"result":"Successfully logged out"}

Load Balancer and Proxy Layer Requirements

When authentication depends on the client IP address and OpenAM lies behind a load balancer or proxy layer, configure the load balancer or proxy to send the address by using the X-Forwarded-For header, and configure OpenAM to consume and forward the header as necessary. For details, see "Handling HTTP Request Headers" in the Installation Guide.

Windows Desktop SSO Requirements

When authenticating with Windows Desktop SSO, add an Authorization header containing the string Basic, followed by a base64-encoded string of the username, a colon character, and the password. In the following example, the credentials demo:changeit are base64-encoded into the string ZGVtbzpjaGFuZ2VpdA==:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: changeit" \
 --header "Authorization: Basic ZGVtbzpjaGFuZ2VpdA==" \
 --data "{}" \
 https://openam.example.com:8443/openam/json/authenticate

{ "tokenId": "AQIC5w...NTcy*", "successUrl": "/openam/console" }

Using the Session Token After Authentication

The following is a common scenario when accessing OpenAM by using REST API calls:

  • First, call the /json/authenticate endpoint to log a user in to OpenAM. This REST API call returns a tokenID value, which is used in subsequent REST API calls to identify the user:

    $ curl \
     --request POST \
     --header "Content-Type: application/json" \
     --header "X-OpenAM-Username: demo" \
     --header "X-OpenAM-Password: changeit" \
     --data "{}" \
     https://openam.example.com:8443/openam/json/authenticate
    
    { "tokenId": "AQIC5w...NTcy*", "successUrl": "/openam/console" }

    The returned tokenID is known as a session token (also referred to as an SSO token). REST API calls made after successful authentication to OpenAM must present the session token in the HTTP header as proof of authentication.

  • Next, call one or more additional REST APIs on behalf of the logged-in user. Each REST API call passes the user’s tokenID back to OpenAM in the HTTP header as proof of previous authentication.

    The following is a partial example of a curl command that inserts the token ID returned from a prior successful OpenAM authentication attempt into the HTTP header:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "iPlanetDirectoryPro: AQIC5w...NTcy*" \
    --data '{
      ...

    Observe that the session token is inserted into a header field named iPlanetDirectoryPro. This header field name must correspond to the name of the OpenAM session cookie—by default, iPlanetDirectoryPro. You can find the cookie name in the OpenAM console by navigating to Deployment > Servers > Server Name > Security > Cookie, in the Cookie Name field of the OpenAM console.

    Once a user has authenticated, it is not necessary to insert login credentials in the HTTP header in subsequent REST API calls. Note the absence of X-OpenAM-Username and X-OpenAM-Password headers in the preceding example.

    Users are required to have appropriate privileges in order to access OpenAM functionality using the REST API. For example, users who lack administrative privileges cannot create OpenAM realms. For more information on the OpenAM privilege model, see "Managing Realms" in the Administration Guide.

  • Finally, call the REST API to log the user out of OpenAM as described in "Authentication and Logout". As with other REST API calls made after a user has authenticated, the REST API call to log out of OpenAM requires the user’s tokenID in the HTTP header.

Filtering, Sorting, and Paging Results

Some OpenAM endpoints support additional query string parameters when querying the REST APIs to manipulate the returned data.

The query string parameters for manipulating returned results are:

_queryFilter

The _queryFilter parameter can take true to return every result, false to return no results, or a filter of the following form to match field values: field operator value where field represents the field name, operator is the operator code, value is the value to match, and the entire filter is URL-encoded.

Supported fields and operator codes vary depending on the endpoint.

The operators codes are as follows:

  • co: contains

  • eq: equals

  • ge: greater than or equal to

  • gt: greater than

  • le: less than or equal to

  • lt: less than

  • pr: field exists, field is present

    Do not set a value when using this operator.

  • sw: starts with

    Filters can be composed of multiple expressions by a using boolean operator AND, OR, or ! (NOT) and by using parentheses, (expression) to group expressions.

    Regular expressions are implemented for some operators, so you can create a filter that includes or excludes certain records.

    You must URL-encode the filter expression in _queryFilter=filter.

The following example returns resource types with a name that contains Service and also has a pattern that starts with http:

+

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
--get \
--data-urlencode \
'_queryFilter=name co "Service" and patterns sw "http"' \
https://openam.example.com:8443/openam/json/resourcetypes
_fields

You can use _fields=field-name[,field-name…​] to limit the fields returned in the output.

The following example returns the name and creationDate of all policies in the top level realm:

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
--get \
--data-urlencode '_queryFilter=true' \
--data-urlencode '_fields=name,creationDate' \
https://openam.example.com:8443/openam/json/policies
_prettyPrint

You can use the query string parameters _prettyPrint=true to make the output easier to read.

_pageSize

You can use _pageSize=integer to limit the number of results returned.

_pagedResultsOffset

You can use _pagedResultsOffset=integer to return results starting at a specified result when using paged results.

_sortKeys

You can use _sortKeys=[-]field-name[,field-name...]` to sort the results returned, where __field-name__ represents a field in the returned JSON. Optionally use the ` prefix to sort in ascending order (the default), or - to sort in descending order.

The following example returns all applications in the top level realm, sorted in descending creationDate order:

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
--get \
--data-urlencode '_queryFilter=true' \
--data-urlencode '_sortKeys=-creationDate' \
https://openam.example.com:8443/openam/json/applications

Server Information

You can retrieve OpenAM server information by using HTTP GET on /json/serverinfo/* as follows:

$ curl https://openam.example.com:8443/openam/json/serverinfo/*
{
    "domains": [
        ".example.com"
    ],
    "protectedUserAttributes": [],
    "cookieName": "iPlanetDirectoryPro",
    "secureCookie": false,
    "forgotPassword": "false",
    "forgotUsername": "false",
    "kbaEnabled": "false",
    "selfRegistration": "false",
    "lang": "en-US",
    "successfulUserRegistrationDestination": "default",
    "socialImplementations": [
        {
            "iconPath": "XUI/images/logos/facebook.png",
            "authnChain": "FacebookSocialAuthenticationService",
            "displayName": "Facebook",
            "valid": true
        }
    ],
    "referralsEnabled": "false",
    "zeroPageLogin": {
        "enabled": false,
        "refererWhitelist": [
            ""
        ],
        "allowedWithoutReferer": true
    },
    "realm": "/",
    "xuiUserSessionValidationEnabled": true,
    "FQDN": "openam.example.com"
}

Token Validation and Session Information

OpenAM provides REST APIs under /json/sessions for validating SSO tokens and getting information about active sessions.

Validating Sessions

To check over REST whether a session token is valid, perform an HTTP POST to the resource URL, /json/sessions/tokenId, using the validate action as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
  http://openam.example.com:8080/openam/json/sessions/AQIC5...?_action=validate
{"valid":true,"uid":"demo","realm":"/myRealm"}

If the session token is not valid, a "valid": false JSON message is returned, as shown below:

$ curl \
--request POST \
--header "Content-Type: application/json" \
  http://openam.example.com:8080/openam/json/sessions/AQIC5...?_action=validate
{"valid":false}

Validating a session token has the tangential effect of resetting the idle timeout for a stateful session. If session failover is enabled in your deployment, validating session tokens can trigger write operations to the Core Token Service token store. See "Obtaining Information About Sessions" for information about how to validate a session token without resetting the idle timeout, thereby avoiding the overhead of writes to the token store.

Note that OpenAM does not reset the idle timeout for a stateless session.

Obtaining Information About Sessions

You can use REST API calls to:

  • Identify whether a session is active

  • Check the maximum remaining amount of time a session has left before the user is required to reauthenticate

  • Determine the length of time a stateful session has been idle

  • Reset a stateful session’s idle time to 0

For these REST endpoints, specify two token IDs. Provide the token ID for the current authenticated user as the value of a header whose name is the name of the SSO token cookie, by default iPlanetDirectoryPro. Specify the token ID you want information about as the tokenId query string parameter of the REST URL. In the examples in this section, AQIC5w…​NTcy* is the token ID for the current authenticated user, while BXCCq…​NX*1* is the token being queried.

To determine whether a session is active, perform an HTTP POST to the resource URL, /json/sessions/, using the isActive action as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
  http://openam.example.com:8080/openam/json/sessions/?_action=isActive&tokenId=BXCCq...NX*1*
{"active":true}

To check the maximum remaining time (in seconds) of a session, perform an HTTP POST to the resource URL, /json/sessions/, using the getTimeLeft action as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
  http://openam.example.com:8080/openam/json/sessions/?_action=getTimeLeft&tokenId=BXCCq...NX*1*
{"maxtime":7022}

To check the time (in minutes) configured for sessions, perform an HTTP POST to the resource URL, /json/sessions/, using the getMaxSessionTime action as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
  http://openam.example.com:8080/openam/json/sessions/?_action=getMaxSessionTime
{"maxsessiontime":120}

To check the idle time (in minutes) configured for sessions, perform an HTTP POST to the resource URL, /json/sessions/, using the getMaxIdle action as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
  http://openam.example.com:8080/openam/json/sessions/?_action=getMaxIdle
{"maxidletime":30}

To check the amount of time (in seconds) that a stateful session has been idle, perform an HTTP POST to the resource URL, /json/sessions/, using the getIdle action as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
  http://openam.example.com:8080/openam/json/sessions/?_action=getIdle&tokenId=BXCCq...NX*1*
{"idletime":355}

Because OpenAM does not monitor idle time for stateless sessions, do not use the tokenId of a stateless session when using the getIdle action.

To reset a stateful session’s idle time, perform an HTTP POST to the resource URL, /json/sessions/, using the isActive action with the refresh=true option as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
  http://openam.example.com:8080/openam/json/sessions/?_action=isActive&refresh=true&tokenId=BXCCq...NX*1*
{"active":true}

REST API calls to retrieve session information do not reset a stateful session’s idle time if you specify the refresh=false parameter, which is the default.

If you specify the refresh=true parameter, OpenAM resets the idle time for stateful sessions. If session failover is enabled in your deployment, resetting a stateful session’s idle time can trigger write operations to the Core Token Service token store. Therefore, to avoid the overhead of writes to the token store, be careful to use the refresh=true parameter only if you want to reset a stateful session’s idle time.

Because OpenAM does not monitor idle time for stateless sessions, do not use the tokenId of a stateless session when refreshing a session’s idle time.

Refreshing Stateful Sessions

To reset the idle time of a stateful session using REST, perform an HTTP POST to the /json/sessions/ endpoint, using the refresh action. The endpoint will refresh the session token provided in the iPlanetDirectoryPro header by default. To refresh a different session token, include it as the value of the tokenId query parameter.

The following example shows an administrative user passing their session token in the iPlanetDirectoryPro header, and the session token of the demo user as the tokenId query parameter:

$ curl \
--request POST \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
http://openam.example.com:8080/openam/json/sessions/?_action=isActive&refresh=true&tokenId=BXCCq...NX*1*
{
 "uid": "demo",
 "realm": "/",
 "idletime": 4,
 "maxidletime": 30,
 "maxsessiontime": 120,
 "maxtime": 7195
}

On success, OpenAM resets the idle time for the stateful session, and returns timeout details of the session.

Resetting a stateful session’s idle time triggers a write operation to the Core Token Service token store. Therefore, to avoid the overhead of write operations to the token store, be careful to use the refresh action only if you want to reset a stateful session’s idle time.

Because OpenAM does not monitor idle time for stateless sessions, do not use the tokenId of a stateless session when refreshing a session’s idle time.

Invalidating Sessions

To invalidate a session, perform an HTTP POST to the /json/sessions/ endpoint using the logout action. The endpoint will invalidate the session token provided in the iPlanetDirectoryPro header by default. To refresh a different session token, include it as the value of the tokenId query parameter.

For example, the following shows an administrative user passing their session token in the iPlanetDirectoryPro header, and the session token of the demo user as the tokenId query parameter:

$ curl \
--request POST \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
http://openam.example.com:8080/openam/json/sessions/?_action=logout&tokenId=BXCCq...NX*1*
{
 "result": "Successfully logged out"
}

On success, OpenAM invalidates the session and returns a success message.

If the token is not valid and cannot be invalidated an error message is returned, as follows:

{
 "result": "Token has expired"
}

Session Properties

OpenAM lets you set, read, and delete properties on users' sessions using REST API calls.

Before you can perform operations on session properties using the REST API, you must first define the properties you want to set in the Session Property Whitelist Service configuration. For information on whitelisting session properties, see "Session Property Whitelist" in the Reference.

You can use REST API calls for the following purposes:

  • To retrieve the names of the properties that you can read, set, or delete. This is the same set of properties configured in the Session Property Whitelist Service.

  • To set property values.

  • To read property values.

  • To delete property values. Deleting a property value sets the property to an empty string.

Session state affects the ability to set and delete properties as follows:

  • You can set and delete properties on a stateful session at any time during the session’s lifetime.

  • You can only set and delete properties on a stateless session during the authentication process, before the user receives the session token from OpenAM. For example, you could set or delete properties on a stateless session from within a post-authentication plugin.

Differentiate the user who performs the operation on session properties from the session affected by the operation as follows:

  • Specify the session token of the user performing the operation on session properties in the iPlanetDirectoryPro header.

  • Specify the session token of the user whose session is to be read or modified as the tokenId parameter to the REST API call.

  • Omit the tokenId parameter from the REST API call if the session of the user performing the operation is the session that you want to read or modify.

The following examples assume that you configured a property named LoginLocation in the Session Property Whitelist Service configuration.

To retrieve the names of the properties you can get or set, perform an an HTTP POST to the resource URL, /json/sessions/, using the getPropertyNames action as shown in the following example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
  http://openam.example.com:8080/openam/json/sessions/?_action=getPropertyNames
{"properties":["LoginLocation"]}

To set the value of a session property, perform an HTTP POST to the resource URL, /json/sessions/, using the setProperty action. Because no tokenId parameter is present in the REST API call, the session affected by the operation is the session specified in the iPlanetDirectoryPro header:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
--data '{"LoginLocation":"40.748440, -73.984559"}' \
  http://openam.example.com:8080/openam/json/sessions/?_action=setProperty
{"success":true}

You can set multiple properties in a single REST API call by specifying a set of fields and their values in the JSON data. For example, --data '{"property1":"value1", "property2":"value2"}'.

To set the value of a session property on another user’s session, specify the session token of the user performing the setProperty action in the iPlanetDirectoryPro, and specify the session token to be modified as the value of the tokenId parameter:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
--data '{"LoginLocation":"40.748440, -73.984559"}' \
    http://openam.example.com:8080/openam/json/sessions/?_action=setProperty&tokenId=BXCCq...NX*1*
{"success":true}

If the user attempting to modify the session does not have sufficient access privileges, the preceding example results in a 403 Forbidden error.

To read the value of a session property, perform an HTTP POST to the resource URL, /json/sessions/, using the getProperty action:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
--data '{"properties": ["LoginLocation"]}' \
  http://openam.example.com:8080/openam/json/sessions/?_action=getProperty
{"LoginLocation":"40.748440, -73.984559"}

You can read multiple properties in a single REST API call by specifying an array of fields in the JSON data. For example, --data '{"properties": ["property1", "property2"]}'.

To delete the value of a session property, perform an HTTP POST to the resource URL, /json/sessions/, using the deleteProperty action:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
--data '{"properties": ["LoginLocation"]}' \
  http://openam.example.com:8080/openam/json/sessions/?_action=deleteProperty
{"success":true}

You can not read or set properties internal to OpenAM sessions. If you specify an internal property in a REST API call, a 403 Forbidden error is returned. For example:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iplanetDirectoryPro: AQIC5w...NTcy*" \
--data '{"properties": ["AuthLevel"]}' \
  http://openam.example.com:8080/openam/json/sessions/?_action=getProperty
{"code":403,"reason":"Forbidden","message":"Forbidden"}

REST Goto URL Validation

You can set valid goto URLs using the OpenAM console by following the instructions in "Configuring Valid goto URL Resources" in the Administration Guide.

To validate a goto URL over REST, use the endpoint: /json/user?_action=validateGoto.

$ curl \
--request POST --header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: AQIC5...ACMDE.*" \
--data "'{"goto":"http://www.example.com/"}' \
http://openam.example.com:8080/openam/json/users?_action=validateGoto

{"successURL":"http://www.example.com/"}

Logging

OpenAM 15.1.5 supports two Audit Logging Services: a new common REST-based Audit Logging Service, and the legacy Logging Service, which is based on a Java SDK and is available in OpenAM versions prior to OpenAM 13. The legacy Logging Service is deprecated in OpenAM 15.1.5.

Both audit facilities log OpenAM REST API calls.

Common Audit Logging of REST API Calls

OpenAM logs information about all REST API calls to the access topic. For more information about OpenAM audit topics, see "Audit Log Topics" in the Administration Guide.

Locate specific REST endpoints in the http.path log file property.

Legacy Logging of REST API Calls

OpenAM logs information about REST API calls to two files:

  • amRest.access. Records accesses to a CREST endpoint, regardless of whether the request successfully reached the endpoint through policy authorization.

    An amRest.access example is as follows:

    $ cat openam/openam/log/amRest.access
    
    #Version: 1.0
    #Fields: time  Data  LoginID  ContextID  IPAddr  LogLevel  Domain  LoggedBy  MessageID  ModuleName
    NameID  HostName
    "2011-09-14 16:38:17"   /home/user/openam/openam/log/ "cn=dsameuser,ou=DSAME Users,o=openam"
    aa307b2dcb721d4201 "Not Available" INFO  o=openam   "cn=dsameuser,ou=DSAME Users,o=openam"
    LOG-1  amRest.access  "Not Available"  192.168.56.2
    "2011-09-14 16:38:17"  "Hello World"  id=bjensen,ou=user,o=openam 8a4025a2b3af291d01  "Not Available"
    INFO  o=openam id=amadmin,ou=user,o=openam "Not Available" amRest.access "Not Available"
    192.168.56.2
  • amRest.authz. Records all CREST authorization results regardless of success. If a request has an entry in the amRest.access log, but no corresponding entry in amRest.authz, then that endpoint was not protected by an authorization filter and therefore the request was granted access to the resource.

    The amRest.authz file contains the Data field, which specifies the authorization decision, resource, and type of action performed on that resource. The Data field has the following syntax:

    ("GRANT"||"DENY") > "RESOURCE | ACTION"
    
    where
      "GRANT > " is prepended to the entry if the request was allowed
      "DENY  > " is prepended to the entry if the request was not allowed
      "RESOURCE" is "ResourceLocation | ResourceParameter"
         where
           "ResourceLocation" is the endpoint location (e.g., subrealm/applicationtypes)
           "ResourceParameter" is the ID of the resource being touched
            (e.g., myApplicationType) if applicable. Otherwise, this field is empty
            if touching the resource itself, such as in a query.
    
      "ACTION" is "ActionType | ActionParameter"
         where
           "ActionType" is "CREATE||READ||UPDATE||DELETE||PATCH||ACTION||QUERY"
           "ActionParameter" is one of the following depending on the ActionType:
              For CREATE: the new resource ID
              For READ: empty
              For UPDATE: the revision of the resource to update
              For DELETE: the revision of the resource to delete
              For PATCH: the revision of the resource to patch
              For ACTION: the actual action performed (e.g., "forgotPassword")
              For QUERY: the query ID if any
    $ cat openam/openam/log/amRest.authz
    
    #Version: 1.0
    #Fields: time   Data  ContextID  LoginID  IPAddr  LogLevel  Domain  MessageID  LoggedBy  NameID
    ModuleName    HostName
    "2014-09-16 14:17:28"   /var/root/openam/openam/log/   7d3af9e799b6393301
    "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org" "Not Available" INFO
    dc=openam,dc=forgerock,dc=org  LOG-1  "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org"
    "Not Available" amRest.authz    10.0.1.5
    "2014-09-16 15:56:12"  "GRANT > sessions|ACTION|logout|AdminOnlyFilter"  d3977a55a2ee18c201
    id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org "Not Available" INFO  dc=openam,dc=forgerock,dc=org
    OAuth2Provider-2  "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org"  "Not Available"
    amRest.authz    127.0.0.1
    "2014-09-16 15:56:40"   "GRANT > sessions|ACTION|logout|AdminOnlyFilter"  eedbc205bf51780001
    id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org  "Not Available" INFO dc=openam,dc=forgerock,dc=org
    OAuth2Provider-2  "cn=dsameuser,ou=DSAME Users,dc=openam,dc=forgerock,dc=org"  "Not Available"
    amRest.authz    127.0.0.1

OpenAM also provides additional information in its debug notifications for accesses to any endpoint, depending on the message type (error, warning or message) including realm, user, and result of the operation.

REST Status Codes

OpenAM REST APIs respond to successful requests with HTTP status codes in the 2xx range. OpenAM REST APIs respond to error conditions with HTTP status codes in the 4xx and 5xx range. Status codes used are described in the following list:

200 OK

The request was successful and a resource returned, depending on the request. For example, a successful HTTP GET on /users/myUser returns a user profile and status code 200, whereas a successful HTTP DELETE returns {"success","true"} and status code 200.

201 Created

The request succeeded and the resource was created.

400 Bad Request

The request was malformed. Either parameters required by the action were missing, or as in the following example incorrect data was sent in the payload for the action:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --data '{"bad":"data"}' \
 https://openam.example.com:8443/openam/json/users?_action=forgotPassword

{
 "code":400,
 "reason":"Bad Request",
 "message":"Username or email not provided in request"
}
401 Unauthorized

The request requires user authentication as in the following example, which is missing an SSO Token value:

$ curl \
 --request POST \
 https://openam.example.com:8443/openam/json/sessions?_action=logout

{
 "code": 401,
 "reason": "Unauthorized",
 "message": "Access denied"
}
403 Forbidden

Access was forbidden during an operation on a resource as in the following example, which has a regular user trying to read the OpenAM administrator profile:

$ curl \
 --request POST \
 --header "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: changeit" \
 https://openam.example.com:8443/openam/json/authenticate

{ "tokenId": "AQIC5w...YyMA..*" }

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...YyMA..*" \
 https://openam.example.com:8443/openam/json/users/amadmin

{
 "code": 403,
 "reason": "Forbidden",
 "message": "Permission to perform the read operation denied to
             id=demo,ou=user,dc=openam,dc=forgerock,dc=org"
}
404 Not Found

The specified resource could not be found as in the following example, which is attempting to read a nonexistent user’s profile:

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...NTcy*" \
 https://openam.example.com:8443/openam/json/users/missing

{
 "code":404,
 "reason":"Not Found",
 "message":"Resource cannot be found."
}
405 Method Not Allowed

The HTTP method is not allowed for the requested resource.

406 Not Acceptable

The request contains parameters that are not acceptable as in the following example, which specifies an API version parameter that is not supported by OpenAM:

$ curl \
 --request POST \
 --header "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: changeit" \
 --header "Accept-API-Version: protocol=1.0, resource=999.0" \
 https://openam.example.com:8443/openam/json/authenticate

{
 "code":406,
 "reason":"Not Acceptable",
 "message":"Accept-API-Version: Requested version \"999.0\" does not match any routes."
}
409 Conflict

The request would have resulted in a conflict with the current state of the resource. For example using the Forgot Password feature and specifying the user’s email address as in the following example, where multiple users have the same email address:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --data '{"email":"demo@example.com"}' \
 https://openam.example.com:8443/openam/json/users?_action=forgotPassword

{
 "code":409,
 "reason":"Conflict",
 "message":"Multiple users found"
}
410 Gone

The requested resource is no longer available, and will not become available again. The URI returned for resetting a password may have expired as in the following example:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --data '{"username": "demo"}' \
 https://openam.example.com:8443/openam/json/users/?_action=forgotPassword

{
 "code":410,
 "reason":"Gone",
 "message":"Token not found"
}
415 Unsupported Media Type

The request is in a format not supported by the requested resource for the requested method as in the following example, which is attempting to pass basic authentication credentials as form-encoded data rather than query string parameters:

$ curl \
 --request POST \
 --data "username=demo&password=changeit" \
 https://openam.example.com:8443/openam/json/authenticate

...
HTTP Status 415
...
The server refused this request because the request entity is in a
format not supported by the requested resource for the requested method
...
500 Internal Server Error

The server encountered an unexpected condition which prevented it from fulfilling the request. This could be caused by an invalid configuration in the Email Service, or as in the following example the specified user account not having an associated email address to send the Forgot Password URI to:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --data '{"username": "demo"}' \
 https://openam.example.com:8443/openam/json/users/?_action=forgotPassword

{
 "code":500,
 "reason":"Internal Server Error",
 "message":"No email provided in profile."
}
501 Not Implemented

The resource does not support the functionality required to fulfill the request as in the following example, which is attempting to delete an entry as a delete action instead of using an HTTP DELETE request:

$ curl \
 --request POST \
 --header "iplanetDirectoryPro: AQIC5w...NTcy*" \
 https://openam.example.com:8443/openam/json/users/demo?_action=delete

{
 "code": 501,
 "reason": "Not Implemented",
 "message": "Actions are not supported for resource instances"
}
503 Service Unavailable

The requested resource was temporarily unavailable. The service may have been disabled, as in the following example, where the Forgot Password functionality has been disabled:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --data '{"username": "demo"}' \
 https://openam.example.com:8443/openam/json/users/?_action=forgotPassword

{
 "code":503,
 "reason":"Service Unavailable",
 "message":"Forgot password is not accessible."
}

RESTful Authorization and Policy Management Services

This section shows how to use the OpenAM RESTful interfaces for authorization and policy management.

About the REST Policy Endpoints

OpenAM provides REST APIs both for requesting policy decisions, and also for administering policy definitions.

  • Under /json{/realm}/resourcetypes, you find a JSON-based API for managing resource types.

  • Under /json{/realm}/applications and /json/applicationtypes you find JSON-based APIs for administering policy sets and reading application types.

  • Under /json{/realm}/policies, you find a JSON-based API for policy management and evaluation.

  • Under /json/conditiontypes you find a JSON-based API for viewing what types of conditions you can use when defining policies.

  • Under /json/subjecttypes you find a JSON-based API for viewing what types of subjects you can use when defining policies.

  • Under /json/subjectattributes you find a JSON-based API for viewing subjects' attributes you can use when defining response attributes in policies.

  • Under /json/decisioncombiners you find a JSON-based API for viewing implementations you can use when defining policies to specify how to combine results when multiple policies apply.

Before making a REST API call to request a policy decision or manage a policy component, make sure that you have:

  • Authenticated successfully to OpenAM as a user with sufficient privileges to make the REST API call

  • Obtained the session token returned after successful authentication

When making the REST API call, pass the session token in the HTTP header. For more information about the OpenAM session token and its use in REST API calls, see "Using the Session Token After Authentication".

Requesting Policy Decisions

You can request policy decisions from OpenAM by using the REST APIs described in this section. OpenAM evaluates requests based on the context and the policies configured, and returns decisions that indicate what actions are allowed or denied, as well as any attributes or advice for the resources specified.

To request decisions for specific resources, see "Requesting Policy Decisions For Specific Resources".

To request decisions for a resource and all resources beneath it, see "Requesting Policy Decisions For a Tree of Resources".

Requesting Policy Decisions For Specific Resources

This section shows how you can request a policy decision over REST for specific resources.

To request policy decisions for specific resources, perform an HTTP POST using the evaluation action to the appropriate path under the URI where OpenAM is deployed, /json{/realm}{/subrealm}/policies?_action=evaluate, where realm and subrealm optionally specifies the realm. The payload for the HTTP POST is a JSON object that specifies at least the resources, and takes the following form.

{
    "resources": [
        "resource1",
        "resource2",
        ...,
        "resourceN"
    ],
    "application": "defaults to iPlanetAMWebAgentService if not specified",
    "subject": {
        "ssoToken": "SSO token ID string",
        "jwt": "JSON Web Token string",
        "claims": {
            "key": "value",
            ...
        }
    },
    "environment": {
        "optional key1": [
            "value",
            "another value",
            ...
        ],
        "optional key2": [
            "value",
            "another value",
            ...
        ],
        ...
    }
}

The values for the fields shown above are explained below:

"resources"

This required field specifies the list of resources for which to return decisions.

For example, when using the default policy set, "iPlanetAMWebAgentService", you can request decisions for resource URLs.

{
    "resources": [
        "http://www.example.com/index.html",
        "http://www.example.com/do?action=run"
    ]
}
"application"

This field holds the name of the policy set, and defaults to "iPlanetAMWebAgentService" if not specified.

For more on policy sets, see "Managing Policy Sets".

"subject"

This optional field holds an object that represents the subject. You can specify one or more of the following keys. If you specify multiple keys, the subject can have multiple associated principals, and you can use subject conditions corresponding to any type in the request.

"ssoToken"

The value is the SSO token ID string for the subject, returned for example on successful authentication as described in "Authentication and Logout".

"jwt"

The value is a JWT string.

"claims"

The value is an object (map) of JWT claims to their values.

If you do not specify the subject, OpenAM uses the SSO token ID of the subject making the request.

"environment"

This optional field holds a map of keys to lists of values.

If you do not specify the environment, the default is an empty map.

The example below requests policy decisions for two URL resources. The iPlanetDirectoryPro header sets the SSO token for a user who has access to perform the operation.

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iPlanetDirectoryPro: AQIC5..." \
 --data '{
    "resources": [
        "http://www.example.com/index.html",
        "http://www.example.com/do?action=run"
    ],
    "application": "iPlanetAMWebAgentService"
 }' \
 https://openam.example.com:8443/openam/json/policies?_action=evaluate
 [ {
  "resource" : "http://www.example.com/do?action=run",
  "actions" : {
  },
  "attributes" : {
  },
  "advices" : {
    "AuthLevelConditionAdvice" : [ "3" ]
  }
}, {
  "resource" : "http://www.example.com/index.html",
  "actions" : {
    "POST" : false,
    "GET" : true
  },
  "attributes" : {
    "cn" : [ "demo" ]
  },
  "advices" : {
  }
 }
]

In the JSON list of decisions returned for each resource, OpenAM includes these fields.

"resource"

A resource specified in the request.

The decisions returned are not guaranteed to be in the same order as the resources were requested.

"actions"

A map of action name keys to Boolean values that indicate whether the action is allowed (true) or denied (false) for the specified resource.

In the example, for resource http://www.example.com:80/index.html HTTP GET is allowed, whereas HTTP POST is denied.

"attributes"

A map of attribute names to their values, if any response attributes are returned according to applicable policies.

In the example, the policy that applies to http://www.example.com:80/index.html causes that the value of the subject’s "cn" profile attribute to be returned.

"advices"

A map of advice names to their values, if any advice is returned according to applicable policies.

The "advices" field can provide hints regarding what OpenAM needs to take the authorization decision.

In the example, the policy that applies to http://www.example.com:80/do?action=run requests that the subject be authenticated at an authentication level of at least 3.

{
    "advices": {
        "AuthLevelConditionAdvice": [
            "3"
        ]
    }
}

See "Policy Decision Advice" for details.

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Policy Decision Advice

When OpenAM returns a policy decision, the JSON for the decision can include an "advices" field. This field contains hints for the policy enforcement point.

{
    "advices": {
        "type": [
            "advice"
        ]
    }
}

The "advices" returned depend on policy conditions. For more information about OpenAM policy conditions, see "Managing Policies".

This section shows examples of the different types of policy decision advice and the conditions that cause OpenAM to return the advice.

"AuthLevel" and "LEAuthLevel" condition failures can result in advice showing the expected or maximum possible authentication level. For example, failure against the following condition:

{
    "type": "AuthLevel",
    "authLevel": 2
}

Leads to this advice:

{
    "AuthLevelConditionAdvice": [
        "2"
    ]
}

An "AuthScheme" condition failure can result in advice showing one or more required authentication modules. For example, failure against the following condition:

{
    "type": "AuthScheme",
    "authScheme": [
        "HOTP"
    ],
    "applicationName": "iPlanetAMWebAgentService",
    "applicationIdleTimeout": 10
}

Leads to this advice:

{
    "AuthSchemeConditionAdvice": [
        "HOTP"
    ]
}

An "AuthenticateToRealm" condition failure can result in advice showing the name of the realm to which authentication is required. For example, failure against the following condition:

{
    "type": "AuthenticateToRealm",
    "authenticateToRealm": "MyRealm"
}

Leads to this advice:

{
    "AuthenticateToRealmConditionAdvice": [
        "/myRealm"
    ]
}

An "AuthenticateToService" condition failure can result in advice showing the name of the required authentication chain. For example, failure against the following condition:

{
    "type": "AuthenticateToService",
    "authenticateToService": "MyAuthnChain"
}

Leads to this advice:

{
    "AuthenticateToServiceConditionAdvice": [
        "MyAuthnChain"
    ]
}

A "ResourceEnvIP" condition failure can result in advice showing that indicates corrective action to be taken to resolve the problem. The advice varies, depending on what the condition tests. For example, failure against the following condition:

{
    "type": "ResourceEnvIP",
    "resourceEnvIPConditionValue": [
        "IF IP=[127.0.0.12] THEN authlevel=4"
    ]
}

Leads to this advice:

{
    "AuthLevelConditionAdvice": [
        "4"
    ]
}

Failure against a different type of "ResourceEnvIP" condition such as the following:

{
    "type": "ResourceEnvIP",
    "resourceEnvIPConditionValue": [
        "IF IP=[127.0.0.11] THEN service=MyAuthnChain"
    ]
}

Leads to this advice:

{
    "AuthenticateToServiceConditionAdvice": [
        "MyAuthnChain"
    ]
}

A "Session" condition failure can result in advice showing that access has been denied because the user’s stateful or stateless session has been active longer than allowed by the condition. The advice will also show if the user’s session was terminated and reauthentication is required. For example, failure against the following condition:

{
    "type": "Session",
    "maxSessionTime": "10",
    "terminateSession": false
}

Leads to this advice:

{
    "SessionConditionAdvice": [
        "deny"
    ]
}

When policy evaluation denials occur against the following conditions, OpenAM does not return any advice:

  • IPv4

  • IPv6

  • LDAPFilter

  • OAuth2Scope

  • SessionProperty

  • SimpleTime

Requesting Policy Decisions For a Tree of Resources

This section shows how you can request policy decisions over REST for a resource and all other resources in the subtree beneath it.

To request policy decisions for a tree of resources, perform an HTTP POST using the evaluation action to the appropriate path under the URI where OpenAM is deployed, /json{/realm}/policies?_action=evaluateTree, where realm optionally specifies the realm. The payload for the HTTP POST is a JSON object that specifies at least the root resource, and takes the following form.

{
    "resource": "resource string",
    "application": "defaults to iPlanetAMWebAgentService if not specified",
    "subject": {
        "ssoToken": "SSO token ID string",
        "jwt": "JSON Web Token string",
        "claims": {
            "key": "value",
            ...
        }
    },
    "environment": {
        "optional key1": [
            "value",
            "another value",
            ...
        ],
        "optional key2": [
            "value",
            "another value",
            ...
        ],
        ...
    }
}

The values for the fields shown above are explained below:

"resource"

This required field specifies the root resource for the decisions to return.

For example, when using the default policy set, "iPlanetAMWebAgentService", you can request decisions for resource URLs.

{
    "resource": "http://www.example.com/"
}
"application"

This field holds the name of the policy set, and defaults to "iPlanetAMWebAgentService" if not specified.

For more on policy sets, see "Managing Policy Sets".

"subject"

This optional field holds an object that represents the subject. You can specify one or more of the following keys. If you specify multiple keys, the subject can have multiple associated principals, and you can use subject conditions corresponding to any type in the request.

"ssoToken"

The value is the SSO token ID string for the subject, returned for example on successful authentication as described in, "Authentication and Logout".

"jwt"

The value is a JWT string.

"claims"

The value is an object (map) of JWT claims to their values.

If you do not specify the subject, OpenAM uses the SSO token ID of the subject making the request.

"environment"

This optional field holds a map of keys to lists of values.

If you do not specify the environment, the default is an empty map.

The example below requests policy decisions for http://www.example.com/. The iPlanetDirectoryPro header sets the SSO token for a user who has access to perform the operation, and the subject takes the SSO token of the user who wants to access a resource.

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iPlanetDirectoryPro: AQIC5...NDU1*" \
 --data '{
    "resource": "http://www.example.com/",
    "subject": { "ssoToken": "AQIC5...zE4*" }
 }' \
 https://openam.example.com:8443/openam/json/policies?_action=evaluateTree
 [ {
  "resource" : "http://www.example.com/",
  "actions" : {
    "GET" : true,
    "OPTIONS" : true,
    "HEAD" : true
  },
  "attributes" : {
  },
  "advices" : {
  }
}, {
  "resource" : "http://www.example.com/*",
  "actions" : {
    "POST" : false,
    "PATCH" : false,
    "GET" : true,
    "DELETE" : true,
    "OPTIONS" : true,
    "HEAD" : true,
    "PUT" : true
  },
  "attributes" : {
    "myStaticAttr" : [ "myStaticValue" ]
  },
  "advices" : {
  }
}, {
  "resource" : "http://www.example.com/*?*",
  "actions" : {
    "POST" : false,
    "PATCH" : false,
    "GET" : false,
    "DELETE" : false,
    "OPTIONS" : true,
    "HEAD" : false,
    "PUT" : false
  },
  "attributes" : {
  },
  "advices" : {
    "AuthLevelConditionAdvice" : [ "3" ]
  }
} ]

Notice that OpenAM returns decisions not only for the specified resource, but also for matching resource names in the tree whose root is the specified resource.

In the JSON list of decisions returned for each resource, OpenAM includes these fields.

"resource"

A resource name whose root is the resource specified in the request.

The decisions returned are not guaranteed to be in the same order as the resources were requested.

"actions"

A map of action name keys to Boolean values that indicate whether the action is allowed (true) or denied (false) for the specified resource.

In the example, for matching resources with a query string only HTTP OPTIONS is allowed according to the policies configured.

"attributes"

A map of attribute names to their values, if any response attributes are returned according to applicable policies.

In the example, the policy that applies to http://www.example.com:80/* causes a static attribute to be returned.

"advices"

A map of advice names to their values, if any advice is returned according to applicable policies.

The "advices" field can provide hints regarding what OpenAM needs to take the authorization decision.

In the example, the policy that applies to resources with a query string requests that the subject be authenticated at an authentication level of at least 3.

Notice that with the "advices" field present, no "advices" appear in the JSON response.

{
    "advices": {
        "AuthLevelConditionAdvice": [ "3" ]
    }
}

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Managing Resource Types

This section describes the process of using the OpenAM REST API for managing resource types, which define a template for the resources that policies apply to, and the actions associated with those resources.

For information on creating resource types by using the OpenAM console, see "OpenAM Resource Types, Policy Sets, and Policies" in the Administration Guide. OpenAM provides the resourcetypes REST endpoint for the following:

Resource types are realm specific, hence the URI for the resource types API can contain a realm component, such as /json{/realm}/resourcetypes. If the realm is not specified in the URI, the top level realm is used.

Resource types are represented in JSON and take the following form. Resource types are built from standard JSON objects and values (strings, numbers, objects, sets, arrays, true, false, and null). Each resource type has a unique, system-generated UUID, which must be used when modifying existing resource types. Renaming a resource type will not affect the UUID.

{
    "uuid": "12345a67-8f0b-123c-45de-6fab78cd01e2",
    "name": "URL",
    "description": "The built-in URL Resource Type available to OpenAM Policies.",
    "patterns": [
        "*://*:*/*?*",
        "*://*:*/*"
    ],
    "actions": {
        "POST": true,
        "PATCH": true,
        "GET": true,
        "DELETE": true,
        "OPTIONS": true,
        "HEAD": true,
        "PUT": true
    },
    "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1422892465848,
    "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1422892465848
}

The values for the fields shown in the description are explained below:

"uuid"

String matching the unique identifier OpenAM generated for the resource type when created.

"name"

The name provided for the resource type.

"description"

An optional text string to help identify the resource type.

"patterns"

An array of resource patterns specifying individual URLs or resource names to protect.

For more information on patterns in resource types and policies, see "Specifying Resource Patterns with Wildcards" in the Administration Guide

"actions"

Set of string action names, each set to a boolean indicating whether the action is allowed.

"createdBy"

A string containing the universal identifier DN of the subject that created the resource type.

"creationDate"

An integer containing the creation date and time, in ISO 8601 format.

"lastModifiedBy"

A string containing the universal identifier DN of the subject that most recently updated the resource type.

If the resource type has not been modified since it was created, this will be the same value as createdBy.

"lastModifiedDate"

An string containing the last modified date and time, in ISO 8601 format.

If the resource type has not been modified since it was created, this will be the same value as creationDate.

Querying Resource Types

To list all the resource types in a realm, perform an HTTP GET to the /json{/realm}/resourcetypes endpoint, with a _queryFilter parameter set to true.

If the realm is not specified in the URL, OpenAM returns resource types in the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/myrealm/resourcetypes?_queryFilter=true
{
    "result": [
    {
        "uuid": "12345a67-8f0b-123c-45de-6fab78cd01e3",
        "name": "LIGHTS",
        "description": "",
        "patterns": [
            "light://*/*"
        ],
        "actions": {
            "switch_off": true,
            "switch_on": true
        },
        "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
        "creationDate": 1431013059131,
        "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
        "lastModifiedDate": 1431013069803
    }
    ],
    "resultCount": 1,
    "pagedResultsCookie": null,
    "remainingPagedResults": 0
}

Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

Supported _queryFilter Fields and Operators
Field Supported Operators

uuid

Equals (eq), Contains (co), Starts with (sw)

name

Equals (eq), Contains (co), Starts with (sw)

description

Equals (eq), Contains (co), Starts with (sw)

patterns

Equals (eq), Contains (co), Starts with (sw)

actions

Equals (eq), Contains (co), Starts with (sw)

Reading a Specific Resource Type

To read an individual resource types in a realm, perform an HTTP GET to the /json{/realm}/resourcetypes endpoint, and specify the UUID in the URL.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/myrealm/resourcetypes/12345a67-8f0b-123c-45de-6fab78cd01e3
{
    "uuid": "12345a67-8f0b-123c-45de-6fab78cd01e3",
    "name": "LIGHTS",
    "description": "",
    "patterns": [
        "light://*/*"
    ],
    "actions": {
        "switch_off": true,
        "switch_on": true
    },
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1431013059131,
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1431013069803
}
Creating a Resource Type

To create a resource type in a realm, perform an HTTP POST to the /json{/realm}/resourcetypes endpoint, with an _action parameter set to create. Include a JSON representation of the resource type in the POST data.

If the realm is not specified in the URL, OpenAM creates the resource type in the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

Do not use special characters within resource type, policy, or policy set names (for example, "my+resource+type") when using the console or REST endpoints. Using the special characters listed below causes OpenAM to return a 400 Bad Request error. The special characters are: double quotes ("), plus sign (+), comma (,), less than (<), equals (=), greater than (>), backslash (\), forward slash (/), semicolon (;), and null (\u0000).

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: AQIC5..." \
--data '{
    "name": "My Resource Type",
    "actions": {
        "LEFT": true,
        "RIGHT": true,
        "UP": true,
        "DOWN": true
    },
    "patterns": [
        "http://device/location/*"
    ]
}' \
https://openam.example.com:8443/openam/json/myrealm/resourcetypes/?_action=create
{
    "uuid": "12345a67-8f0b-123c-45de-6fab78cd01e4",
    "name": "My Resource Type",
    "description": null,
    "patterns": [
        "http://device/location/*"
    ],
    "actions": {
        "RIGHT": true,
        "DOWN": true,
        "UP": true,
        "LEFT": true
    },
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1431099940616,
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1431099940616
}
Updating a Resource Type

To update an individual resource type in a realm, perform an HTTP PUT to the /json{/realm}/resourcetypes endpoint, and specify the UUID in both the URL and the PUT body. Include a JSON representation of the updated resource type in the PUT data, alongside the UUID.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

Do not use special characters within resource type, policy, or policy set names (for example, "my+resource+type") when using the console or REST endpoints. Using the special characters listed below causes OpenAM to return a 400 Bad Request error. The special characters are: double quotes ("), plus sign (+), comma (,), less than (<), equals (=), greater than (>), backslash (\), forward slash (/), semicolon (;), and null (\u0000).

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
--request PUT \
--header "Content-Type: application/json" \
--data '{
    "uuid": "12345a67-8f0b-123c-45de-6fab78cd01e4",
    "name": "My Updated Resource Type",
    "actions": {
        "LEFT": false,
        "RIGHT": false,
        "UP": false,
        "DOWN": false
    },
    "patterns": [
        "http://device/location/*"
    ]
}' \
https://openam.example.com:8443/openam/json/myrealm/resourcetypes/12345a67-8f0b-123c-45de-6fab78cd01e4
{
    "uuid": "12345a67-8f0b-123c-45de-6fab78cd01e4",
    "name": "My Updated Resource Type",
    "description": null,
    "patterns": [
        "http://device/location/*"
    ],
    "actions": {
        "RIGHT": false,
        "DOWN": false,
        "UP": false,
        "LEFT": false
    },
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1431099940616,
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1431101016427
}
Deleting a Specific Resource Type

To delete an individual resource types in a realm, perform an HTTP DELETE to the /json{/realm}/resourcetypes endpoint, and specify the UUID in the URL.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--request DELETE \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/myrealm/resourcetypes/12345a67-8f0b-123c-45de-6fab78cd01e4
{}

You can only delete resource types that are not being used by a policy set or policy. Trying to delete a resource type that is in use will return an HTTP 409 Conflict status code, with a message such as:

{
    "code": 409,
    "reason": "Conflict",
    "message": "Unable to remove resource type 12345a67-8f0b-123c-45de-6fab78cd01e4 because it is
                referenced in the policy model."
}

Remove the resource type from any associated policy sets or policies to be able to delete it.

Managing Application Types

Application types act as templates for policy sets, and define how to compare resources and index policies. OpenAM provides a default application type that represents web resources called iPlanetAMWebAgentService. OpenAM policy agents use a default policy set that is based on this type, which is also called iPlanetAMWebAgentService. OpenAM provides the applicationtypes REST endpoint for the following:

Applications types are server-wide, and do not differ by realm. Hence the URI for the application types API does not contain a realm component, but is /json/applicationtypes.

Application type resources are represented in JSON and take the following form. Application type resources are built from standard JSON objects and values (strings, numbers, objects, arrays, true, false, and null).

{
    "name": "iPlanetAMWebAgentService",
    "actions": {
        "POST": true,
        "PATCH": true,
        "GET": true,
        "DELETE": true,
        "OPTIONS": true,
        "PUT": true,
        "HEAD": true
    },
    "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
    "saveIndex": "org.forgerock.openam.entitlement.indextree.TreeSaveIndex",
    "searchIndex": "org.forgerock.openam.entitlement.indextree.TreeSearchIndex",
    "applicationClassName": "com.sun.identity.entitlement.Application"
}

The values for the fields shown in the description are explained below:

"name"

The name provided for the application type.

"actions"

Set of string action names, each set to a boolean indicating whether the action is allowed.

"resourceComparator"

Class name of the resource comparator implementation used in the context of this application type.

The following implementations are available:

  • "com.sun.identity.entitlement.ExactMatchResourceName"

  • "com.sun.identity.entitlement.PrefixResourceName"

  • "com.sun.identity.entitlement.RegExResourceName"

  • "com.sun.identity.entitlement.URLResourceName"

"saveIndex"

Class name of the implementation for creating indexes for resource names, such as "com.sun.identity.entitlement.util.ResourceNameIndexGenerator" for URL resource names.

"searchIndex"

Class name of the implementation for searching indexes for resource names, such as "com.sun.identity.entitlement.util.ResourceNameSplitter" for URL resource names.

"applicationClassName"

Class name of the application type implementation, such as "com.sun.identity.entitlement.Application".

Querying Application Types

To list all application types, perform an HTTP GET to the /json/applicationtypes endpoint, with a _queryFilter parameter set to true.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/applicationtypes?_queryFilter=true
{
    "result" : [ ... application types ... ],
    "resultCount" : 8,
    "pagedResultsCookie" : null,
    "remainingPagedResults" : -1
}

Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

Reading a Specific Application Type

To read an individual application type, perform an HTTP GET to the /json/applicationtypes endpoint, and specify the application type name in the URL.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/applicationtypes/iPlanetAMWebAgentService
{
    "name": "iPlanetAMWebAgentService",
    "actions": {
        "POST": true,
        "PATCH": true,
        "GET": true,
        "DELETE": true,
        "OPTIONS": true,
        "PUT": true,
        "HEAD": true
    },
    "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
    "saveIndex": "org.forgerock.openam.entitlement.indextree.TreeSaveIndex",
    "searchIndex": "org.forgerock.openam.entitlement.indextree.TreeSearchIndex",
    "applicationClassName": "com.sun.identity.entitlement.Application"
}

Managing Policy Sets

This section describes the process of using the OpenAM REST API for managing policy sets.

Policy set definitions set constraints for defining policies. The default built-in policy set is called iPlanetAMWebAgentService, which OpenAM policy agents use to allow policy management through the console.

For information on creating policy sets by using the OpenAM console, see "OpenAM Resource Types, Policy Sets, and Policies" in the Administration Guide. OpenAM provides the applications REST endpoint for the following:

Policy sets are realm specific, hence the URI for the policy set API can contain a realm component, such as /json{/realm}/applications. If the realm is not specified in the URI, the top level realm is used.

Policy sets are represented in JSON and take the following form. Policy sets are built from standard JSON objects and values (strings, numbers, objects, arrays, true, false, and null).

{
    "creationDate": 1431351677264,
    "lastModifiedDate": 1431351677264,
    "conditions": [
        "AuthenticateToService",
        "Script",
        "AuthScheme",
        "IPv6",
        "SimpleTime",
        "OAuth2Scope",
        "IPv4",
        "AuthenticateToRealm",
        "OR",
        "AMIdentityMembership",
        "LDAPFilter",
        "AuthLevel",
        "SessionProperty",
        "LEAuthLevel",
        "Session",
        "NOT",
        "AND",
        "ResourceEnvIP"
    ],
    "applicationType": "iPlanetAMWebAgentService",
    "subjects": [
        "JwtClaim",
        "AuthenticatedUsers",
        "Identity",
        "NOT",
        "AND",
        "NONE",
        "OR"
    ],
    "entitlementCombiner": "DenyOverride",
    "saveIndex": null,
    "searchIndex": null,
    "resourceComparator": null,
    "resourceTypeUuids": [
        "12345a67-8f0b-123c-45de-6fab78cd01e4"
    ],
    "attributeNames": [ ],
    "editable": true,
    "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "description": "The built-in Application used by OpenAM Policy Agents.",
    "realm": "/",
    "name": "iPlanetAMWebAgentService"
}

The values for the fields shown in the description are explained below:

"conditions"

Condition types allowed in the context of this policy set.

For information on condition types, see "Managing Policies" and "Managing Environment Condition Types".

"applicationType"

Name of the application type used as a template for this policy set.

"subjects"

Subject types allowed in the context of this policy set.

For information on subject types, see "Managing Policies" and "Managing Subject Condition Types".

"entitlementCombiner"

Name of the decision combiner, such as "DenyOverride".

For more on decision combiners, see "Managing Decision Combiners".

"saveIndex"

Class name of the implementation for creating indexes for resource names, such as "com.sun.identity.entitlement.util.ResourceNameIndexGenerator" for URL resource names.

"searchIndex"

Class name of the implementation for searching indexes for resource names, such as "com.sun.identity.entitlement.util.ResourceNameSplitter" for URL resource names.

"resourceComparator"

Class name of the resource comparator implementation used in the context of this policy set.

The following implementations are available:

  • "com.sun.identity.entitlement.ExactMatchResourceName"

  • "com.sun.identity.entitlement.PrefixResourceName"

  • "com.sun.identity.entitlement.RegExResourceName"

  • "com.sun.identity.entitlement.URLResourceName"

"resourceTypeUuids"

A list of the UUIDs of the resource types associated with the policy set.

"attributeNames"

A list of attribute names such as cn. The list is used to aid policy indexing and lookup.

"description"

String describing the policy set.

"realm"

Name of the realm where this policy set is defined. You must specify the realm in the policy set JSON even though it can be derived from the URL that is used when creating the policy set.

"name"

String matching the name in the URL used when creating the policy set by HTTP PUT or in the body when creating the policy set by HTTP POST.

"createdBy"

A string containing the universal identifier DN of the subject that created the policy set.

"creationDate"

An integer containing the creation date and time, in number of seconds since the Unix epoch (1970-01-01T00:00:00Z).

"lastModifiedBy"

A string containing the universal identifier DN of the subject that most recently updated the policy set.

If the policy set has not been modified since it was created, this will be the same value as createdBy.

"lastModifiedDate"

An integer containing the last modified date and time, in number of seconds since the Unix epoch (1970-01-01T00:00:00Z).

If the policy set has not been modified since it was created, this will be the same value as creationDate.

Querying Policy Sets

To list all the policy sets in a realm, perform an HTTP GET to the /json{/realm}/applications endpoint, with a _queryFilter parameter set to true.

If the realm is not specified in the URL, OpenAM returns policy sets in the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/applications?_queryFilter=true
{
 "result": [
 {
   "_id": "iPlanetAMWebAgentService",
   "name": "iPlanetAMWebAgentService",
   "displayName": "Default Policy Set",
   "subjects": [
     "NOT",
     "OR",
     "JwtClaim",
     "AuthenticatedUsers",
     "AND",
     "Identity",
     "NONE"
   ],
   "saveIndex": null,
   "searchIndex": null,
   "entitlementCombiner": "DenyOverride",
   "resourceComparator": null,
   "attributeNames": [
   ],
   "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
   "editable": true,
   "resourceTypeUuids": [
     "76656a38-5f8e-401b-83aa-4ccb74ce88d2"
   ],
   "creationDate": 1480651214923,
   "lastModifiedDate": 1480651214923,
   "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
   "description": "The built-in Application used by OpenAM Policy Agents.",
   "applicationType": "iPlanetAMWebAgentService",
   "conditions": [
     "LEAuthLevel",
     "Script",
     "AuthenticateToService",
     "SimpleTime",
     "AMIdentityMembership",
     "OR",
     "IPv6",
     "IPv4",
     "SessionProperty",
     "AuthScheme",
     "AuthLevel",
     "NOT",
     "AuthenticateToRealm",
     "AND",
     "ResourceEnvIP",
     "LDAPFilter",
     "OAuth2Scope",
     "Session"
   ]
 },
 {
   "_id": "sunAMDelegationService",
   "name": "sunAMDelegationService",
   "displayName": "Delegation Policy Set",
   "subjects": [
     "NOT",
     "OR",
     "AuthenticatedUsers",
     "AND",
     "Identity"
   ],
   "saveIndex": null,
   "searchIndex": null,
   "entitlementCombiner": "DenyOverride",
   "resourceComparator": null,
   "attributeNames": [
   ],
   "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
   "editable": true,
   "resourceTypeUuids": [
     "20a13582-1f32-4f83-905f-f71ff4e2e00d"
   ],
   "creationDate": 1480651214933,
   "lastModifiedDate": 1480651214933,
   "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
   "description": null,
   "applicationType": "sunAMDelegationService",
   "conditions": [
   ]
 }
 ],
 "resultCount": 2,
 "pagedResultsCookie": null,
 "totalPagedResultsPolicy": "NONE",
 "totalPagedResults": -1,
 "remainingPagedResults": 0
}

Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

Supported _queryFilter Fields and Operators
Field Supported Operators

name

Equals (eq)

description

Equals (eq)

createdBy

Equals (eq)

creationDate

Equals (eq), Greater than or equal to (ge), Greater than (gt), Less than or equal to (le), Less than (lt)

The implementation of eq for this date field does not use regular expression pattern matching.

lastModifiedBy

Equals (eq)

lastModifiedDate

Equals (eq), Greater than or equal to (ge), Greater than (gt), Less than or equal to (le), Less than (lt)

The implementation of eq for this date field does not use regular expression pattern matching.

Reading a Specific Policy Set

To read an individual policy set in a realm, perform an HTTP GET to the /json{/realm}/applications endpoint, and specify the policy set name in the URL.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/applications/mypolicyset
{
    "creationDate": 1431360678810,
    "lastModifiedDate": 1431360678810,
    "conditions": [
        "AuthenticateToService",
        "AuthScheme",
        "IPv6",
        "SimpleTime",
        "OAuth2Scope",
        "IPv4",
        "AuthenticateToRealm",
        "OR",
        "AMIdentityMembership",
        "LDAPFilter",
        "SessionProperty",
        "AuthLevel",
        "LEAuthLevel",
        "Session",
        "NOT",
        "AND",
        "ResourceEnvIP"
    ],
    "applicationType": "iPlanetAMWebAgentService",
    "subjects": [
        "JwtClaim",
        "AuthenticatedUsers",
        "Identity",
        "NOT",
        "AND",
        "OR"
    ],
    "entitlementCombiner": "DenyOverride",
    "saveIndex": null,
    "searchIndex": null,
    "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
    "resourceTypeUuids": [
        "12345a67-8f0b-123c-45de-6fab78cd01e2"
    ],
    "attributeNames": [ ],
    "editable": true,
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "description": "My example policy set.",
    "realm": "/",
    "name": "mypolicyset"
}

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Creating Policy Sets

To create a policy set in a realm, perform an HTTP POST to the /json{/realm}/applications endpoint, with an _action parameter set to create. Include a JSON representation of the policy set in the POST data.

If the realm is not specified in the URL, OpenAM creates the policy set in the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

Do not use special characters within resource type, policy, or policy set names (for example, "my+resource+type") when using the console or REST endpoints. Using the special characters listed below causes OpenAM to return a 400 Bad Request error. The special characters are: double quotes ("), plus sign (+), comma (,), less than (<), equals (=), greater than (>), backslash (\), forward slash (/), semicolon (;), and null (\u0000).

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: AQIC5..." \
--data '{
    "name": "mypolicyset",
    "resourceTypeUuids": [
        "12345a67-8f0b-123c-45de-6fab78cd01e2"
    ],
    "realm": "/",
    "conditions": [
        "AND",
        "OR",
        "NOT",
        "AMIdentityMembership",
        "AuthLevel",
        "AuthScheme",
        "AuthenticateToRealm",
        "AuthenticateToService",
        "IPv4",
        "IPv6",
        "LDAPFilter",
        "LEAuthLevel",
        "OAuth2Scope",
        "ResourceEnvIP",
        "Session",
        "SessionProperty",
        "SimpleTime"
    ],
    "applicationType": "iPlanetAMWebAgentService",
    "description": "My example policy set.",
    "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
    "subjects": [
        "AND",
        "OR",
        "NOT",
        "AuthenticatedUsers",
        "Identity",
        "JwtClaim"
    ],
    "entitlementCombiner": "DenyOverride",
    "saveIndex": null,
    "searchIndex": null,
    "attributeNames": []
}' \
https://openam.example.com:8443/openam/json/applications/?_action=create
{
    "creationDate": 1431360678810,
    "lastModifiedDate": 1431360678810,
    "conditions": [
        "AuthenticateToService",
        "AuthScheme",
        "IPv6",
        "SimpleTime",
        "OAuth2Scope",
        "IPv4",
        "AuthenticateToRealm",
        "OR",
        "AMIdentityMembership",
        "LDAPFilter",
        "SessionProperty",
        "AuthLevel",
        "LEAuthLevel",
        "Session",
        "NOT",
        "AND",
        "ResourceEnvIP"
    ],
    "applicationType": "iPlanetAMWebAgentService",
    "subjects": [
        "JwtClaim",
        "AuthenticatedUsers",
        "Identity",
        "NOT",
        "AND",
        "OR"
    ],
    "entitlementCombiner": "DenyOverride",
    "saveIndex": null,
    "searchIndex": null,
    "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
    "resourceTypeUuids": [
        "12345a67-8f0b-123c-45de-6fab78cd01e2"
    ],
    "attributeNames": [ ],
    "editable": true,
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "description": "My example policy set.",
    "realm": "/",
    "name": "mypolicyset"
}

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Updating Policy Sets

To update an individual policy set in a realm, perform an HTTP PUT to the /json{/realm}/applications endpoint, and specify the policy set name in the URL. Include a JSON representation of the updated policy set in the PUT data.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

Do not use special characters within resource type, policy, or policy set names (for example, "my+resource+type") when using the console or REST endpoints. Using the special characters listed below causes OpenAM to return a 400 Bad Request error. The special characters are: double quotes ("), plus sign (+), comma (,), less than (<), equals (=), greater than (>), backslash (\), forward slash (/), semicolon (;), and null (\u0000).

$ curl \
--request PUT \
--header "iPlanetDirectoryPro: AQIC5..." \
--header "Content-Type: application/json" \
--data '{
    "name": "myupdatedpolicyset",
    "description": "My updated policy set - new name and fewer allowable conditions/subjects.",
    "conditions": [
        "NOT",
        "SimpleTime"
    ],
    "subjects": [
        "AND",
        "OR",
        "NOT",
        "AuthenticatedUsers",
        "Identity"
    ],
    "applicationType": "iPlanetAMWebAgentService",
    "entitlementCombiner": "DenyOverride",
    "resourceTypeUuids": [
        "76656a38-5f8e-401b-83aa-4ccb74ce88d2"
    ]
}' \
https://openam.example.com:8443/openam/json/applications/mypolicyset
{
    "creationDate": 1431362370739,
    "lastModifiedDate": 1431362390817,
    "conditions": [
        "NOT",
        "SimpleTime"
    ],
    "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
    "resourceTypeUuids": [
        "76656a38-5f8e-401b-83aa-4ccb74ce88d2"
    ],
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "applicationType": "iPlanetAMWebAgentService",
    "subjects": [
        "AuthenticatedUsers",
        "Identity",
        "NOT",
        "AND",
        "OR"
    ],
    "entitlementCombiner": "DenyOverride",
    "saveIndex": null,
    "searchIndex": null,
    "attributeNames": [ ],
    "editable": true,
    "description": "My updated policy set - new name and fewer allowable conditions/subjects.",
    "realm": "/",
    "name": "myupdatedpolicyset"
}

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Deleting Policy Sets

To delete an individual policy set in a realm, perform an HTTP DELETE to the /json{/realm}/applications endpoint, and specify the policy set name in the URL.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
  --request DELETE \
  --header "iPlanetDirectoryPro: AQIC5..." \
  https://openam.example.com:8443/openam/json/applications/myupdatedpolicyset
{}

Managing Policies

This section describes the process of using the OpenAM REST API for managing policies.

For information on creating policies by using the OpenAM console, see "OpenAM Resource Types, Policy Sets, and Policies" in the Administration Guide. OpenAM provides the policies REST endpoint for the following:

Policies are realm specific, hence the URI for the policies API can contain a realm component, such as /json{/realm}/policies. If the realm is not specified in the URI, the top level realm is used.

Policy resources are represented in JSON and take the following form. Policy resources are built from standard JSON objects and values (strings, numbers, objects, arrays, true, false, and null).

{
    "name": "mypolicy",
    "active": true,
    "description": "My Policy.",
    "applicationName": "iPlanetAMWebAgentService",
    "actionValues": {
        "POST": true,
        "GET": true
    },
    "resources": [
        "http://www.example.com:80/*",
        "http://www.example.com:80/*?*"
    ],
    "subject": {
        "type": "AuthenticatedUsers"
    },
    "condition": {
        "type": "SimpleTime",
        "startTime": "09:00",
        "endTime": "17:00",
        "startDay": "mon",
        "endDay": "fri",
        "enforcementTimeZone": "GMT"
    },
    "resourceTypeUuid": "76656a38-5f8e-401b-83aa-4ccb74ce88d2",
    "resourceAttributes": [
        {
            "type": "User",
            "propertyName": "givenName",
            "propertyValues": [ ]
        }
    ],
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": "2015-05-11T17:39:09.393Z",
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": "2015-05-11T17:37:24.556Z"
}

The values for the fields shown in the example are explained below:

"name"

String matching the name in the URL used when creating the policy by HTTP PUT or in the body when creating the policy by HTTP POST.

"active"

Boolean indicating whether OpenAM considers the policy active for evaluation purposes, defaults to false.

"description"

String describing the policy.

"resources"

List of the resource name pattern strings to which the policy applies. Must conform to the pattern templates provided by the associated resource type.

"applicationName"

String containing the policy set name, such as "iPlanetAMWebAgentService", or "mypolicyset".

"actionValues"

Set of string action names, each set to a boolean indicating whether the action is allowed. Chosen from the available actions provided by the associated resource type.

Action values can also be expressed as numeric values. When using numeric values, use the value 0 for false and use any non-zero numeric value for true.

"subject"

Specifies the subject conditions to which the policy applies, where subjects can be combined by using the built-in types "AND", "OR", and "NOT", and where subject implementations are pluggable.

Subjects are shown as JSON objects with "type" set to the name of the implementation (using a short name for all registered subject implementations), and also other fields depending on the implementation. The subject types registered by default include the following:

  • "AuthenticatedUsers", meaning any user that has successfully authenticated to OpenAM.

    {
        "type": "AuthenticatedUsers"
    }

    The AuthenticatedUsers subject condition does not take into account the realm to which a user authenticated. Any user that has authenticated successfully to any realm passes this subject condition. To test whether a user has authenticated successfully to a specific realm, also add the AuthenticateToRealm environment condition.

  • "Identity" to specify one or more users from an OpenAM identity repository:

    {
       "type": "Identity",
       "subjectValues": [
           "uid=scarter,ou=People,dc=example,dc=com",
           "uid=ahall,ou=People,dc=example,dc=com"
       ]
    }

    You can also use the "Identity" subject type to specify one or more groups from an identity repository:

    {
        "type": "Identity",
        "subjectValues": [
            "cn=HR Managers,ou=Groups,dc=example,dc=com"
        ]
    }
  • "JwtClaim" to specify a claim in a user’s JSON web token (JWT).

    {
        "type": "JwtClaim",
        "claimName": "sub",
        "claimValue": "scarter"
    }
  • "NONE", meaning never match any subject. The result is not that access is denied, but rather that the policy itself does not match and therefore cannot be evaluated in order to allow access.

The following example defines the subject either as the user Sam Carter from an OpenAM identity repository, or as a user with a JWT claim with a subject claim with the value scarter:

+

"subject": {
    "type": "OR",
    "subjects": [
       {
           "type": "Identity",
           "subjectValues": [
               "uid=scarter,ou=People,dc=example,dc=com"
           ]
       },
       {
           "type": "JwtClaim",
           "claimName": "sub",
           "claimValue": "scarter"
       }
   ]
}

+ To read a single subject type description, or to list all the available subject types, see "Managing Subject Condition Types".

"condition"

Specifies environment conditions, where conditions can be combined by using the built-in types "AND", "OR", and "NOT", and where condition implementations are pluggable.

Conditions are shown as JSON objects with "type" set to the name of the implementation (using a short name for all registered condition implementations), and also other fields depending on the implementation. The condition types registered by default include the following.

  • "AMIdentityMembership" to specify a list of OpenAM users and groups.

    {
        "type": "AMIdentityMembership",
        "amIdentityName": [
            "id=scarter,ou=People,dc=example,dc=com"
        ]
    }
  • "AuthLevel" to specify the authentication level.

    {
        "type": "AuthLevel",
        "authLevel": 2
    }
  • "AuthScheme" to specify the authentication module used to authenticate and the policy set name, and to set a timeout for authentication.

    {
        "type": "AuthScheme",
        "authScheme": [
            "DataStore"
        ],
        "applicationName": "iPlanetAMWebAgentService",
        "applicationIdleTimeout": 10
    }
  • "AuthenticateToRealm" to specify the realm to which the user authenticated.

    {
        "type": "AuthenticateToRealm",
        "authenticateToRealm": "MyRealm"
    }
  • "AuthenticateToService" to specify the authentication chain that was used to authenticate.

    {
        "type": "AuthenticateToService",
        "authenticateToService": "MyAuthnChain"
    }
  • "IPv4" or "IPv6" to specify an IP address range from which the request originated.

    {
       "type": "IPv4",
       "startIp": "127.0.0.1",
       "endIp": "127.0.0.255"
    }

    You can also use the "IPv4" and "IPv6" conditions with the "dnsName" field to specify domain names from which the request originated. Omit "startIp" and "endIp" when using "dnsName".

    {
        "type": "IPv4",
        "dnsName": [
            "*.example.com"
        ]
    }
  • "LDAPFilter" to specify an LDAP search filter. The user’s entry is tested against the search filter in the directory configured in the Policy Configuration Service.

    {
        "type": "LDAPFilter",
        "ldapFilter": "(&(c=US)(preferredLanguage=en-us))"
    }
  • "LEAuthLevel" to specify a maximum acceptable authentication level.

    {
        "type": "LEAuthLevel",
        "authLevel": 2
    }
  • "OAuth2Scope" to specify a list of attributes that must be present in the user profile.

    {
        "type": "OAuth2Scope",
        "requiredScopes": [
            "name",
            "address",
            "email"
        ]
    }
  • "ResourceEnvIP" to specify a complex condition such as whether the user is making a request from a given host and has authenticated with a given authentication level. For example:

    {
        "type": "ResourceEnvIP",
        "resourceEnvIPConditionValue": [
            "IF IP=[127.168.10.*] THEN authlevel=4"
        ]
    }

    Entries must take the form of one or more IF…​ELSE statements. If the IF statement is true, the THEN statement must also be true for the condition to be fulfilled. The IF statement can specify either IP to match the user’s IP address, or dnsName to match their DNS name. The IP address can be IPv4 or IPv6 format, or a hybrid of the two, and can include wildcard characters.

    The available parameters for the THEN statement are as follows:

    module

    The module that was used to authenticate the user, for example DataStore.

    service

    The authentication chain that was used to authenticate the user.

    authlevel

    The minimum required authentication level.

    role

    The role of the authenticated user.

    user

    The name of the authenticated user.

    redirectURL

    The URL from which the user was redirected.

    realm

    The realm to which the user authenticated.

  • "Session" to specify how long the user’s stateful or stateless session has been active, and to terminate the session if deemed too old, such that the user must authenticate again. Note that OpenAM terminates stateless sessions only if session blacklisting is in effect. For more information about session blacklisting, see "Session Termination" in the Administration Guide.

    {
        "type": "Session",
        "maxSessionTime": "10",
        "terminateSession": false
    }
  • "SessionProperty" to specify attributes set in the user’s stateful or stateless session.

    {
        "type": "SessionProperty",
        "ignoreValueCase": true,
        "properties": {
            "CharSet": [
                "UTF-8"
            ],
            "clientType": [
                "genericHTML"
            ]
        }
    }
  • "SimpleTime" to specify a time range, where "type" is the only required field.

    {
        "type": "SimpleTime",
        "startTime": "07:00",
        "endTime": "19:00",
        "startDay": "mon",
        "endDay": "fri",
        "startDate": "2015:01:01",
        "endDate": "2015:12:31",
        "enforcementTimeZone": "GMT+0:00"
    }

The following example defines the condition as neither Saturday or Sunday, nor certain client IP addresses.

+

{
    "type": "NOT",
    "condition": {
        "type": "OR",
        "conditions": [
            {
                "type": "SimpleTime",
                "startDay": "sat",
                "endDay": "sun",
                "enforcementTimeZone": "GMT+8:00"
            },
            {
                "type": "IPv4",
                "startIp": "192.168.0.1",
                "endIp": "192.168.0.255"
            }
        ]
    }
}

+ To read a single condition type description, or to list all the available condition types, see "Managing Environment Condition Types".

"resourceTypeUuid"

The UUIDs of the resource type associated with the policy.

"resourceAttributes"

List of attributes to return with decisions. These attributes are known as response attributes.

The response attribute provider is pluggable. The default implementation provides for statically defined attributes and for attributes retrieved from user profiles.

Attributes are shown as JSON objects with "type" set to the name of the implementation (by default either "Static" for statically defined attributes or "User" for attributes from the user profile), "propertyName" set to the attribute names. For static attributes, "propertyValues" holds the attribute values. For user attributes, "propertyValues" is not used; the property values are determined at evaluation time.

"createdBy"

A string containing the universal identifier DN of the subject that created the policy.

"creationDate"

An integer containing the creation date and time, in number of seconds since the Unix epoch (1970-01-01T00:00:00Z).

"lastModifiedBy"

A string containing the universal identifier DN of the subject that most recently updated the policy.

If the policy has not been modified since it was created, this will be the same value as createdBy.

"lastModifiedDate"

An integer containing the last modified date and time, in number of seconds since the Unix epoch (1970-01-01T00:00:00Z).

If the policy has not been modified since it was created, this will be the same value as creationDate.

Querying Policies

Use REST calls to list all the policies in a realm, or to find policies that explicitly apply to a given user or group, by using the procedures below:

To List All Policies in a Realm
  • To list all the policies in a realm, perform an HTTP GET to the /json{/realm}/policies endpoint, with an _queryFilter parameter set to true.

    If the realm is not specified in the URL, OpenAM returns policies in the top level realm.

    The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

    $ curl \
      --header "iPlanetDirectoryPro: AQIC5w..." \
      https://openam.example.com:8443/openam/json/myrealm/policies?_queryFilter=true
    
    {
        "result": [
            {
            "name": "example",
            "active": true,
            "description": "Example Policy",
            "applicationName": "iPlanetAMWebAgentService",
            "actionValues": {
                "POST": false,
                "GET": true
            },
            "resources": [
                "http://www.example.com:80/*",
                "http://www.example.com:80/*?*"
            ],
            "subject": {
                "type": "Identity",
                "subjectValues": [
                    "uid=demo,ou=People,dc=example,dc=com"
                ]
            },
            "resourceTypeUuid": "12345a67-8f0b-123c-45de-6fab78cd01e4",
            "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
            "lastModifiedDate": "2015-05-11T14:48:08.711Z",
            "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
            "creationDate": "2015-05-11T14:48:08.711Z"
            }
        ],
        "resultCount": 1,
        "pagedResultsCookie": null,
        "remainingPagedResults": 0
    }

    Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

    Supported _queryFilter Fields and Operators
    Field Supported Operators

    name

    Equals (eq)

    description

    Equals (eq)

    applicationName

    Equals (eq)

    createdBy

    Equals (eq)

    creationDate

    Equals (eq), Greater than or equal to (ge), Greater than (gt), Less than or equal to (le), Less than (lt)

    The implementation of eq for this date field does not use regular expression pattern matching.

    lastModifiedBy

    Equals (eq)

    lastModifiedDate

    Equals (eq), Greater than or equal to (ge), Greater than (gt), Less than or equal to (le), Less than (lt)

    The implementation of eq for this date field does not use regular expression pattern matching.

To Query Policies in a Realm by User or Group

You can query policies that explicitly reference a given subject by providing the universal ID (UID) of either a user or group. OpenAM returns any policies that explicitly apply to the user or group as part of a subject condition.

You can obtain the universal ID for a user or group by using REST. See "Reading Identities".

The following caveats apply to querying policies by user or group:

  • Group membership is not considered. For example, querying policies for a specific user will not return policies that only use groups in their subject conditions, even if the user is a member of any of those groups.

  • Wildcards are not supported, only exact matches.

  • Only policies with a subject condition type of Identity are queried—environment conditions are not queried. The Identity subject condition type is labelled as Users & Groups in the policy editor in the OpenAM console.

  • Policies with subject conditions that only contain the user or group in a logical NOT operator are not returned.

To query policies by user or group:

  • Perform an HTTP GET to the /json{/realm}/policies endpoint, with an _queryId parameter set to queryByIdentityUid, and a uid parameter containing the universal ID of the user or group:

    $ curl \
      --get \
      --header "iPlanetDirectoryPro: AQIC5w..." \
      --data "_queryId=queryByIdentityUid" \
      --data "uid=id=demo,ou=user,o=myrealm,ou=services,dc=openam,dc=forgerock,dc=org" \
      https://openam.example.com:8443/openam/json/myrealm/policies
     {
      "result" : [ {
        "name" : "mySubRealmPolicy",
        "active" : true,
        "description" : "",
        "resources" : [ "*://*:*/*?*", "*://*:*/*" ],
        "applicationName" : "iPlanetAMWebAgentService",
        "actionValues" : {
          "POST" : true,
          "PATCH" : true,
          "GET" : true,
          "DELETE" : true,
          "OPTIONS" : true,
          "PUT" : true,
          "HEAD" : true
        },
        "subject" : {
          "type" : "Identity",
          "subjectValues" :
          [
            "id=demo,ou=user,o=myrealm,ou=services,dc=openam,dc=forgerock,dc=org"
          ]
        },
        "resourceTypeUuid" : "76656a38-5f8e-401b-83aa-4ccb74ce88d2",
        "lastModifiedBy" : "id=amAdmin,ou=user,dc=openam,dc=forgerock,dc=org",
        "lastModifiedDate" : "2016-05-05T08:45:35.716Z",
        "createdBy" : "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
        "creationDate" : "2016-05-03T13:45:38.137Z"
      } ],
      "resultCount" : 1,
      "pagedResultsCookie" : null,
      "totalPagedResultsPolicy" : "NONE",
      "totalPagedResults" : -1,
      "remainingPagedResults" : 0
    }

    If the realm is not specified in the URL, OpenAM searches the top level realm.

    The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

Reading a Specific Policy

To read an individual policy in a realm, perform an HTTP GET to the /json{/realm}/policies endpoint, and specify the policy name in the URL.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/policies/example
{
    "result": [
        {
        "name": "example",
        "active": true,
        "description": "Example Policy",
        "applicationName": "iPlanetAMWebAgentService",
        "actionValues": {
            "POST": false,
            "GET": true
        },
        "resources": [
            "http://www.example.com:80/*",
            "http://www.example.com:80/*?*"
        ],
        "subject": {
            "type": "Identity",
            "subjectValues": [
                "uid=demo,ou=People,dc=example,dc=com"
            ]
        },
        "resourceTypeUuid": "12345a67-8f0b-123c-45de-6fab78cd01e4",
        "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
        "lastModifiedDate": "2015-05-11T14:48:08.711Z",
        "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
        "creationDate": "2015-05-11T14:48:08.711Z"
        }
    ],
    "resultCount": 1,
    "pagedResultsCookie": null,
    "remainingPagedResults": 0
}

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Creating Policies

To create a policy in a realm, perform an HTTP POST to the /json{/realm}/policies endpoint, with an _action parameter set to create. Include a JSON representation of the policy in the POST data.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

Do not use special characters within resource type, policy, or policy set names (for example, "my+resource+type") when using the console or REST endpoints. Using the special characters listed below causes OpenAM to return a 400 Bad Request error. The special characters are: double quotes ("), plus sign (+), comma (,), less than (<), equals (=), greater than (>), backslash (\), forward slash (/), semicolon (;), and null (\u0000).

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iPlanetDirectoryPro: AQIC5..." \
 --data '{
    "name": "mypolicy",
    "active": true,
    "description": "My Policy.",
    "applicationName": "iPlanetAMWebAgentService",
    "actionValues": {
        "POST": false,
        "GET": true
    },
    "resources": [
        "http://www.example.com:80/*",
        "http://www.example.com:80/*?*"
    ],
    "subject": {
        "type": "Identity",
        "subjectValues": [
            "uid=demo,ou=People,dc=example,dc=com"
        ]
    },
    "resourceTypeUuid": "12345a67-8f0b-123c-45de-6fab78cd01e4"
 }' \
 https://openam.example.com:8443/openam/json/policies?_action=create
 {
    "name": "mypolicy",
    "active": true,
    "description": "My Policy.",
    "applicationName": "iPlanetAMWebAgentService",
    "actionValues": {
        "POST": false,
        "GET": true
    },
    "resources": [
        "http://www.example.com:80/*",
        "http://www.example.com:80/*?*"
    ],
    "subject": {
        "type": "Identity",
        "subjectValues": [
            "uid=demo,ou=People,dc=example,dc=com"
        ]
    },
    "resourceTypeUuid": "12345a67-8f0b-123c-45de-6fab78cd01e4",
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": "2015-05-11T14:48:08.711Z",
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": "2015-05-11T14:48:08.711Z"
}

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Updating Policies

To update an individual policy in a realm, perform an HTTP PUT to the /json{/realm}/policies endpoint, and specify the policy name in the URL. Include a JSON representation of the updated policy in the PUT data.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

Do not use special characters within resource type, policy, or policy set names (for example, "my+resource+type") when using the console or REST endpoints. Using the special characters listed below causes OpenAM to return a 400 Bad Request error. The special characters are: double quotes ("), plus sign (+), comma (,), less than (<), equals (=), greater than (>), backslash (\), forward slash (/), semicolon (;), and null (\u0000).

$ curl \
 --request PUT \
 --header "iPlanetDirectoryPro: AQIC5w..." \
 --header "Content-Type: application/json" \
 --data '{
    "name": "myupdatedpolicy",
    "active": true,
    "description": "My Updated Policy.",
    "resources": [
        "http://www.example.com:80/*",
        "http://www.example.com:80/*?*"
    ],
    "actionValues": {
        "POST": true,
        "GET": true
    },
    "subject": {
        "type": "Identity",
        "subjectValues": [
            "uid=scarter,ou=People,dc=example,dc=com",
            "uid=bjenson,ou=People,dc=example,dc=com"
        ]
    },
    "resourceTypeUuid": "12345a67-8f0b-123c-45de-6fab78cd01e4"
}' \
 https://openam.example.com:8443/openam/json/policies/mypolicy
 {
    "name": "myupdatedpolicy",
    "active": true,
    "description": "My Updated Policy.",
    "applicationName": "iPlanetAMWebAgentService",
    "actionValues": {
        "POST": true,
        "GET": true
    },
    "resources": [
        "http://www.example.com:80/*",
        "http://www.example.com:80/*?*"
    ],
    "subject": {
        "type": "Identity",
        "subjectValues": [
            "uid=bjenson,ou=People,dc=example,dc=com",
            "uid=scarter,ou=People,dc=example,dc=com"
        ]
    },
    "resourceTypeUuid": "12345a67-8f0b-123c-45de-6fab78cd01e4",
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": "2015-05-11T17:26:59.116Z",
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": "2015-05-11T17:25:18.632Z"
}

You can use the query string parameters _prettyPrint=true to make the output easier to read, and _fields=field-name[,field-name…​] to limit the fields returned in the output.

Deleting Policies

To delete an individual policy in a realm, perform an HTTP DELETE to the /json{/realm}/policies endpoint, and specify the policy name in the URL.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
  --header "iPlanetDirectoryPro: AQIC5w..." \
  --request DELETE \
  https://openam.example.com:8443/openam/json/policies/myupdatedpolicy
{}
Copying and Moving Policies

You can copy or move an individual policy by performing an HTTP POST to the /json{/realm}/policies/policyName endpoint as follows:

  • Specify the _action=copy or _action=move URL parameter.

  • Specify the realm in which the input policy resides in the URL. If the realm is not specified in the URL, OpenAM copies or moves a policy from the top level realm.

  • Specify the policy to be copied or moved in the URL.

  • Specify the SSO token of an administrative user who has access to perform the operation in the iPlanetDirectoryPro header.

Specify JSON input data as follows:

JSON Input Data for Copying or Moving Individual Policies
Object Property Description

to

name

The name of the output policy.

Required unless you are copying or moving a policy to a different realm and you want the output policy to have the same name as the input policy.

to

application

The policy set in which to place the output policy.

Required when copying or moving a policy to a different policy set.

to

realm

The realm in which to place the output policy. If not specified, OpenAM copies or moves the policy within the realm identified in the URL.

Required when copying or moving a policy to a different realm.

to

resourceType

The UUID of the output policy’s resource type.

Required when copying or moving a policy to a different realm.

The follow example copies the policy myPolicy to myNewPolicy. The output policy is placed in the myRealm realm, in the same policy set as the input policy:

$ curl \
  --request POST \
  --header "Content-Type: application/json" \
  --header "iPlanetDirectoryPro: AQIC5w..." \
  --data '{
      "to": {
          "name": "myNewPolicy"
      }
  }' \
  https://openam.example.com:8443/openam/json/myRealm/policies/myPolicy?_action=copy
{
    "name":"myNewPolicy",
    "active":true,
    "description":"",
    "applicationName":"iPlanetAMWebAgentService",
    "actionValues":{},
    "resources":['"*://*:*/*"],
    "subject":{"type":"NONE"},
    "resourceTypeUuid":"d98e59c9-766a-4934-b5de-8a28a9edc158",
    "lastModifiedBy":"id=amadmin,ou=user,dc=example,dc=com",
    "lastModifiedDate":"2015-12-19T15:22:44.861Z",
    "createdBy":"id=amadmin,ou=user,dc=example,dc=com",
    "creationDate":"2015-12-19T15:22:44.861Z"
}

The following example moves a policy named myPolicy in the myRealm realm to myMovedPolicy in the myOtherRealm realm. The output policy is placed in the iPlanetAMWebAgentService policy set, which is the policy set in which the input policy is located.

The realm myOtherRealm must be configured as follows for the example to run successfully:

  • It must have a resource type that has the same resources as the resource type configured for the myPolicy policy.

  • It must have a policy set named iPlanetAMWebAgentService.

$ curl \
  --request POST \
  --header "Content-Type: application/json" \
  --header "iPlanetDirectoryPro: AQIC5w..." \
  --data '{
      "to": {
          "name": "myMovedPolicy",
          "realm": "/myOtherRealm",
          "resourceType: "616b3d02-7a8d-4422-b6a7-174f62afd065"
      }
  }' \
  https://openam.example.com:8443/openam/json/myRealm/policies/myPolicy?_action=move
{
    "name":"myMovedPolicy",
    "active":true,
    "description":"",
    "actionValues":{},
    "applicationName":"iPlanetAMWebAgentService",
    "resources":["*://*:*/*"],
    "subject":{"type":"NONE"},
    "resourceTypeUuid":"616b3d02-7a8d-4422-b6a7-174f62afd065",
    "lastModifiedBy":"id=amadmin,ou=user,dc=example,dc=com",
    "lastModifiedDate":"2015-12-21T19:32:59.502Z",
    "createdBy":"id=amadmin,ou=user,dc=example,dc=com",
    "creationDate":"2015-12-21T19:32:59.502Z"
 }

You can also copy and move multiple policies—all the policies in a policy set—in a single operation by performing an HTTP POST to the /json{/realm}/policies endpoint as follows:

  • Specify the _action=copy or _action=move URL parameter.

  • Specify the realm in which the input policies reside as part of the URL. If no realm is specified in the URL, OpenAM copies or moves policies within the top level realm.

  • Specify the SSO token of an administrative user who has access to perform the operation in the iPlanetDirectoryPro header.

Specify JSON input data as follows:

JSON Input Data for Copying or Moving Multiple Policies
Object Property Description

from

application

The policy set in which the input policies are located.

Required.

to

application

The policy set in which to store output policies.

Required when copying or moving policies to a different policy set.

to

realm

The realm in which to store output policies.

Required when copying or moving policies to a different realm.

to

namePostfix

A value appended to output policy names in order to prevent name clashes.

Required.

resourceTypeMapping

Varies; see Description

One or more resource types mappings, where the left side of the mapping specifies the UUID of a resource type used by the input policies and the right side of the mapping specifies the UUID of a resource type used by the output policies. The two resource types should have the same resource patterns.

Required when copying or moving policies to a different realm.

The following example copies all the policies in the iPlanetAMWebAgentService policy set in the myRealm realm to the iPlanetAMWebAgentService policy set in the myOtherRealm realm, appending the string -copy to the output policy names.

The realm myOtherRealm must be configured as follows for the example to run successfully:

  • It must have a resource type that maps to the ccb50c1a-206d-4946-9106-4164e8f2b35b resource type. The two resource types should have the same resource patterns.

  • It must have a policy set named iPlanetAMWebAgentService.

The JSON output shows that a single policy is copied. The policy myNewPolicy is copied to realm myOtherRealm. The copied policy receives the name myOtherRealm-copy:

$ curl \
  --request POST \
  --header "Content-Type: application/json" \
  --header "iPlanetDirectoryPro: AQIC5w..." \
  --data '{
      "from": {
          "application": "iPlanetAMWebAgentService"
      },
      "to": {
          "realm": "/myOtherRealm",
          "namePostfix": "-copy"
      },
      "resourceTypeMapping": {
          "ccb50c1a-206d-4946-9106-4164e8f2b35b": "616b3d02-7a8d-4422-b6a7-174f62afd065"
      }

  }' \
https://openam.example.com:8443/openam/json/myRealm/policies?_action=copy
{
    "name":"myNewPolicy-copy",
    "active":true,
    "description":"",
    "actionValues":{},
    "applicationName":"iPlanetAMWebAgentService",
    "resources":["*://*:*/*"],"subject":{"type":"NONE"},
    "resourceTypeUuid":"616b3d02-7a8d-4422-b6a7-174f62afd065",
    "lastModifiedBy":"id=amadmin,ou=user,dc=example,dc=com",
    "lastModifiedDate":"2015-12-21T20:01:42.410Z",
    "createdBy":"id=amadmin,ou=user,dc=example,dc=com",
    "creationDate":"2015-12-21T20:01:42.410Z"
}

Importing and Exporting XACML 3.0

OpenAM supports the ability to export policies to eXtensible Access Control Markup Language (XACML) 3.0-based formatted policy sets through its /xacml/policies REST endpoint. You can also import XACML 3.0 policy sets back into OpenAM by using the same endpoint. The endpoint’s functionally is identical to that of the ssoadm create-xacml and ssoadm list-xacml commands. For more information, see "Importing and Exporting Policies" in the Administration Guide

OpenAM can only import XACML 3.0 policy sets that were either created by an OpenAM instance, or that have had minor manual modifications, due to the reuse of some XACML 3.0 parameters for non-standard information.

When exporting OpenAM policies to XACML 3.0 policy sets, OpenAM maps its policies to XACML 3.0 policy elements. The mappings are as follows:

OpenAM Policies to XACML Mappings
OpenAM Policy XACML Policy

Policy Name

Policy ID

Description

Description

Current Time (yyyy.MM.dd.HH.mm.ss.SSS)

Version

xacml rule target

entitlement excluded resource names

Rule Deny Overrides

Rule Combining Algorithm ID

Any of:

  • Entitlement Subject

  • Resource Names

  • Policy Set Names

  • Action Values

Target

Any of:

  • Policy Set Name

  • Entitlement Name

  • Privilege Created By

  • Privilege Modified By

  • Privilege Creation Date

  • Privilege Last Modification Date

Variable Definitions

Single Level Permit/Deny Actions converted to Policy Rules

Rules

XACML obligation is not supported. Also, only one XACML match is defined for each privilege action, and only one XACML rule for each privilege action value.

Exporting from OpenAM to XACML

OpenAM supports exporting policies into XACML 3.0 format. OpenAM only exports a policy set that contains policy definitions. No other types can be included in the policy set, such as sub-policy sets or rules. The policy set mapping is as follows:

Policy Set Mappings
OpenAM XACML

Realm:<timestamp>(yyyy.MM.dd.HH.mm.ss.SSS)

PolicySet ID

Current Time (yyyy.MM.dd.HH.mm.ss.SSS)

Version

Deny Overrides

Policy Combining Algorithm ID

No targets defined

Target

The export service is accessible at the /xacml/policies endpoint using a HTTP GET request at the following endpoint for the root realm or a specific realm:

http://openam.example.com:8080/openam/xacml/policies
http://openam.example.com:8080/openam/xacml/{realm}/policies

where {realm} is the name of a specific realm

You can filter your XACML exports using query search filters. Note the following points about the search filters:

  • LDAP-based Searches. The search filters follow the standard guidelines for LDAP searches as they are applied to the entitlements index in the LDAP configuration backend, located at: ou=default,ou=OrganizationalConfig,ou=1.0,ou=sunEntitlementIndexes, ou=services,dc=openam,dc=forgerock,dc=org.

  • Search Filter Format. You can specify a single search filter or multiple filters in the HTTP URL parameters. The format for the search filter is as follows:

    [attribute name][operator][attribute value]

    If you specify multiple search filters, they are logically ANDed: the search results meet the criteria specified in all the search filters.

    XACML Export Search Filter Format
    Element Description

    Attribute Name

    The name of the attribute to be searched for. The only permissible values are: application (keyword for policy set), createdby, lastmodifiedby, creationdate, lastmodifieddate, name, description.

    Operator

    The type of comparison operation to perform.

    • = Equals (text)

    • < Less Than or Equal To (numerical)

    • > Greater Than or Equal To (numerical)

    Attribute Value

    The matching value. Asterisk wildcards are supported.

To Export Policies
  • Use the /xacml/policies endpoint to export the OpenAM entitlement policies into XACML 3.0 format. The following curl command exports the policies and returns the XACML response (truncated for display purposes).

    $ curl \
      --request GET \
      --header "iPlanetDirectoryPro: AQIC5..." \
      http://openam.example.com:8080/openam/xacml/policies
    
    
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <PolicySet xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17"
     PolicyCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-overrides"
     Version="2014.10.08.21.59.39.231" PolicySetId="/:2014.10.08.21.59.39.231">
     <Target/>
     <Policy RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:deny-overrides"
      Version="2014.10.08.18.01.03.626"
      PolicyId="Rockshop_Checkout_https://forgerock-rockshop.openrock.org:443/wp-login.php*?*">
      ...
To Export Policies with Search Filters
  1. Use the /xacml/policies endpoint to export the policies into XACML 3.0 format with a search filter. This command only exports policies that were created by "amadmin".

    $ curl \
      --request GET \
      --header "iPlanetDirectoryPro: AQIC5..." \
      http://openam.example.com:8080/openam/xacml/policies?filter=createdby=amadmin
  2. You can also specify more than one search filter by logically ANDing the filters as follows:

    $ curl \
      --request GET \
      --header "iPlanetDirectoryPro: AQIC5..." \
      http://openam.example.com:8080/openam/xacml/policies?filter=createdby=amadmin&
      filter=creationdate=135563832
Importing from XACML to OpenAM

OpenAM supports the import of XACML 3.0-based policy sets into OpenAM policies using the REST /xacml/policies endpoint. To test an import, OpenAM provides a dry-run feature that runs an import without saving the changes to the database. The dry-run feature provides a summary of the import so that you can troubleshoot any potential mismatches prior to the actual import.

You can import a XACML policy using an HTTP POST request for the root realm or a specific realm at the following endpoints:

http://openam.example.com:8080/openam/xacml/policies
http://openam.example.com:8080/openam/xacml/{realm}/policies

where {realm} is the name of a specific realm
To Import a XACML 3.0 Policy
  1. You can do a dry run using the dryrun=true query to test the import. The dry-run option outputs in JSON format and displays the status of each import policy, where "U" indicates "Updated"; "A" for "Added". The dry-run does not actually update to the database. When you are ready for an actual import, you need to re-run the command without the dryrun=true query.

    $ curl \
      --request POST \
      --header "Content-Type: application/xml" \
      --header "iPlanetDirectoryPro: AQIC5..." \
      --data @xacml-policy.xml \
      http://openam.example.com:8080/openam/xacml/policies?dryrun=true
    [
     {
       "status":"A",
       "name":"aNewPolicy"
     },
     {
       "status":"U",
       "name":"anExistingPolicy"
     },
     {
       "status":"U",
       "name":"anotherExistingPolicy"
     }
    ]
  2. Use the /xacml/policies endpoint to import a XACML policy:

    $ curl \
      --request POST \
      --header "Content-Type: application/xml" \
      --header "iPlanetDirectoryPro: AQIC5..." \
      --data @xacml-policy.xml \
      http://openam.example.com:8080/openam/xacml/policies

You can import a XACML policy into a realm as follows:

$ curl \
  --request POST \
  --header "Content-Type: application/xml" \
  --header "iPlanetDirectoryPro: AQIC5..." \
  --data @xacml-policy.xml \
  http://openam.example.com:8080/openam/xacml/{realm}/policies

Managing Environment Condition Types

Environment condition types describe the JSON representation of environment conditions that you can use in policy definitions. OpenAM provides the conditiontypes REST endpoint for the following:

Environment condition types are server-wide, and do not differ by realm. Hence the URI for the condition types API does not contain a realm component, but is /json/conditiontypes.

Environment condition types are represented in JSON and take the following form. Environment condition types are built from standard JSON objects and values (strings, numbers, objects, arrays, true, false, and null).

{
    "title": "IPv4",
    "logical": false,
    "config": {
        "type": "object",
        "properties": {
            "startIp": {
                "type": "string"
            },
            "endIp": {
                "type": "string"
            },
            "dnsName": {
                "type": "array",
                "items": {
                    "type": "string"
                }
            }
        }
    }
}

Notice that the environment condition type has a title, a "logical" field that indicates whether the type is a logical operator or takes a predicate, and a configuration specification. The configuration specification in this case indicates that an IPv4 environment condition has two properties, "startIp" and "endIp", that each take a single string value, and a third property, "dnsName," that takes an array of string values. In other words, a concrete IP environment condition specification without a DNS name constraint could be represented in a policy definition as in the following example:

{
   "type": "IPv4",
   "startIp": "127.0.0.1",
   "endIp": "127.0.0.255"
}

The configuration is what differs the most across environment condition types. The NOT condition, for example, takes a single condition object as the body of its configuration.

{
  "title" : "NOT",
  "logical" : true,
  "config" : {
    "type" : "object",
    "properties" : {
      "condition" : {
        "type" : "object",
        "properties" : {
        }
      }
    }
  }
}

The concrete NOT condition therefore takes the following form.

{
    "type": "NOT",
    "condition": {
        ...
    }
}

The OR condition takes an array of conditions.

{
  "title" : "OR",
  "logical" : true,
  "config" : {
    "type" : "object",
    "properties" : {
      "conditions" : {
        "type" : "array",
        "items" : {
          "type" : "any"
        }
      }
    }
  }
}

A corresponding concrete OR condition thus takes the following form.

{
    "type": "OR",
    "conditions": [
        {
            ...
        },
        {
            ...
        },
        ...
    ]
}
Querying Environment Condition Types

To list all environment condition types, perform an HTTP GET to the /json/conditiontypes endpoint, with a _queryFilter parameter set to true.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
 --header "iPlanetDirectoryPro: AQIC5..." \
 https://openam.example.com:8443/openam/json/conditiontypes?_queryFilter=true
 {
    "result" : [
        {
            "title": "IPv4",
            "logical": false,
            "config": {
                "type": "object",
                "properties": {
                    "startIp": {
                        "type": "string"
                    },
                    "endIp": {
                        "type": "string"
                    },
                    "dnsName": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        {
            "title": "NOT",
            "logical": true,
            "config": {
                "type": "object",
                "properties": {
                    "condition": {
                        "type": "object",
                        "properties": { }
                    }
                }
            }
        },
        {...},
        {...},
        {...}
    ],
    "resultCount" : 18,
    "pagedResultsCookie" : null,
    "remainingPagedResults" : 0
}

Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

Reading a Specific Environment Condition Type

To read an individual environment condition type, perform an HTTP GET to the /json/conditiontypes endpoint, and specify the environment condition type name in the URL.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
 --header "iPlanetDirectoryPro: AQIC5..." \
 https://openam.example.com:8443/openam/json/conditiontypes/IPv4
{
  "title" : "IPv4",
  "logical" : false,
  "config" : {
    "type" : "object",
    "properties" : {
      "startIp" : {
        "type" : "string"
      },
      "endIp" : {
        "type" : "string"
      },
      "dnsName" : {
        "type" : "array",
        "items" : {
          "type" : "string"
        }
      }
    }
  }
}

Managing Subject Condition Types

Subject condition types describe the JSON representation of subject conditions that you can use in policy definitions. OpenAM provides the subjecttypes REST endpoint for the following:

Environment condition types are server-wide, and do not differ by realm. Hence the URI for the condition types API does not contain a realm component, but is /json/subjecttypes.

Subject condition types are represented in JSON and take the following form. Subject condition types are built from standard JSON objects and values (strings, numbers, objects, arrays, true, false, and null).

{
    "title" : "Identity",
    "logical" : false,
    "config" : {
        "type" : "object",
        "properties" : {
            "subjectValues" : {
                "type" : "array",
                "items" : {
                    "type" : "string"
                }
            }
        }
    }
}

Notice that the subject type has a title, a "logical" field that indicates whether the type is a logical operator or takes a predicate, and a configuration specification. The configuration specification in this case indicates that an Identity subject condition has one property, "subjectValues", which takes an array of string values. In other words, a concrete Identity subject condition specification is represented in a policy definition as in the following example:

{
   "type": "Identity",
   "subjectValues": [
       "uid=scarter,ou=People,dc=example,dc=com"
   ]
}

The configuration is what differs the most across subject condition types. The AND condition, for example, takes an array of subject condition objects as the body of its configuration.

{
    "title" : "AND",
    "logical" : true,
    "config" : {
        "type" : "object",
        "properties" : {
            "subjects" : {
                "type" : "array",
                "items" : {
                    "type" : "any"
                }
            }
        }
    }
}

The concrete AND subject condition therefore takes the following form.

{
    "type": "AND",
    "subject": [
      {...},
      {...},
      {...},
      {...}
    ]
}
Querying Subject Condition Types

To list all environment condition types, perform an HTTP GET to the /json/subjecttypes endpoint, with a _queryFilter parameter set to true.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
  --header "iPlanetDirectoryPro: AQIC5..." \
  https://openam.example.com:8443/openam/json/subjecttypes?_queryFilter=true
  {
    "result" : [
        {
            "title": "JwtClaim",
            "logical": false,
            "config": {
                "type": "object",
                "properties": {
                    "claimName": {
                        "type": "string"
                    },
                    "claimValue": {
                        "type": "string"
                    }
                }
            }
        },
        {
            "title": "NOT",
            "logical": true,
            "config": {
                "type": "object",
                "properties": {
                    "subject": {
                        "type": "object",
                        "properties": { }
                    }
                }
            }
        },
        {...},
        {...},
        {...}
    ],
    "resultCount" : 5,
    "pagedResultsCookie" : null,
    "remainingPagedResults" : 0
}

Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

Reading a Specific Subject Condition Type

To read an individual subject condition type, perform an HTTP GET to the /json/subjecttypes endpoint, and specify the subject condition type name in the URL.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
 --header "iPlanetDirectoryPro: AQIC5..." \
 https://openam.example.com:8443/openam/json/subjecttypes/Identity
{
    "title" : "Identity",
    "logical" : false,
    "config" : {
        "type" : "object",
        "properties" : {
            "subjectValues" : {
                "type" : "array",
                "items" : {
                    "type" : "string"
                }
            }
        }
    }
}

Managing Subject Attributes

When you define a policy subject condition, the condition can depend on values of subject attributes stored in a user’s profile. The list of possible subject attributes that you can use depends on the LDAP User Attributes configured for the Identity data store where OpenAM looks up the user’s profile. OpenAM provides the subjectattributes REST endpoint for the following:

Subject attributes derive from the list of LDAP user attributes configured for the Identity data store. For more information, see "Configuring Data Stores" in the Administration Guide.

Querying Subject Attributes

To list all subject attributes, perform an HTTP GET to the /json/subjectattributes endpoint, with a _queryFilter parameter set to true.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/subjectattributes/?_queryFilter=true

{
    "result" : [
        "sunIdentityServerPPInformalName",
        "sunIdentityServerPPFacadeGreetSound",
        "uid",
        "manager",
        "sunIdentityServerPPCommonNameMN",
        "sunIdentityServerPPLegalIdentityGender",
        "preferredLocale",
        "...",
        "...",
        "..."
    ],
    "resultCount": 87,
    "pagedResultsCookie": null,
    "remainingPagedResults": 0
}

Note that no pagination cookie is set and the subject attribute names are all returned as part of the "result" array.

Managing Decision Combiners

Decision combiners describe how to resolve policy decisions when multiple policies apply. OpenAM provides the decisioncombiners REST endpoint for the following:

Decision combiners are server-wide, and do not differ by realm. Hence the URI for the condition types API does not contain a realm component, but is /json/decisioncombiners.

Querying Decision Combiners

To list all decision combiners, perform an HTTP GET to the /json/decisioncombiners endpoint, with a _queryFilter parameter set to true.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
 --header "iPlanetDirectoryPro: AQIC5..." \
 https://openam.example.com:8443/openam/json/decisioncombiners?_queryFilter=true
{
    "result": [
        {
            "title": "DenyOverride"
        }
    ],
    "resultCount": 1,
    "pagedResultsCookie": null,
    "remainingPagedResults": 0
}

Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

Reading a Specific Decision Combiner

To view an individual decision combiner, perform an HTTP GET on its resource.

To read an individual decision combiner, perform an HTTP GET to the /json/decisioncombiners endpoint, and specify the decision combiner name in the URL.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
 --header "iPlanetDirectoryPro: AQIC5..." \
 https://openam.example.com:8443/openam/json/decisioncombiners/DenyOverride
{
  "title" : "DenyOverride"
}

RESTful OAuth 2.0, OpenID Connect 1.0 and UMA 1.0 Services

This section shows how to use the OpenAM RESTful interfaces for OAuth 2.0, OpenID Connect 1.0, and UMA 1.0.

In this section, long URLs are wrapped to fit the printed page, as some of the output is formatted for easier reading.

OAuth 2.0

OpenAM exposes the following REST endpoints for different OAuth 2.0 purposes:

When accessing the APIs, browser-based REST clients can rely on OpenAM to handle the session as usual. First authenticate with OpenAM. Then perform the operations in the browser session.

Clients not running in a browser can authenticate as described in "Authentication and Logout", whereby OpenAM returns a token.id value. Clients pass the token.id value in a header named after the authentication cookie, by default iplanetDirectoryPro.

OAuth 2.0 Client and Resource Server Endpoints

OpenAM exposes REST endpoints for making calls to OpenAM acting as an authorization server, as described in "Managing OAuth 2.0 Authorization" in the Administration Guide.

In addition to the standard authorization and token endpoints described in RFC 6749, OpenAM also exposes a token information endpoint for resource servers to get information about access tokens so they can determine how to respond to requests for protected resources, and an introspection endpoint to retrieve metadata about a token, such as approved scopes and the context in which the token was issued. OpenAM as authorization server exposes the following endpoints for clients and resource servers.

/oauth2/authorize

Authorization endpoint defined in RFC 6749, used to obtain an authorization grant from the resource owner.

The /oauth2/authorize endpoint is protected by the policy you created after OAuth 2.0 authorization server configuration, which grants all authenticated users access.

The following is an example URL for obtaining consent:

https://openam.example.com:8443/openam/oauth2/realms/root/authorize\ ?client_id=myClient\ &response_type=code\ &scope=profile\ &redirect_uri=https://www.example.com

After logging in, the URL above presents the OAuth 2.0 consent screen, similar to the following:

+ If creating your own consent page, you can create a POST request to the endpoint with the following additional parameters:

decision

Whether the resource owner consents to the requested access, or denies consent.

Valid values are allow or deny.

save_consent

Updates the resource owner’s profile to avoid having to prompt the resource owner to grant authorization when the client issues subsequent authorization requests.

To save consent, set the save_consent property to on.

You must provide the Saved Consent Attribute Name property with a profile attribute in which to store the resource owner’s consent decision.

For more information on setting this property in the OAuth2 Provider service, see "OAuth2 Provider" in the Reference.

csrf

Duplicates the contents of the iPlanetDirectoryPro cookie, which contains the SSO token of the resource owner giving consent.

Duplicating the cookie value helps prevent against Cross-Site Request Forgery (CSRF) attacks.

+ Example:

+

$ curl \
 --request POST \
 --header  "Content-Type: application/x-www-form-urlencoded" \
 --Cookie "iPlanetDirectoryPro=AQIC5w...*" \
 --data "redirect_uri=http://www.example.net" \
 --data "scope=profile" \
 --data "response_type=code" \
 --data "client_id=myClient" \
 --data "csrf=AQIC5w...*" \
 --data "decision=allow" \
 --data "save_consent=on" \
 "https://openam.example.com:8443/openam/oauth2/authorize?response_type=code&client_id=myClient"\
 "&realm=/&scope=profile&redirect_uri=http://www.example.net"

+ You must specify the realm if the OpenAM OAuth 2.0 provider is configured for a subrealm rather than the top-level realm. For example, if the OAuth 2.0 provider is configured for the /customers realm, then use /oauth2/customers/authorize.

+ The /oauth2/authorize endpoint can take additional parameters, such as:

+

  • module and service. Use either as described in "Authenticating To OpenAM" in the Administration Guide, where module specifies the authentication module instance to use or service specifies the authentication chain to use when authenticating the resource owner.

  • response_mode=form_post. Use this parameter to return a self-submitting form that contains the code instead of redirecting to the redirect URL with the code as a string parameter. For more information, see the OAuth 2.0 Form Post Response Mode spec.

  • code_challenge. Use this parameter when Proof Key for Code Exchange (PKCE) support is enabled in the OAuth2 Provider service. To configure it, navigate to Realms > Realm Name > Services > OAuth2 Provider > Advanced and enable the Code Verifier Parameter Required property. For more information about the PKCE support, see Proof Key for Code Exchange by OAuth Public Clients - RFC 7636.

    /oauth2/access_token

    Token endpoint defined in RFC 6749, used to obtain an access token from the authorization server.

    Example: https://openam.example.com:8443/openam/oauth2/access_token

    The /oauth2/access_token endpoint can take an additional parameter, auth_chain=authentication-chain, which allows client to specify the authentication chain to use for Password Grant Type.

    The following example shows how a client can specify the authentication chain, myAuthChain:

    $ curl \
    --request POST \
    --user "myClientID:password" \
    --data "grant_type=password&username=amadmin&password=cangetinam&scope=profile&auth_chain=myAuthChain" \
    https://openam.example.com:8443/openam/oauth2/access_token

    The /oauth2/access_token endpoint can take additional parameters. In particular, you must specify the realm if the OpenAM OAuth 2.0 provider is configured for a subrealm rather than the top-level realm.

    For example, if the OAuth 2.0 provider is configured for the /customers realm, then use /oauth2/customers/access_token.

    /oauth2/device

    Device flow endpoint as defined by the Internet-Draft OAuth 2.0 Device Flow, used by a client device to obtain a device code or an access token.

    Example: https://openam.example.com:8443/openam/oauth2/device/code

    For more information, see "Using Endpoints for OAuth 2.0 Device Flow".

    /oauth2/token/revoke

    When a user logs out of an application, the application revokes any OAuth 2.0 tokens (access and refresh tokens) that are associated with the user. The client can also revoke a token without the need of an SSOToken by sending a request to the /oauth2/token/revoke endpoint as follows:

    $ curl \
    --request POST \
    --data "token=d06ab31e-9cdb-403e-855f-bd77652add84" \
    --data "client_id=MyClientID" \
    --data "client_secret=password" \
    https://openam.example.com:8443/openam/oauth2/token/revoke

    + If you are revoking an access token, then that token will be revoked. If you are revoking a refresh token, then both the refresh token and any other associated access tokens will also be revoked. Associated access tokens means that any other tokens that have come out of the same authorization grant will also be revoked. For cases where a client has multiple access tokens for a single user that were obtained via different authorization grants, then the client will have to make multiple calls to the /oauth2/token/revoke endpoint to invalidate each token.

    /oauth2/tokeninfo

    Endpoint not defined in RFC 6749, used to validate tokens, and to retrieve information, such as scopes.

    The /oauth2/tokeninfo endpoint takes an HTTP GET on /oauth2/tokeninfo?access_token=token-id, and returns information about the token.

    Resource servers — or any party having the token ID — can get token information through this endpoint without authenticating. This means any application or user can validate the token without having to be registered with OpenAM.

    Given an access token, a resource server can perform an HTTP GET on /oauth2/tokeninfo?access_token=token-id to retrieve a JSON object indicating token_type, expires_in, scope, and the access_token ID.

    Example: https://openam.example.com:8443/openam/oauth2/tokeninfo

    The following example shows OpenAM issuing an access token, and then returning token information:

$ curl \
--request POST \
--user "myClientID:password" \
--data "grant_type=password&username=demo&password=changeit&scope=cn%20mail" \
https://openam.example.com:8443/openam/oauth2/access_token
    {
     "expires_in": 599,
     "token_type": "Bearer",
     "refresh_token": "f6dcf133-f00b-4943-a8d4-ee939fc1bf29",
     "access_token": "f9063e26-3a29-41ec-86de-1d0d68aa85e9"
     }

$ curl https://openam.example.com:8443/openam/oauth2/tokeninfo\
  ?access_token=f9063e26-3a29-41ec-86de-1d0d68aa85e9
    {
  "mail": "demo@example.com",
  "grant_type":"password",
  "scope": [
     "mail",
     "cn"
  ],
  "cn": "demo",
  "realm": "/",
  "cnf": {
     "jwk": {
        "alg": "RS512",
        "e": "AQAB",
        "n": "k7qLlj...G2oucQ",
        "kty": "RSA",
        "use": "sig",
        "kid": "myJWK"
     }
  }
  "token_type": "Bearer",
  "expires_in": 577,
  "client_id": "MyClientID",
  "access_token": "f9063e26-3a29-41ec-86de-1d0d68aa85e9"
}

+

Running a GET method to the /oauth2/tokeninfo endpoint as shown in the previous example writes the token ID to the access log. To not expose the token ID in the logs, send the OAuth 2.0 access token as part of the authorization bearer header:

$ curl \
--request GET \
--header "Authorization Bearer aec6b050-b0a4-4ece-a86f-bd131decbb9c" \
"https://openam.example.com:8443/openam/oauth2/tokeninfo"

+ The resource server making decisions about whether the token is valid can thus use the /oauth2/tokeninfo endpoint to retrieve expiration information about the token. Depending on the scopes implementation, the JSON response about the token can also contain scope information. As described in "Using Your Own Client and Resource Server" in the Administration Guide, the default scopes implementation in OpenAM considers scopes to be names of attributes in the resource owner’s user profile. Notice that the JSON response contains the values for those attributes from the user’s profile, as in the preceding example, with scopes set to mail and cn.

/oauth2/introspect

Endpoint defined in draft-ietf-oauth-introspection-04, used to retrieve metadata about a token, such as approved scopes and the context in which the token was issued.

Given an access token, a client can perform an HTTP POST on /oauth2/introspect?token=access_token to retrieve a JSON object indicating the following:

active

Is the token active.

scope

A space-separated list of the scopes associated with the token.

client_id

Client identifier of the client that requested the token.

user_id

The user who authorized the token.

token_type

The type of token.

exp

When the token expires, in seconds since January 1 1970 UTC.

sub

Subject of the token.

iss

Issuer of the token.

The /oauth2/introspect endpoint requires authentication, and supports basic authorization (a base64-encoded string of client_id:client_secret), client_id and client_secret passed as header values, or a JWT bearer token.

The following example demonstrates the /oauth2/introspect endpoint with basic authorization:

$ curl \
 --request POST \
 --header "Authorization: Basic ZGVtbzpjaGFuZ2VpdA==" \
 https://openam.example.com:8443/openam/oauth2/introspect \
 ?token=f9063e26-3a29-41ec-86de-1d0d68aa85e9
 {
  "active": true,
  "scope": "mail cn",
  "client_id": "myOAuth2Client",
  "user_id": "demo",
  "token_type": "Bearer",
  "exp": 1419356238,
  "sub": "https://resources.example.com/",
  "iss": "https://openam.example.com/"
  }

Running a POST method to the /oauth2/introspect endpoint as shown in the previous example writes the token ID to the access log. To hide the token ID in the logs, send the OAuth 2.0 access token as part of the POST body:

$ curl \
--request POST \
--header "Authorization Basic ZGVtbzpjaGFuZ2VpdA==" \
--data "token=f9063e26-3a29-41ec-86de-1d0d68aa85e9" \
"https://openam.example.com:8443/openam/oauth2/introspect"
Using Endpoints for OAuth 2.0 Device Flow

If a client device has a limited user interface, it can obtain an OAuth 2.0 device code and ask a user to authorize the client on a more full-featured user agent, such as an Internet browser.

OpenAM provides the /oauth2/device/code, /oauth2/device/user, and /oauth2/access_token endpoints to support the OAuth 2.0 Device Flow.

The following procedures show how to use the OAuth 2.0 device flow endpoints:

In the examples nonce and state OAuth 2.0 parameters are omitted, but should be used in production.

To Request a User Code in the OAuth 2.0 Device Flow

Devices can display a user code and instructions to a user, which can be used on a separate client to provide consent, allowing the device to access resources.

As user codes may be displayed on lower resolution devices, the list of possible characters used has been optimized to reduce ambiguity. User codes consist of a random selection of eight of the following characters:

234567ABCDEFGHIJKLMNOPQRSTVWXYZabcdefghijkmnopqrstvwxyz

To request a user code in the OAuth 2.0 device flow:

  1. Ensure that an OAuth 2.0/OpenID Connect client Agent profile is configured in OpenAM, as described in "Configuring OAuth 2.0 and OpenID Connect 1.0 Clients" in the Administration Guide.

  2. Create a POST request to the /oauth2/device/code endpoint to acquire a device code. The following URL parameters are required:

    response_type

    Specifies the response type required by the request. Must be set to token.

    scope

    Specifies the list of scopes requested by the client, separated by URL-encoded space characters.

    client_id

    Specifies the name of the client agent profile in OpenAM.

    $ curl \
      --data response_type=token \
      --data scope=phone%20email%20profile%20address \
      --data client_id=myDeviceAgentProfile \
      http://openam.example.com:8080/openam/oauth2/device/code
    {
        "interval": 5,
        "device_code": "7a95a0a4-6f13-42e3-ac3e-d3d159c94c55",
        "verification_url": "http://openam.example.com:8080/openam/oauth2/device/user",
        "user_code": "VAL12e0v",
        "expires_in": 300
    }

    On success, OpenAM returns a verification URL, and a user code to enter at that URL. OpenAM also returns an interval, in seconds, that the client device must wait for in between requests for an access token.

  3. The client device should now provide instructions to the user to enter the user code and grant access to the OAuth 2.0 device. The client may choose an appropriate method to convey the instructions, for example text instructions on screen, or a QR code. See "To Grant Consent in the OAuth 2.0 Device Flow".

  4. The client device should also begin polling the authorization server for the access token, once consent has been given. See "To Poll for Authorization in the OAuth 2.0 Device Flow".

To Grant Consent in the OAuth 2.0 Device Flow

OAuth 2.0 device flow requires that the user grants consent to allow the client device to access resources.

  • You can grant consent in the OAuth 2.0 device flow using the OpenAM user interface, or by making calls to OpenAM endpoints.

    • To use the OpenAM user interface, the user should visit the verification URL in a web browser and enter the user code:

oauth2 device user code

The user can then authorize the device flow client by allowing the requested scopes:

oauth2 device consent
  • To use endpoint calls, create a POST request to the /oauth2/device/user endpoint. The following URL parameter is required:

    user_code

    The user code as provided by the /oauth2/device/code endpoint.

    The form data should be in x-www-form-urlencoded format, and contain the following fields:

    user_code

    The user code as provided by the /oauth2/device/code endpoint.

    scope

    Specifies the list of scopes consented to by the user, separated by URL-encoded space characters.

    client_id

    Specifies the name of the client agent profile in OpenAM.

    response_type

    Must be token.

    decision

    To allow client access, specify allow. Any other value will deny consent.

    csrf

    Duplicates the contents of the iPlanetDirectoryPro cookie, which contains the SSO token of the user granting access.

    Duplicating the cookie value helps prevent against Cross-Site Request Forgery (CSRF) attacks.

    The iPlanetDirectoryPro cookie is required and should contain the SSO token of the user granting access to the client.

    $ curl \
      -X POST \
      --header "Cookie: iPlanetDirectoryPro=AQIC5..." \
      --header "Content-Type: application/x-www-form-urlencoded" \
      --data scope=phone%20email%20profile%20address \
      --data user_code=VAL12e0v \
      --data response_type=token \
      --data client_id=myDeviceAgentProfile \
      --data decision=allow \
      --data csrf=AQIC5... \
      http://openam.example.com:8080/openam/oauth2/device/user?user_code=VAL12e0v

    OpenAM returns HTML containing a JavaScript fragment named pageData, with details of the result.

    Successfully allowing or denying access returns:

    pageData = {
        locale: "en-us",
        baseUrl : "http://openam.example.com:8080/openam/XUI",
        realm : "//XUI",
        done: true
    };

    If the supplied user code has already been used, or is incorrect, the following is returned:

    pageData = {
        locale: "*",
        errorCode: "not_found",
        realm : "/",
        baseUrl : "http://openam.example.com:8080/openam/XUI"
    };

    If the user gives consent, OpenAM adds the OAuth 2.0 client to the user’s profile page in the Authorized Apps section. For more information, see "User Consent Management" in the Administration Guide.

    As per Section 4.1.1 of the OAuth 2.0 authorization framework, it is required that the authorization server legitimately obtains an authorization decision from the resource owner. Any client using the endpoints to register consent is responsible for ensuring this requirement, OpenAM cannot assert that consent was given in these cases.

To Poll for Authorization in the OAuth 2.0 Device Flow
  • On the client device, create a POST request to poll the /oauth2/access_token endpoint to request an access token. Include the client ID, client secret, and the device code as query parameters in the request. You must also specify a grant_type of http://oauth.net/grant_type/device/1.0.

    The client device must wait for the number of seconds previously provided as the value of interval between polling OpenAM for an access token.

    $ curl \
      --data client_id=myDeviceAgentProfile \
      --data client_secret=password \
      --data grant_type=http://oauth.net/grant_type/device/1.0 \
      --data code=7a95a0a4-6f13-42e3-ac3e-d3d159c94c55 \
      http://openam.example.com:8080/openam/oauth2/access_token
    {
        "scope": "phone email address profile",
        "code": "20c1fc0c-3153-4a11-8d1f-d815c1a522b5"
    }

    If the user has authorized the client device, an HTTP 200 status code is returned, with an access token that can be used to request resources.

    {
        "expires_in": 3599,
        "token_type": "Bearer",
        "access_token": "c1e9c8a4-6a6c-45b2-919c-335f2cec5a40"
    }

    If the user has not yet authorized the client device, an HTTP 403 status code is returned, with the following error message:

    {
        "error": "authorization_pending",
        "error_description": "The user has not yet completed authorization"
    }

    If the client device is polling faster than the specified interval, an HTTP 400 status code is returned, with the following error message:

    {
        "error": "slow_down",
        "error_description": "The polling interval has not elapsed since the last request"
    }
OAuth 2.0 Resource Set Endpoint

OpenAM provides a read-only REST endpoint for viewing a resource set registered to a particular user. The endpoint is /json{/realm}/users/user/oauth2/resourcesets/resource_set_ID, so for example https://openam.example.com:8443/openam/json/myrealm/users/demo/oauth2/resourcesets/43225628-4c5b-4206-b7cc-5164da81decd0.

To read a resource set, either the resource set owner or an administrator such as amadmin must have logged in to OpenAM (the authorization server) and have been issued an SSO token.

To Read an OAuth 2.0 Resource Set
  • Create a GET request to the resourcesets endpoint, including the SSO token in a header based on the configured session cookie name (for example: iPlanetDirectoryPro), and with the resource set ID in the URL.

    The following example uses an SSO token acquired by the amadmin user to view a resource set, and related policy, belonging to the demo user in the top level realm:

    $ curl \
    --header "iPlanetDirectoryPro: AQIC5wM2LY4Sfcxs...EwNDU2NjE0*" \
    https://openam.example.com:8443/openam/json/users/demo\
    /oauth2/resourcesets/43225628-4c5b-4206-b7cc-5164da81decd0
    {
        "scopes": [
             "http://photoz.example.com/dev/scopes/view",
             "http://photoz.example.com/dev/scopes/comment"
        ],
        "_id": "43225628-4c5b-4206-b7cc-5164da81decd0",
        "resourceServer": "UMA-Resource-Server",
        "name": "My Videos",
        "icon_uri": "http://www.example.com/icons/cinema.png",
        "policy": {
            "permissions": [
                {
                    "subject": "user.1",
                    "scopes": [
                        "http://photoz.example.com/dev/scopes/view"
                    ]
                },
                {
                    "subject": "user.2",
                    "scopes": [
                        "http://photoz.example.com/dev/scopes/comment",
                        "http://photoz.example.com/dev/scopes/view"
                    ]
                }
            ]
        },
        "type": "http://www.example.com/rsets/videos"
    }

    You can specify the fields that are returned with the _fields query string filter. For example ?_fields=scopes, resourceServer, name

    On success, an HTTP 200 OK status code is returned, with a JSON body representing the resource set. If a policy relating to the resource set exists, a representation of the policy is also returned in the JSON.

    If the specified resource set does not exist, an HTTP 404 Not Found status code is returned, as follows:

    {
        "code": 404,
        "reason": "Not Found",
        "message": "No resource set with id, bad-id-3e28-4c19-8a2b-36fc24c899df0, found."
    }

    If the SSO token used is not that of the resource set owner or an administrator, an HTTP 403 Forbidden status code is returned, as follows:

    {
        "code": 403,
        "reason": "Forbidden",
        "message": "User, user.1, not authorized."
    }
OAuth 2.0 Token Administration Endpoint

The OpenAM-specific OAuth 2.0 token administration endpoint lets administrators read, list, and delete OAuth 2.0 tokens. OAuth 2.0 clients can also manage their own tokens.

OpenAM exposes the token administration endpoint at /frrest/oauth2/token, such as https://openam.example.com:8443/openam/frrest/oauth2/token.

This endpoint location is likely to change in the future.

To get a token, perform an HTTP GET on /frrest/oauth2/token/token-id, as in the following example:

$ curl \
 --request POST \
 --user "myClientID:password" \
 --data "grant_type=password&username=demo&password=changeit&scope=cn" \
 https://openam.example.com:8443/openam/oauth2/access_token
 {
    "scope": "cn",
    "expires_in": 60,
    "token_type": "Bearer",
    "access_token": "f5fb4833-ba3d-41c8-bba4-833b49c3fe2c"
}

$ curl \
 --request GET \
 --header "iplanetDirectoryPro: AQIC5wM2LY4Sfcxs...EwNDU2NjE0*" \
 https://openam.example.com:8443/openam/frrest/oauth2/token/f5fb4833-ba3d-41c8-bba4-833b49c3fe2c
 {
    "expireTime": [
        "1418818601396"
    ],
    "tokenName": [
        "access_token"
    ],
    "scope": [
        "cn"
    ],
    "grant_type": [
        "password"
    ],
    "clientID": [
        "myClientID"
    ],
    "parent": [],
    "id": [
        "f5fb4833-ba3d-41c8-bba4-833b49c3fe2c"
    ],
    "tokenType": [
        "Bearer"
    ],
    "redirectURI": [],
    "nonce": [],
    "realm": [
        "/"
    ],
    "userName": [
        "demo"
    ]
}

To list tokens, perform an HTTP GET on /frrest/oauth2/token/?_queryId=access_token to request the list of access tokens for the current user.

The following example shows a search for the demo user’s access tokens:

$ curl \
 --request GET \
 --header "iplanetDirectoryPro: AQIC5wM2LY4Sfcw..." \
 https://openam.example.com:8443/openam/frrest/oauth2/token/?_queryId=access_token
 {
    "_rev": "1753454107",
    "tokenName": [
    "access_token"
    ],
    "expireTime": "Indefinitely",
    "scope": [
      "openid"
    ],
    "grant_type": [
      "password"
    ],
    "clientID": [
      "myOAuth2Client"
    ],
    "tokenType": [
      "Bearer"
    ],
    "redirectURI": [],
    "nonce": [],
    "realm": [
      "/test"
    ],
    "userName": [
      "user.4"
    ],
    "display_name": "",
    "scopes": "openid"
    },
    {
    "_rev": "1753454107",
    "tokenName": [
      "access_token"
    ],
    "expireTime": "Indefinitely",
    "scope": [
      "openid"
    ],
    "grant_type": [
      "password"
    ],
    "clientID": [
      "myOAuth2Client"
    ],
    "tokenType": [
      "Bearer"
    ],
    "redirectURI": [],
    "nonce": [],
    "realm": [
      "/test"
    ],
    "userName": [
      "user.4"
    ],
    "display_name": "",
    "scopes": "openid"
    }
    ],
    "resultCount": 2,
    "pagedResultsCookie": null,
    "totalPagedResultsPolicy": "NONE",
    "totalPagedResults": -1,
    "remainingPagedResults": -1
}

To list a specific user’s tokens, perform an HTTP GET on /ffrest/oauth2/token/?_queryId=userName=string, where string is the user, such as user.4. You must use an amadmin token with this GET method. Delegated admins are not supported here.

$ curl \
--request GET \
--header "iplanetDirectoryPro: AQIC5wM2LY4Sfcxs...EwNDU2NjE0*" \
https://openam.example.com:8443/openam/frrest/oauth2/token/?_queryId=userName=user.4
{
    "result": [
    {
    "_id": "2aaddde8-586b-4cb7-b431-eb86af57aabc",
    "_rev": "-549186065",
    "tokenName": [
      "access_token"
    ],
    "expireTime": "Indefinitely",
    "scope": [
      "openid"
    ],
    "grant_type": [
      "password"
    ],
    "authGrantId": [
      "50e9f80b-d193-4aeb-93e9-e383ea2cabd3"
    ],
    "clientID": [
      "myOAuth2Client"
    ],
    "parent": [],
    "refreshToken": [
      "5e1423a2-d2cd-40d5-8f54-5b695836cd44"
    ],
    "id": [
      "2aaddde8-586b-4cb7-b431-eb86af57aabc"
    ],
    "tokenType": [
      "Bearer"
    ],
    "auditTrackingId": [
      "6ac90d13-9cac-444b-bfbc-c7aca16713de-777"
    ],
    "redirectURI": [],
    "nonce": [],
    "realm": [
      "/test"
    ],
    "userName": [
      "user.4"
    ],
    "display_name": "",
    "scopes": "openid"
    },
    {
    "_id": "5e1423a2-d2cd-40d5-8f54-5b695836cd44",
    "_rev": "1171292923",
    "tokenName": [
      "refresh_token"
    ],
    "expireTime": "Oct 18, 2016 10:51 AM",
    "scope": [
      "openid"
    ],
    "grant_type": [
      "password"
    ],
    "authGrantId": [
      "50e9f80b-d193-4aeb-93e9-e383ea2cabd3"
    ],
    "clientID": [
      "myOAuth2Client"
    ],
    "authModules": [],
    "id": [
      "5e1423a2-d2cd-40d5-8f54-5b695836cd44"
    ],
    "tokenType": [
      "Bearer"
    ],
    "auditTrackingId": [
      "6ac90d13-9cac-444b-bfbc-c7aca16713de-776"
    ],
    "redirectURI": [],
    "realm": [
      "/test"
    ],
    "userName": [
      "user.4"
    ],
    "acr": [],
    "display_name": "",
    "scopes": "openid"
    },
    ],
    "resultCount": 2,
    "pagedResultsCookie": null,
    "totalPagedResultsPolicy": "NONE",
    "totalPagedResults": -1,
    "remainingPagedResults": -1
}

To delete a token, perform an HTTP DELETE on /frrest/oauth2/token/token-id, as in the following example:

$ curl \
 --request POST \
 --data "grant_type=client_credentials&username=demo&password=changeit\
&client_id=myClientID&client_secret=password&scope=cn%20mail" \
 https://openam.example.com:8443/openam/oauth2/access_token
{
    "expires_in": 599,
    "token_type": "Bearer",
    "access_token": "867aaab2-61d7-4b78-9b80-4f9098034540"
}

$ curl \
 --request DELETE \
 --header "iplanetDirectoryPro: AQIC5wM2LY4Sfcxs...EwNDU2NjE0*" \
 https://openam.example.com:8443/openam/frrest/oauth2/token/867aaab2..098034540
{
    "success": "true"
}
OAuth 2.0 Client Administration Endpoint

The OAuth 2.0 administration endpoint lets OpenAM administrators and agent administrators create (that is, register) and delete OAuth 2.0 clients.

OpenAM exposes this endpoint at /frrest/oauth2/client, such as https://openam.example.com:8443/openam/frrest/oauth2/client.

This endpoint location is likely to change in the future.

To create an OAuth 2.0 client, perform an HTTP POST to /frrest/oauth2/client/?_action=create with a JSON object fully specifying the client, as in the following example:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iplanetDirectoryPro: AQIC5wM...3MTYxOA..*" \
 --data \
 '{"client_id":["testClient"],
   "realm":["/"],
   "userpassword":["secret12"],
   "com.forgerock.openam.oauth2provider.clientType":["Confidential"],
   "com.forgerock.openam.oauth2provider.redirectionURIs":
     ["www.client.com","www.example.com"],
   "com.forgerock.openam.oauth2provider.scopes":["cn","sn"],
   "com.forgerock.openam.oauth2provider.defaultScopes":["cn"],
   "com.forgerock.openam.oauth2provider.name":["My Test Client"],
   "com.forgerock.openam.oauth2provider.description":["OAuth 2.0 Client"]
  }' \
 https://openam.example.com:8443/openam/frrest/oauth2/client/?_action=create
{"success":"true"}

When creating an OAuth 2.0 client, use the following fields in your JSON object:

client_id

(Required) This field takes an array containing the client identifier as defined in RFC 6749.

realm

(Required) This field takes an array containing the OpenAM realm in which to create the client as defined in RFC 6749.

userpassword

(Required) This field takes an array containing the client secret as defined in RFC 6749.

com.forgerock.openam.oauth2provider.clientType

(Required) This field takes an array containing the client type, either "Confidential" or "Public" as defined in RFC 6749.

com.forgerock.openam.oauth2provider.redirectionURIs

(Optional for confidential clients) This field takes an array of client redirection endpoints as defined in RFC 6749.

com.forgerock.openam.oauth2provider.scopes

(Optional) This field takes an array of scopes as defined in RFC 6749. The default scopes implementation takes scopes to be names of attributes in the resource owner profile.

Specify locale scopes in scope|locale|localized description format.

com.forgerock.openam.oauth2provider.defaultScopes

(Optional) This field takes an array of default scopes set automatically when tokens are issued.

com.forgerock.openam.oauth2provider.name

(Optional) This field takes an array containing the client name to display to the resource owner when the resource owner must authorize client access to protected resources.

Specify localized names in locale|localized name format.

com.forgerock.openam.oauth2provider.description

(Optional) This field takes an array containing the description to display to the resource owner when the resource owner must authorize client access to protected resources.

Specify localized descriptions in locale|localized description format.

To delete an OAuth 2.0 client, perform an HTTP DELETE on /frrest/oauth2/client/client-id, as in the following example:

$ curl \
 --request DELETE \
 --header "iplanetDirectoryPro: AQIC5wM...3MTYxOA..*" \
 https://openam.example.com:8443/openam/frrest/oauth2/client/myClient
{"success":"true"}

To delete an OAuth 2.0 client from a subrealm, add the name of the subrealm in a query parameter named realm, as in the following example:

$ curl \
 --request DELETE \
 --header "iplanetDirectoryPro: AQIC5wM...3MTYxOA..*" \
 https://openam.example.com:8443/openam/frrest/oauth2/client/myClient?realm=myRealm
{"success":"true"}

OpenID Connect 1.0

OpenID Connect 1.0 extends OAuth 2.0 so the client can verify claims about the identity of the end user, get profile information about the end user, and log the user out at the end of the OpenAM session. OpenAM exposes the following endpoints for OpenID Connect 1.0 purposes:

Endpoints for Discovering OpenID Connect 1.0 Configuration

OpenAM exposes endpoints for discovering information about the provider configuration, and about the provider for a given end user:

  • /oauth2/.well-known/openid-configuration allows clients to retrieve OpenID Provider configuration by HTTP GET as specified by OpenID Connect Discovery 1.0.

  • /oauth2/.well-known/webfinger allows clients to retrieve the provider URL for an end user by HTTP GET as specified by OpenID Connect Discovery 1.0.

For examples, see Configuring OpenAM For OpenID Connect Discovery in the Administration Guide.

OpenAM supports a provider service that allows the realm to have a configured option for obtaining the base URL (including protocol) for components that need to return a URL to the client. This service is used to provide the URL base that is used in the .well-known endpoints used in OpenID Connect 1.0 and UMA.

For more information, see "Configuring the Base URL Source Service" in the Administration Guide.

Endpoints for Registering OpenID Connect 1.0 Clients

OpenAM allows both static and dynamic registration of OpenID Connect client applications. For dynamic registration according to the OpenID Connect Dynamic Client Registration 1.0 specification, the endpoint is /oauth2/connect/register. See "To Register a Relying Party Dynamically" in the Administration Guide for details.

Endpoints for Performing OpenID Connect 1.0 Client Authorization

Registered clients can request authorization through OpenAM.

OpenID Connect 1.0 supports both a Basic Client Profile using the OAuth 2.0 authorization code grant, and an Implicit Client Profile using the OAuth 2.0 implicit grant. These client profiles rely on the OAuth 2.0 endpoints for authorization. Those endpoints are described in "OAuth 2.0 Client and Resource Server Endpoints".

In addition, authorized clients can access end user information through the OpenID Connect 1.0 specific endpoint /oauth2/userinfo.

For examples, see "Relying Party Examples" in the Administration Guide.

Endpoints for Managing OpenID Connect 1.0 Sessions

Registered clients can use OpenID Connect Session Management 1.0 to handle end user logout actions.

  • /oauth2/connect/checkSession allows clients to retrieve session status notifications.

  • /oauth2/connect/endSession allows clients to terminate end user sessions.

For an example, see "Managing OpenID Connect User Sessions" in the Administration Guide.

Endpoint for Validating OpenID Connect 1.0 ID Tokens

Clients can use an OpenID Connect 1.0 endpoint on OpenAM to quickly validate a stateless OIDC ID token and optionally retrieve any claims within the token. The endpoint is used globally and not within a realm. For information on configuring stateless OIDC tokens, see "Configuring Stateless OpenID Connect 1.0 Tokens".

  • /openam/oauth2/idtokeninfo

The endpoint does not support the validation of encrypted OIDC ID tokens.

The endpoint validates an OIDC ID token based on rules 1-10 in section 3.1.3.7 of the OpenID Connect Core and runs the following steps:

  1. Extracts the first aud (audience) claim from the ID token. The client_id, which is passed in as authentication of the request, will be used as the client and validated against the aud claim.

  2. Extracts the realm claim, if present, default to the root realm if the token was not issued by OpenAM.

  3. Looks up the client in the given realm, producing an error if it does not exist.

  4. Verifies the signature of the ID token, according to the settings for the client (ID token signed response algorithm, public key selector).

  5. Verifies the issuer, audience, expiry, not-before, and issued-at claims as per the specification.

To invoke the endpoint, the client sends an HTTP POST request to /openam/oauth2/idtokeninfo using the following parameters in the POST body in application/x-www-form-url-encoded format or as query parameters:

  • id_token - OIDC ID token to validate (required)

  • claims - optional comma-separated list of claims to return from the ID token For example, you can run the following command:

curl -X POST -d "id_token=$IDTOKEN" http://openam.example.com:8080/openam/oauth2/idtokeninfo

where $IDTOKEN is an OIDC ID token

If the ID token validates successfully, the endpoint unpacks the claims from the ID token and returns them as JSON. You can also use an optional claims parameter in the request to return those specific claims. If a claim is requested that does not exist, no error occurs; it will simply not be present in the response.

For example, you can run the following command to retrieve the claims in an OIDC ID token:

curl -i -X POST -d "id_token=$IDTOKEN" \
'http://openam.example.com:8080/openam/oauth2/idtokeninfo?claims=sub,exp,realm'
HTTP/1.1 200 OK
Date: Wed, 01 Jun 2016 07:31:39 GMT
Accept-Ranges: bytes
Server: Restlet-Framework/2.3.4
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Type: application/json;charset=UTF-8
Content-Length: 50
{
    "sub": "demo",
    "exp": 1461065147,
    "realm": "/"
}

For invalid requests, the endpoint returns a 400 HTTP code with a JSON error response:

curl -i -X POST 'http://openam.example.com:8080/openam/oauth2/idtokeninfo?claims=sub,exp,realm'
HTTP/1.1 400 Bad Request
Date: Wed, 01 Jun 2016 08:32:43 GMT
Accept-Ranges: bytes
Server: Restlet-Framework/2.3.4
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept
Content-Type: application/json
Transfer-Encoding: chunked
Connection: close
{
    "error":"bad_request",
    "error_description":"no id_token in request"
}
Configuring Stateless OpenID Connect 1.0 Tokens

OpenAM supports stateless access, refresh, and ID tokens for OpenID Connect 1.0 (OIDC). Stateless tokens allow clients to directly validate the tokens by storing session information within the token itself and bypassing storage in an external CTS data store. This feature also allows any OpenAM instance in the issuing cluster to validate an OIDC tokens without cross-talk.

For configuration procedures, see "Stateless OpenID Connect 1.0 Access and Refresh Tokens" in the Administration Guide.

User-Managed Access (UMA)

User-Managed Access (UMA) is a profile of OAuth 2.0 that lets resource owners control access to protected resources on any number of resource servers from arbitrary requesting parties.

OpenAM acts as the centralized authorization server and governs access using policies created by resource owners. OpenAM exposes the following REST endpoints for User-Managed Access purposes:

Discovering UMA Configuration

OpenAM exposes an endpoint for discovering information about the UMA provider configuration.

A resource server or client can perform an HTTP GET on /uma{/realm}/.well-known/uma-configuration to retrieve a JSON object indicating the UMA configuration.

For an example, see Configuring OpenAM For UMA Discovery in the Administration Guide.

Managing UMA Resource Sets

UMA uses the OAuth 2.0 Resource Set Registration standard for registration and management of resources. The endpoint is /oauth2/resource_set/. For details, see "Managing UMA Resource Sets" in the Administration Guide.

OpenAM also provides a read-only endpoint for viewing a user’s resource sets, and if available policy definitions. For more information, see "OAuth 2.0 Resource Set Endpoint".

Managing UMA Policies

OpenAM exposes the following endpoint for managing UMA policies:

/json/users/username/uma/policies

For managing UMA policies. For details, see "Managing UMA Policies" in the Administration Guide.

Accessing UMA Protected Resources

OpenAM exposes the following endpoints for managing UMA workflow and accessing protected resources:

/uma/permission_request

For registering permission requests. For more information, see "To Register an UMA Permission Request" in the Administration Guide.

/uma/authz_request

For acquiring requesting party tokens. For more information, see "To Acquire a Requesting Party Token" in the Administration Guide.

RESTful User Self-Service

This section shows how to use the OpenAM RESTful interfaces for user self-service functionality: user self-registration, forgotten password reset, forgotten username retrieval, dashboard configuration, and device profile reset.

The steps to perform user self-service via the REST APIs varies depending on the configured user self-service process flow. For more information, see "User Self-Service Process Flows" in the Administration Guide.

When performing user self-service functions, you can enable one or more security methods, such as email validation, Google reCAPTCHA, knowledge-based authentication, or custom plugins. Each configured security method requires requests to be sent from OpenAM to the client, and completed responses returned to OpenAM to verify.

At least one security method should be enabled for each self-service feature.

A unique token is provided in the second request to the client that must be used in any subsequent responses, so that OpenAM can maintain the state of the self-service process.

In this section, long URLs are wrapped to fit the printed page, and some of the output is formatted for easier reading.

Registering Users

This section explains how to use the REST APIs for registering a user in OpenAM.

From OpenAM 13.5.1, the user self-registration flow validates the email address after the user has provided their details. This section provides procedures for OpenAM 13.5 and OpenAM 13.5.1 and later:

To Register a User with the REST APIs (13.5.1 or later)
  1. Create a GET request to the /selfservice/userRegistration endpoint. Notice that the request does not require any form of authentication.

    $ curl \
    https://openam.example.com:8443/openam/json/selfservice/userRegistration
    {
     "requirements": {
       "$schema": "http://json-schema.org/draft-04/schema#",
       "description": "New user details",
       "properties": {
         "user": {
           "description": "User details",
           "type": "object"
         }
       },
       "required": [
         "user"
       ],
       "type": "object"
     },
     "tag": "initial",
     "type": "userDetails"
    }

    OpenAM sends a request to complete the user details. The required array defines the data that must be returned to OpenAM to progress past this step of the registration. In the example, the required type is a user object that contains the user details.

  2. Create a POST response back to the /selfservice/userRegistration endpoint with a query string containing _action=submitRequirements. In the POST data, include an input element in the JSON structure, which should contain values for each element in the required array of the request.

    In this example, OpenAM requests an object named user. Ths object should contain values for the username, givenName, sn, mail, userPassword, and inetUserStatus properties.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
      "input": {
        "user": {
          "username": "DEMO",
          "givenName": "Demo User",
          "sn": "User",
          "mail": "demo@example.com",
          "userPassword": "forgerock",
          "inetUserStatus": "Active"
        }
      }
    }' \ https://openam.example.com:8443/openam/json/selfservice/userRegistration?_action=submitRequirements
    {
      "requirements": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "description": "Verify emailed code",
        "properties": {
          "code": {
            "description": "Enter code emailed",
            "type": "string"
          }
        },
        "required": [
          "code"
        ],
        "type": "object"
      },
      "tag": "validateCode",
      "token": "eyJ0eXAiOiJKV.....QiLCJjmqrlqUfQ",
      "type": "emailValidation"
    }

    If the response is accepted, OpenAM continues with the registration process and sends the next request for information.

    The value of the token element should be included in this and any subsequent responses to OpenAM for this registration; OpenAM uses this information to track which stage of the registration process is being completed.

    Note that the request for information is of the type emailValidation. Other possible types include:

    • captcha, if the Google reCAPTCHA plugin is enabled

    • kbaSecurityAnswerDefinitionStage, if knowledge-based security questions are required

    For an example of Google reCAPTCHA validation, see "Retrieving Forgotten Usernames".

  3. Return the information required by the next step of the registration, along with the token element.

    In this example, the user information was accepted and a code was emailed to the email address. OpenAM requires this code in the response in an element named code before continuing:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
      "input": {
        "code": "cf53fcb6-3bf2-44eb-a437-885296899699"
      },
      "token": "eyJ0eXAiOiJKV.....QiLCJjmqrlqUfQ"
    }' https://openam.example.com:8443/openam/json/selfservice/userRegistration\
    ?_action=submitRequirements
    {
      "type": "selfRegistration",
      "tag": "end",
      "status": {
        "success": true
      },
      "additions": {
    
      }
    }

    When the process is complete, the response from OpenAM has a tag property with value of end. If the success property in the status object has a value of true, then self-registration is complete and the user account was created.

    In the example, OpenAM only required email verification to register a new user. In flows containing Google reCAPTCHA validation or knowledge-based security questions, you would continue returning POST data to OpenAM containing the requested information until the process is complete.

    The User Self-Service feature provides options to set the user’s destination after a successful self-registration. These options include redirecting the user to a 'successful registration' page, to the login page, or automaticatically logging the user into the system. Use the Destination After Successful Self-Registration property to set the option (on the console: Realm Name > Services > User Self-Service > User Registration). When you select User sent to 'successful registration' page or User sent to login page, the JSON response after a successful registration is as follows:

    {
     "type": "selfRegistration",
     "tag": "end",
     "status": {
         "success": true
     },
     "additions": {}
    }

    If you select User is automatically logged in, the JSON response is:

    {
     "type": "autoLoginStage",
     "tag": "end",
     "status": {
         "success": true
     },
     "additions": {
         "tokenId": "AQIC5...MQAA*",
         "successUrl": "/openam/console"
     }
    }
To Register a User with the REST APIs (13.5)
  1. Create a GET request to the /selfservice/userRegistration endpoint. Notice that the request does not require any form of authentication.

    $ curl \
    https://openam.example.com:8443/openam/json/selfservice/userRegistration
    {
        "type": "emailValidation",
        "tag": "initial",
        "requirements": {
            "$schema": "http://json-schema.org/draft-04/schema#",
            "description": "Verify your email address",
            "type": "object",
            "required": [
                "mail"
            ],
            "properties": {
                "mail": {
                    "description": "Email address",
                    "type": "string"
                }
            }
        }
    }

    OpenAM sends the first request for security information. In this example, the first request is of type emailValidation, but other types include captcha if the Google reCAPTCHA plugin is enabled, and kbaSecurityAnswerDefinitionStage if knowledge-based authentication is required.

    The required array defines the data that must be returned to OpenAM to progress past this step of the registration.

    The properties element contains additional information about the required response, such as a description of the required field, or the site key required to generate a reCAPTCHA challenge.

  2. Create a POST response back to the /selfservice/userRegistration endpoint with a query string containing _action=submitRequirements. In the POST data, include an input element in the JSON structure, which should contain values for each element in the required array of the request.

    In this example, a mail value was requested.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "mail": "demo.user@example.com"
        }
    }' \
    https://openam.example.com:8443/openam/json/selfservice/userRegistration\
     ?_action=submitRequirements
    {
        "type": "emailValidation",
        "tag": "validateCode",
        "requirements": {
            "$schema": "http://json-schema.org/draft-04/schema#",
            "description": "Verify emailed code",
            "type": "object",
            "required": [
                "code"
            ],
            "properties": {
                "code": {
                    "description": "Enter code emailed",
                    "type": "string"
                }
            }
        },
        "token": "eyAicHis...PIF-lN4s"
    }

    If the response was accepted, OpenAM continues with the registration process and sends the next request for information. In this example, the email address was accepted and a code was emailed to the address, which OpenAM requires in the response in an element named code before continuing.

    The value of the token element should be included in this and any subsequent responses to OpenAM for this registration.

  3. Continue returning POST data to OpenAM containing the requested information, in the format specified in the request. Also return the token value in the POST data, so that OpenAM can track which stage of the registration process is being completed.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "code": "cf53fcb6-3bf2-44eb-a437-885296899699"
        },
        "token": "eyAicHis...PIF-lN4s"
    }' \
    https://openam.example.com:8443/openam/json/selfservice/userRegistration\
     ?_action=submitRequirements
    {
       "type": "userDetails",
       "tag": "initial",
       "requirements": {
           "$schema": "http://json-schema.org/draft-04/schema#",
           "description": "New user details",
           "type": "object",
           "required": [
               "user"
           ],
           "properties": {
               "user": {
                   "description": "User details",
                   "type": "object"
               }
           }
       },
       "token": "eyAicHis...PIF-lN4s"
    }
  4. When requested—when the type value in the request is userDetails—supply the details of the new user as an object in the POST data.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "user": {
                "username": "demo",
                "givenName": "Demo User",
                "sn": "User",
                "userPassword": "d3m0",
                "inetUserStatus": "Active"
            }
        },
        "token": "eyAicHis...PIF-lN4s"
    }' \
    https://openam.example.com:8443/openam/json/selfservice/userRegistration\
         ?_action=submitRequirements
    {
        "type": "selfRegistration",
        "tag": "end",
        "status": {
            "success": true
        },
        "additions": {}
        }

    When the process is complete, the tag element has a value of end. If the success element in the status element has a value of true, then self-registration is complete and the user account was created.

Retrieving Forgotten Usernames

This section explains how to use the REST APIs to retrieve a forgotten username.

To Retrieve a Forgotten Username with the REST APIs
  1. Create a GET request to the /selfservice/forgottenUsername endpoint. Notice that the request does not require any form of authentication.

    $ curl \
    https://openam.example.com:8443/openam/json/selfservice/forgottenUsername
    {
      "type": "captcha",
      "tag": "initial",
      "requirements": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "description": "Captcha stage",
        "type": "object",
        "required": [
          "response"
        ],
        "properties": {
          "response": {
            "recaptchaSiteKey": "6Lfr1...cIqbd",
            "description": "Captcha response",
            "type": "string"
          }
        }
      }
    }

    In this example, the Google reCAPTCHA plugin is enabled, so the first request is of the captcha type.

  2. Create a POST response back to the /selfservice/forgottenUsername endpoint with a query string containing _action=submitRequirements. In the POST data, include an input element in the JSON structure, which should contain values for each element in the required array of the request.

    In this example, a response value was requested, which should be the user input as provided after completing the Google reCAPTCHA challenge.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "response": "03AHJ...qiE1x4"
        }
    }' \
    https://openam.example.com:8443/openam/json/selfservice/forgottenUsername\
     ?_action=submitRequirements
    {
        "type": "userQuery",
        "tag": "initial",
        "requirements": {
            "$schema": "http://json-schema.org/draft-04/schema#",
            "description": "Find your account",
            "type": "object",
            "required": [
                "queryFilter"
            ],
            "properties": {
                "queryFilter": {
                    "description": "filter string to find account",
                    "type": "string"
                }
            }
        },
        "token": "eyAicHis...PIF-lN4s"
    }

    If the response was accepted, OpenAM continues with the username retrieval process and sends the next request for information. In this example, the Google reCAPTCHA was verified and OpenAM is requesting details about the account name to retrieve, which must be provided in a queryFilter element.

    The value of the token element should be included in this and all subsequent responses to OpenAM for this retrieval process.

  3. Create a POST response to OpenAM with a queryFilter value in the POST data containing the user’s email address associated with their account.

    For more information on query filters, see "Filtering, Sorting, and Paging Results".

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "queryFilter": "mail eq \"demo.user@example.com\""
        },
        "token": "eyAicHis...PIF-lN4s"
    }' \
    https://openam.example.com:8443/openam/json/selfservice/forgottenUsername\
     ?_action=submitRequirements
    {
      "type": "kbaSecurityAnswerVerificationStage",
      "tag": "initial",
      "requirements": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "description": "Answer security questions",
        "type": "object",
        "required": [
          "answer1"
        ],
        "properties": {
          "answer1": {
            "systemQuestion": {
              "en": "What was the model of your first car?"
            },
            "type": "string"
          }
        }
      },
      "token": "eyAicHis...PIF-lN4s"
    }

    If a single subject is located that matches the provided query filter, the retrieval process continues.

    If KBA is enabled, OpenAM requests answers to the configured number of KBA questions, as in this example.

    If a subject is not found, an HTTP 400 Bad Request status is returned, and an error message in the JSON data:

    {
        "code": 400,
        "reason": "Bad Request",
        "message": "Unable to find account"
    }
  4. Return a POST response with the answers as values of the elements specified in the required array, in this example answer1. Ensure the same token value is sent with each response.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "answer1": "Mustang"
        },
        "token": "eyAicHis...PIF-lN4s"
    }' \
    https://openam.example.com:8443/openam/json/selfservice/forgottenUsername\
     ?_action=submitRequirements
    {
        "type": "retrieveUsername",
        "tag": "end",
        "status": {
            "success": true
        },
        "additions": {
            "userName": "demo"
        }
    }

    When the process is complete, the tag element has a value of end. If the success element in the status element has a value of true, then username retrieval is complete and the username is emailed to the registered address.

    If the Show Username option is enabled for username retrieval, the username retrieved is also returned in the JSON response as the value of the userName element, as in the example above.

Replacing Forgotten Passwords

This section explains how to use the REST APIs to replace a forgotten password.

To Replace a Forgotten Password with the REST APIs
  1. Create a GET request to the /selfservice/forgottenPassword endpoint. Notice that the request does not require any form of authentication.

    $ curl \
    https://openam.example.com:8443/openam/json/selfservice/forgottenPassword
    {
      "type": "captcha",
      "tag": "initial",
      "requirements": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "description": "Captcha stage",
        "type": "object",
        "required": [
          "response"
        ],
        "properties": {
          "response": {
            "recaptchaSiteKey": "6Lfr1...cIqbd",
            "description": "Captcha response",
            "type": "string"
          }
        }
      }
    }

    In this example the Google reCAPTCHA plugin is enabled, so the first request is of the captcha type.

  2. Create a POST response back to the /selfservice/forgottenPassword endpoint with a query string containing _action=submitRequirements. In the POST data, include an input element in the JSON structure, which should contain values for each element in the required array of the request.

    In this example, a response value was requested, which should be the user input as provided after completing the Google reCAPTCHA challenge.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "response": "03AHJ...qiE1x4"
        }
    }' \
    https://openam.example.com:8443/openam/json/selfservice/forgottenPassword\
     ?_action=submitRequirements
    {
        "type": "userQuery",
        "tag": "initial",
        "requirements": {
            "$schema": "http://json-schema.org/draft-04/schema#",
            "description": "Find your account",
            "type": "object",
            "required": [
                "queryFilter"
            ],
            "properties": {
                "queryFilter": {
                    "description": "filter string to find account",
                    "type": "string"
                }
            }
        },
        "token": "eyAicHis...PIF-lN4s"
    }

    If the response was accepted, OpenAM continues with the password reset process and sends the next request for information. In this example, the Google reCAPTCHA was verified and OpenAM is requesting details about the account with the password to replace, which must be provided in a queryFilter element.

    The value of the token element should be included in this and all subsequent responses to OpenAM for this reset process.

  3. Create a POST response to OpenAM with a queryFilter value in the POST data containing the username of the subject with the password to replace.

    For more information on query filters, see "Filtering, Sorting, and Paging Results".

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "queryFilter": "uid eq \"demo\""
        },
        "token": "eyAicHis...PIF-lN4s"
    }' \
    https://openam.example.com:8443/openam/json/selfservice/forgottenPassword\
     ?_action=submitRequirements
    {
      "type": "kbaSecurityAnswerVerificationStage",
      "tag": "initial",
      "requirements": {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "description": "Answer security questions",
        "type": "object",
        "required": [
          "answer1"
        ],
        "properties": {
          "answer1": {
            "systemQuestion": {
              "en": "What was the model of your first car?"
            },
            "type": "string"
          }
        }
      },
      "token": "eyAicHis...PIF-lN4s"
    }

    If a single subject is located that matches the provided query filter, the password reset process continues.

    If a subject is not found, an HTTP 400 Bad Request status is returned, and an error message in the JSON data:

    {
         "code": 400,
         "reason": "Bad Request",
         "message": "Unable to find account"
         }
  4. Continue returning POST data to OpenAM containing the requested information, in the format specified in the request. Also return the token value in the POST data, so that OpenAM can track which stage of the password reset process is being completed.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "answer1": "Mustang"
        },
        "token": "eyAicHis...PIF-lN4s"
    }' \
    https://openam.example.com:8443/openam/json/selfservice/forgottenPassword\
     ?_action=submitRequirements
    {
      "type": "resetStage",
      "tag": "initial",
      "requirements": {
          "$schema": "http://json-schema.org/draft-04/schema#",
          "description": "Reset password",
          "type": "object",
          "required": [
               "password"
          ],
          "properties": {
              "password": {
                  "description": "Password",
                  "type": "string"
              }
          }
      },
       "token": "eyAicHis...PIF-lN4s"
    }
  5. When requested—when the type value in the request is resetStage—supply the new password in the POST data.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --data \
    '{
        "input": {
            "password": "User1234"
        },
        "token": "eyAicHis...PIF-lN4s"
    }' \
    https://openam.example.com:8443/openam/json/selfservice/forgottenPassword\
         ?_action=submitRequirements
    {
        "type": "resetStage",
        "tag": "end",
        "status": {
            "success": true
        },
        "additions": {}
    }

    When the process is complete, the tag element has a value of end. If the success element in the status element has a value of true, then password reset is complete and the new password is now active.

    If the password is not accepted, an HTTP 400 Bad Request status is returned, and an error message in the JSON data:

    {
        "code": 400,
        "reason": "Bad Request",
        "message": "Minimum password length is 8."
    }

Displaying Dashboard Applications

OpenAM lets administrators configure online applications to display applications on user Dashboards. You can used exposed REST API to display information about the online applications.

/dashboard/assigned

This endpoint retrieves the list of applications assigned to the authenticated user.

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/dashboard/assigned
{
  "google": {
      "dashboardIcon": [
          "Google.gif"
      ],
      "dashboardName": [
          "Google"
      ],
      "dashboardLogin": [
          "http://www.google.com"
      ],
      "ICFIdentifier": [
          ""
      ],
      "dashboardDisplayName": [
          "Google"
      ],
      "dashboardClassName": [
          "SAML2ApplicationClass"
      ]
   }
}
/dashboard/available

This endpoint retrieves the list of applications available in the authenticated user’s realm. The example is based on two of the default Dashboard applications: Google and Salesforce.

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/dashboard/available
{
  "google": {
      "dashboardIcon": [
          "Google.gif"
      ],
      "dashboardName": [
          "Google"
      ],
      "dashboardLogin": [
          "http://www.google.com"
      ],
      "ICFIdentifier": [
          ""
      ],
      "dashboardDisplayName": [
          "Google"
      ],
      "dashboardClassName": [
          "SAML2ApplicationClass"
      ]
  }
  "salesforce": {
      "dashboardIcon": [
          "salesforce.gif"
      ],
      "dashboardName": [
          "Salesforce"
      ],
      "dashboardLogin": [
          "http://salesforce.com"
      ],
      "ICFIdentifier": [
          ""
      ],
      "dashboardDisplayName": [
          "Salesforce"
      ],
      "dashboardClassName": [
          "SAML2ApplicationClass"
      ]
  }
}
/dashboard/defined

This endpoint retrieves the list of all applications available defined for the OpenAM Dashboard service. The example is based on the three default Dashboard applications: Google, Salesforce, and Zendesk.

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/dashboard/defined
 {
    "google": {
        "dashboardIcon": [
            "Google.gif"
        ],
        "dashboardName": [
            "Google"
        ],
        "dashboardLogin": [
            "http://www.google.com"
        ],
        "ICFIdentifier": [
            "idm magic 34"
        ],
        "dashboardDisplayName": [
            "Google"
        ],
        "dashboardClassName": [
            "SAML2ApplicationClass"
        ]
    },
    "salesforce": {
        "dashboardIcon": [
            "salesforce.gif"
        ],
        "dashboardName": [
            "SalesForce"
        ],
        "dashboardLogin": [
            "http://www.salesforce.com"
        ],
        "ICFIdentifier": [
            "idm magic 12"
        ],
        "dashboardDisplayName": [
            "Salesforce"
        ],
        "dashboardClassName": [
            "SAML2ApplicationClass"
        ]
    },
    "zendesk": {
        "dashboardIcon": [
            "ZenDesk.gif"
        ],
        "dashboardName": [
            "ZenDesk"
        ],
        "dashboardLogin": [
            "http://www.ZenDesk.com"
        ],
        "ICFIdentifier": [
            "idm magic 56"
        ],
        "dashboardDisplayName": [
            "ZenDesk"
        ],
        "dashboardClassName": [
            "SAML2ApplicationClass"
        ]
    }
}

If your application runs in a user-agent such as a browser, you can rely on OpenAM to handle authentication.

Resetting Device Profiles

The OpenAM REST API provides an action that lets a user reset their own profile for a registered device running an authenticator app used for two-step verification. Administrators can also use this REST API to reset a user’s registered device profile.

Resetting a device profile deletes information about a user’s registered device from OpenAM.

Resetting a device profile is useful when:

  • A user loses a registered device—for example, a mobile phone—but had not saved the device recovery codes available in the OpenAM dashboard.

  • A user loses a registered device and has no device recovery codes remaining.

An administrator or a user can perform an HTTP POST on /json/subrealm/users/user/devices/2fa/oath?_action=reset to reset the user’s device profile:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 --data '{}' \
 https://openam.example.com:8443/openam/json/mySubrealm/users/myUser/devices/2fa/oath?_action=reset
{"result":true}

For more information about device registration, see "Managing Devices for Multi-Factor Authentication" in the Administration Guide.

RESTful Identity and Realm Management Services

This section shows how to use the OpenAM RESTful interfaces for identity and realm management.

In this section, long URLs are wrapped to fit the printed page, as some of the output is formatted for easier reading.

Before making a REST API call to manage a realm or an identity, make sure that you have:

  • Authenticated successfully to OpenAM as a user with sufficient privileges to make the REST API call

  • Obtained the session token returned after successful authentication

When making the REST API call, pass the session token in the HTTP header. For more information about the OpenAM session token and its use in REST API calls, see "Using the Session Token After Authentication".

Identity Management

This section shows how to create, read, update, delete, and list identities using the RESTful APIs.

OpenAM is not primarily an identity data store, nor is it provisioning software. For storing identity data, consider OpenDJ. For provisioning, consider OpenIDM. Both of these products provide REST APIs as well.

OpenAM has two REST APIs for managing identities:

  • Under the /json/agents, /json/groups, and /json/users, you find the newer JSON-based APIs. The newer APIs follow the ForgeRock common REST pattern creating, reading, updating, deleting, and querying resources.

    Examples in this section do not repeat the authentication shown in Authorization and Policy Management. For browser-based clients, you can rely on OpenAM cookies rather than construct the header in your application. Managing agent profiles, groups, realms, and users with these APIs of course require authorization. The examples shown in this section were performed with the token ID gained after authenticating as OpenAM administrator.

    Although the examples here show user management, you can use /json/agents, /json/groups, /json/realms in similar fashion. See "Realm Management" for examples related to realms.

    The following sections cover this JSON-based API:

Creating Identities

OpenAM lets administrators create a user profile by making an HTTP POST of the JSON representation of the profile to /json/subrealm/users/?_action=create. To add a user to the Top Level Realm, you do not need to specify the realm.

The following example shows an administrator creating a new user. The only required fields are username and userpassword. If no other name is provided, the entry you make for username defaults to both the user id and the user’s last name:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 --data \
 '{
   "username": "bjensen",
   "userpassword": "secret12",
   "mail": "bjensen@example.com"
 }' \
 https://openam.example.com:8443/openam/json/users/?_action=create
 {
    "username": "bjensen",
    "realm": "/",
    "uid": [
        "bjensen"
    ],
    "mail": [
        "bjensen@example.com"
    ],
    "sn": [
        "bjensen"
    ],
    "cn": [
        "bjensen"
    ],
    "inetuserstatus": [
        "Active"
    ],
    "dn": [
        "uid=bjensen,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "person",
        "sunIdentityServerLibertyPPService",
        "sunFederationManagerDataStore",
        "inetorgperson",
        "iPlanetPreferences",
        "iplanet-am-auth-configuration-service",
        "organizationalperson",
        "sunFMSAML2NameIdentifier",
        "inetuser",
        "iplanet-am-managed-person",
        "sunAMAuthAccountLockout",
        "iplanet-am-user-service",
        "top"
    ],
    "universalid": [
        "id=bjensen,ou=user,dc=openam,dc=forgerock,dc=org"
    ]
}

Alternatively, administrators can create user profiles with specific user IDs by doing an HTTP PUT of the JSON representation of the changes to /json/users/user-id, as shown in the following example:

$ curl \
 --request PUT \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 --header "Content-Type: application/json" \
 --header "If-None-Match: *" \
 --data \
 '{
   "username": "janedoe",
   "userpassword": "secret12",
   "mail": "janedoe@example.com"
 }' \
 https://openam.example.com:8443/openam/json/users/janedoe
 {
    "username": "janedoe",
    "realm": "/",
    "uid": [
        "janedoe"
    ],
    "mail": [
        "janedoe@example.com"
    ],
    "sn": [
        "janedoe"
    ],
    "cn": [
        "janedoe"
    ],
    "inetuserstatus": [
        "Active"
    ],
    "dn": [
        "uid=janedoe,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "devicePrintProfilesContainer",
        "person",
        "sunIdentityServerLibertyPPService",
        "inetorgperson",
        "sunFederationManagerDataStore",
        "iPlanetPreferences",
        "iplanet-am-auth-configuration-service",
        "organizationalperson",
        "sunFMSAML2NameIdentifier",
        "inetuser",
        "forgerock-am-dashboard-service",
        "iplanet-am-managed-person",
        "iplanet-am-user-service",
        "sunAMAuthAccountLockout",
        "top"
    ],
    "universalid": [
        "id=janedoe,ou=user,dc=openam,dc=forgerock,dc=org"
    ]
}

As shown in the examples, OpenAM returns the JSON representation of the profile on successful creation. On failure, OpenAM returns a JSON representation of the error including the HTTP status code. For example, version 2.0 of the CREST /json/users, /json/groups, and /json/agents endpoints return 403 if the user making the request is not authorized to do so.

The same HTTP POST and PUT mechanisms also work for other objects such as policy agent profiles and groups:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 --data \
 '{
    "username":"myAgent",
    "com.sun.identity.agents.config.fqdn.default":
      ["www.example.com"],
    "com.sun.identity.agents.config.repository.location":
      ["centralized"],
    "agenttype":["WebAgent"],
    "serverurl":["https://openam.example.com:8443/openam/"],
    "agenturl":["http://www.example.com:80/"],
    "userpassword":["password"],
    "com.sun.identity.agents.config.login.url":
      ["[0]=https://openam.example.com:8443/openam/UI/Login"],
    "com.sun.identity.agents.config.logout.url":
      ["[0]=https://openam.example.com:8443/openam/UI/Logout"],
    "sunidentityserverdevicestatus":["Active"]
 }' \
 https://openam.example.com:8443/openam/json/agents/?_action=create
 {
    "username": "myAgent",
    "realm": "/",
    "com.sun.identity.agents.config.fqdn.default": [
        "www.example.com"
    ],
    "com.sun.identity.agents.config.repository.location": [
        "centralized"
    ],
    "AgentType": [
        "WebAgent"
    ],
    "com.sun.identity.agents.config.login.url": [
        "[0]=https://openam.example.com:8443/openam/UI/Login"
    ],
    "com.sun.identity.agents.config.login.url":
        ["[0]=https://openam.example.com:8443/openam/UI/Login"
    ],
    "com.sun.identity.agents.config.logout.url":
        ["[0]=https://openam.example.com:8443/openam/UI/Logout"
    ],
    "sunIdentityServerDeviceStatus": [
        "Active"
    ]
}

The command output above has been truncated to be more readable. When you create a policy agent profile, OpenAM returns the full profile in JSON format.

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 --data '{
   "username":"newGroup",
   "uniquemember":["uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"]
 }' \
 https://openam.example.com:8443/openam/json/groups?_action=create
 {
    "username": "newGroup",
    "realm": "/",
    "uniqueMember": [
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "cn": [
        "newGroup"
    ],
    "dn": [
        "cn=newGroup,ou=groups,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "groupofuniquenames",
        "top"
    ],
    "universalid": [
        "id=newGroup,ou=group,dc=openam,dc=forgerock,dc=org"
    ]
}

$ curl \
 --request PUT \
 --header "If-None-Match: *" \
 --header "iPlanetDirectoryPro: AQIC5w...2NzEz*" \
 --header "Content-Type: application/json" \
 --data '{
   "username":"anotherGroup",
   "uniquemember":["uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"]
 }' \
 https://openam.example.com:8443/openam/json/groups/anotherGroup
 {
    "username": "anotherGroup",
    "realm": "/",
    "uniqueMember": [
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "cn": [
        "anotherGroup"
    ],
    "dn": [
        "cn=anotherGroup,ou=groups,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "groupofuniquenames",
        "top"
    ],
    "universalid": [
        "id=anotherGroup,ou=group,dc=openam,dc=forgerock,dc=org"
    ]
}
Reading Identities

OpenAM lets users and administrators read profiles by requesting an HTTP GET on /json/subrealm/users/user-id. This allows users and administrators to verify user data, status, and directory. If users or administrators see missing or incorrect information, they can write down the correct information and add it using "Updating Identities". To read a profile on the Top Level Realm, you do not need to specify the realm.

Users can review the data associated with their own accounts, and administrators can also read other user’s profiles.

If an administrator user is reading their own profile, an additional roles element, with a value of ui-admin is returned in the JSON response. The XUI verifies this element to grant or deny access to the OpenAM Console.

The following example shows an administrator accessing user data belonging to demo:

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/users/demo
{
    "username": "demo",
    "realm": "dc=openam,dc=forgerock,dc=org",
    "uid": [
        "demo"
    ],
    "sn": [
        "demo"
    ],
    "cn": [
        "demo"
    ],
    "inetuserstatus": [
        "Active"
    ],
    "dn": [
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "devicePrintProfilesContainer",
        "person",
        "sunIdentityServerLibertyPPService",
        "inetorgperson",
        "sunFederationManagerDataStore",
        "iPlanetPreferences",
        "iplanet-am-auth-configuration-service",
        "organizationalperson",
        "sunFMSAML2NameIdentifier",
        "inetuser",
        "forgerock-am-dashboard-service",
        "iplanet-am-managed-person",
        "iplanet-am-user-service",
        "sunAMAuthAccountLockout",
        "top"
    ],
    "universalid": [
        "id=demo,ou=user,dc=openam,dc=forgerock,dc=org"
    ]
}

Use the _fields query string parameter to restrict the list of attributes returned. This parameter takes a comma-separated list of JSON object fields to include in the result:

$ curl \
 --header "iPlanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/users/demo?_fields=username,uid
{"username":"demo","uid":["demo"]}

As shown in the examples, OpenAM returns the JSON representation of the profile on success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code.

Using HTTP GET to read also works for other objects such as agent profiles and groups:

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/agents/myAgent
{
    "username": "myAgent",
    "realm": "/",
    "com.sun.identity.agents.config.fqdn.default": [
        "www.example.com"
    ],
    "com.sun.identity.agents.config.repository.location": [
        "centralized"
    ],
    "AgentType": [
        "WebAgent"
    ],
    "com.sun.identity.agents.config.login.url": [
        "[0]=https://openam.example.com:8443/openam/UI/Login"
    ],
    "com.sun.identity.agents.config.login.url":
    [
        "[0]=https://openam.example.com:8443/openam/UI/Login"
    ],
    "com.sun.identity.agents.config.logout.url":
    [
        "[0]=https://openam.example.com:8443/openam/UI/Logout"
    ],
    "sunIdentityServerDeviceStatus": [
        "Active"
    ]
}

The command output above has been truncated to be more readable. When you read a policy agent profile, OpenAM returns the full profile in JSON format.

The _prettyPrint query string parameter can make the resulting JSON easier to read when you are viewing the resulting JSON directly:

$ curl \
 --header "iPlanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/groups/newGroup?_prettyPrint=true
{
    "username": "newGroup",
    "realm": "dc=openam,dc=forgerock,dc=org",
    "uniquemember": [
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "cn": [
        "newGroup"
    ],
    "dn": [
        "cn=newGroup,ou=groups,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "groupofuniquenames",
        "top"
    ],
    "universalid": [
        "id=newGroup,ou=group,dc=openam,dc=forgerock,dc=org"
    ]
}
Updating Identities

OpenAM lets users update their own profiles, and lets administrators update other users' profiles. To update an identity do an HTTP PUT of the JSON representation of the changes to /json/subrealm/users/user-id. To update a profile on the Top Level Realm, you do not need to specify the realm.

The following example shows how users can update their own profiles:

$ curl \
 --request PUT \
 --header "iplanetDirectoryPro: AQIC5...Y3MTAx*" \
 --header "Content-Type: application/json" \
 --data '{ "mail": "demo@example.com" }' \
 https://openam.example.com:8443/openam/json/users/demo
 {
    "username": "demo",
    "realm": "/",
    "uid": [
        "demo"
    ],
    "mail": [
        "demo@example.com"
    ],
    "sn": [
        "demo"
    ],
    "cn": [
        "demo"
    ],
    "inetuserstatus": [
        "Active"
    ],
    "dn": [
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "person",
        "sunIdentityServerLibertyPPService",
        "sunFederationManagerDataStore",
        "inetorgperson",
        "iPlanetPreferences",
        "iplanet-am-auth-configuration-service",
        "organizationalperson",
        "sunFMSAML2NameIdentifier",
        "inetuser",
        "iplanet-am-managed-person",
        "sunAMAuthAccountLockout",
        "iplanet-am-user-service",
        "top"
    ],
    "universalid": [
        "id=demo,ou=user,dc=openam,dc=forgerock,dc=org"
    ]
}

As shown in the example, OpenAM returns the JSON representation of the profile on success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code.

You can use HTTP PUT to update other objects as well, such as policy agent profiles and groups.

The following example updates a web policy agent profile:

$ curl \
 --request PUT \
 --header "iPlanetDirectoryPro: AQIC5...Y3MTAx*" \
 --header "Content-Type: application/json" \
 --data '{
      "sunIdentityServerDeviceStatus" : [ "Inactive" ]
 }' \
 https://openam.example.com:8443/openam/json/agents/myAgent?_prettyPrint=true
 {
     "username": "myAgent",
     "realm": "/",
     "com.sun.identity.agents.config.fqdn.default": [
         "www.example.com"
     ],
     "com.sun.identity.agents.config.repository.location": [
         "centralized"
     ],
     "AgentType": [
         "WebAgent"
     ],
     "com.sun.identity.agents.config.login.url": [
         "[0]=https://openam.example.com:8443/openam/UI/Login"
     ],
     "com.sun.identity.agents.config.login.url":
     [
         "[0]=https://openam.example.com:8443/openam/UI/Login"
     ],
     "com.sun.identity.agents.config.logout.url":
     [
         "[0]=https://openam.example.com:8443/openam/UI/Logout"
     ],
     "sunIdentityServerDeviceStatus": [
         "Inactive"
     ]
 }

The command output above has been truncated to be more readable. When you update a policy agent profile, OpenAM returns the full profile in JSON format.

Notice in the following example that updates newGroup the object class value is not included in the JSON sent to OpenAM:

$ curl \
 --request PUT \
 --header "iPlanetDirectoryPro: AQIC5...Y3MTAx*" \
 --header "Content-Type: application/json" \
 --data '{
    "uniquemember":[
        "uid=newUser,ou=people,dc=openam,dc=forgerock,dc=org",
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
    ]
 }' \
 https://openam.example.com:8443/openam/json/groups/newGroup
{
    "name": "newGroup",
    "realm": "/",
    "uniqueMember": [
        "uid=newUser,ou=people,dc=openam,dc=forgerock,dc=org",
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
    ],
    "cn": [
        "newGroup"
    ],
    "dn": [
        "cn=newGroup,ou=groups,dc=openam,dc=forgerock,dc=org"
    ],
    "objectclass": [
        "groupofuniquenames",
        "top"
    ],
    "universalid": [
        "id=newGroup,ou=group,dc=openam,dc=forgerock,dc=org"
    ]
}
Deleting Identities

OpenAM lets administrators delete a user profile by making an HTTP DELETE call to /json/subrealm/users/user-id. To delete a user from the Top Level Realm, you do not need to specify the realm.

The following example removes a user from the top level realm. Only administrators should delete users. The user id is the only field required to delete a user:

$ curl \
 --request DELETE \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/users/bjensen
{"success":"true"}

On success, OpenAM returns a JSON object indicating success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code.

You can use this same logic for other resources such as performing an HTTP DELETE of an agent profile or of a group:

$ curl \
 --request DELETE \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/agents/myOAuth2ClientAgent
{"success":"true"}
$ curl \
 --request DELETE \
 --header "iPlanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/groups/newGroup
{"success":"true"}

Deleting a user does not automatically remove any of the user’s sessions. If you are using stateful sessions, you can remove a user’s sessions by checking for any sessions for the user and then removing them using the console’s Sessions tab. If you are using stateless sessions, you cannot remove users' sessions; you must wait for the sessions to expire.

Listing Identities

OpenAM lets administrators list identities by making an HTTP GET call to /json/subrealm/users/?_queryId=*. To query the Top Level Realm, you do not need to specify the realm:

$ curl \
--header "iPlanetDirectoryPro: AQIC5w...2NzEz*" \
"https://openam.example.com:8443/openam/json/users?_queryId=*"
{
  "result": [
    {
      "username": "amAdmin",
      "realm": "dc=openam,dc=forgerock,dc=org",
      "sunIdentityMSISDNNumber": [],
      "mail": [],
      "sn": [
        "amAdmin"
      ],
      "givenName": [
        "amAdmin"
      ],
      "universalid": [
        "id=amAdmin,ou=user,dc=openam,dc=forgerock,dc=org"
      ],
      "cn": [
        "amAdmin"
      ],
      "iplanet-am-user-success-url": [],
      "telephoneNumber": [],
      "roles": [
        "ui-global-admin",
        "ui-realm-admin"
      ],
      "iplanet-am-user-failure-url": [],
      "inetuserstatus": [
        "Active"
      ],
      "postalAddress": [],
      "dn": [
        "uid=amAdmin,ou=people,dc=openam,dc=forgerock,dc=org"
      ],
      "employeeNumber": [],
      "iplanet-am-user-alias-list": []
    },
    {
      "username": "demo",
      "realm": "dc=openam,dc=forgerock,dc=org",
      "uid": [
        "demo"
      ],
      "createTimestamp": [
        "20160108155628Z"
      ],
      "inetUserStatus": [
        "Active"
      ],
      "mail": [
        "demo.user@example.com"
      ],
      "sn": [
        "demo"
      ],
      "cn": [
        "demo"
      ],
      "objectClass": [
        "devicePrintProfilesContainer",
        "person",
        "sunIdentityServerLibertyPPService",
        "sunFederationManagerDataStore",
        "inetorgperson",
        "oathDeviceProfilesContainer",
        "iPlanetPreferences",
        "iplanet-am-auth-configuration-service",
        "sunFMSAML2NameIdentifier",
        "organizationalperson",
        "inetuser",
        "kbaInfoContainer",
        "forgerock-am-dashboard-service",
        "iplanet-am-managed-person",
        "iplanet-am-user-service",
        "sunAMAuthAccountLockout",
        "top"
      ],
      "kbaInfo": [
        {
          "questionId": "2",
          "answer": {
            "$crypto": {
              "value": {
                "algorithm": "SHA-256",
                "data": "VXGtsnjJMC...MQJ/goU5hkfF"
              },
              "type": "salted-hash"
            }
          }
        },
        {
          "questionId": "1",
          "answer": {
            "$crypto": {
              "value": {
                "algorithm": "SHA-256",
                "data": "cfYYzi9U...rVfFl0Tdw0iX"
              },
              "type": "salted-hash"
            }
          }
        }
      ],
      "dn": [
        "uid=demo,ou=people,dc=openam,dc=forgerock,dc=org"
      ],
      "universalid": [
        "id=demo,ou=user,dc=openam,dc=forgerock,dc=org"
      ],
      "modifyTimestamp": [
        "20160113010610Z"
      ]
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": -1
}

The users endpoint also supports the _queryFilter parameter to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

The _queryId=* parameter also works for other types of objects, such as agent profiles and groups:

$ curl \
 --header "iPlanetDirectoryPro: AQIC5w...2NzEz*" \
 "https://openam.example.com:8443/openam/json/agents?_queryId=*"
{
  "result" : [ "wsp", "wsc", "agentAuth", "SecurityTokenService" ],
  "resultCount" : 4,
  "pagedResultsCookie" : null,
  "remainingPagedResults" : -1
}
$ curl \
 --header "iPlanetDirectoryPro: AQIC5w...2NzEz*" \
 "https://openam.example.com:8443/openam/json/groups?_queryId=*"
{
  "result" : [ "newGroup", "anotherGroup" ],
  "resultCount" : 2,
  "pagedResultsCookie" : null,
  "remainingPagedResults" : -1
}

As the result lists include all objects, this capability to list identity names is mainly useful in testing.

As shown in the examples, OpenAM returns the JSON representation of the resource list if successful. On failure, OpenAM returns a JSON representation of the error including the HTTP status code.

If you only have access to the iPlanetDirectoryPro session cookie, you can retrieve the user ID by performing an HTTP POST operation on the /json/users endpoint using the idFromSession action:

$ curl \
 --verbose \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iplanetDirectoryPro: AQIC5wM2LY4SfczUFNs-TJwFrCVAKgR0NulIAyNaIkQmjis.*AAJTSQACMDEA
 AlNLABQtNTQ3NDE2Njc5ODk4MjYzMzA2MQ..*" \
 http://openam.example.com:8080/openam/json/users?_action=idFromSession

{
  "id":"demo",
  "realm":"/",
  "dn":"id=demo,ou=user,dc=openam,dc=forgerock,dc=org",
  "successURL":"/openam/console",
  "fullLoginURL":null
}
Changing Passwords

Users other than the top-level administrator can change their own passwords with an HTTP POST to /json/subrealm/users/username?_action=changePassword including the new password as the value of userpassword in the request data.

Changing the top-level administrator’s password requires a more complex procedure. See "Administering the amadmin Account" in the Administration Guide for more information.

Users must provide the current password, which is set in the request as the value of the currentpassword.

For cases where users have forgotten their password, see "Retrieving Forgotten Usernames" instead.

The following example shows a successful request to change the demo user’s password to password:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iPlanetDirectoryPro: AQIC5w...NTcy*" \
 --data '{
     "currentpassword":"changeit",
     "userpassword":"password"
 }' \
 https://openam.example.com:8443/openam/json/users/demo?_action=changePassword
{}

On success, the response is an empty JSON object {} as shown in the example.

On failure, OpenAM returns a JSON representation of the error including the HTTP status code. See also "REST Status Codes" for more information.

Administrators can change non-administrative users' passwords with an HTTP PUT to /json/subrealm/users/username including the new password as the value of userpassword in the request data.

Unlike users, administrators do not provide users' current passwords when changing passwords.

The following example shows a successful request by an administrator to change the demo user’s password to cangetin:

$ curl \
 --request PUT \
 --header "iPlanetDirectoryPro: AQIC5w...NTcy*" \
 --header "Content-Type: application/json" \
 --data '{
     "userpassword":"cangetin"
 }' \
 https://openam.example.com:8443/openam/json/users/demo
 {
    "username":"demo",
    "realm":"/",
    "uid":[
        "demo"
    ],
    "universalid":[
        "id=demo,ou=user,dc=example,dc=com"
    ],
    "objectClass":[
        "iplanet-am-managed-person",
        "inetuser","sunFederationManagerDataStore",
        "sunFMSAML2NameIdentifier",
        "devicePrintProfilesContainer",
        "inetorgperson",
        "sunIdentityServerLibertyPPService",
        "iPlanetPreferences",
        "iplanet-am-user-service",
        "forgerock-am-dashboard-service",
        "organizationalperson",
        "top",
        "sunAMAuthAccountLockout",
        "person",
        "oathDeviceProfilesContainer",
        "iplanet-am-auth-configuration-service"
    ],
    "inetUserStatus":[
        "Active"
    ],
    "dn":[
        "uid=demo,ou=people,dc=example,dc=com"
    ],
    "sn":[
        "demo"
    ],
    "cn":[
        "demo"
    ],
    "modifyTimestamp":[
        "20151006213634Z"
    ],
    "createTimestamp":[
        "20151005134244Z"
    ]
}

As shown in the example, OpenAM returns the JSON representation of the profile on success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code. See also "REST Status Codes" for more information.

Realm Management

This section shows how to create, read, update, and delete realms using the RESTful APIs:

Default Parameters for Realms

Realms have a number of fields entered with the default loading. The following table provides information on what the default realm settings are, and whether they can be updated, added, or deleted when updating a realm.

Realm Parameters for JSON-based API
Realm Parameter Default Purpose

realm

None - the only required field to add a realm

The name of the realm

Example: `myRealm`

sunOrganizationStatus

Active

The status of the realm

`Active` or `Inactive`

sunOrganizationAliases

None

Any applicable aliases associated with the realm. Be aware that an alias can only be used once. Entering an alias used by another realm will remove the alias from that realm and you will lose configuration.

Example: `opensso.example.com`

serviceNames

sunAMAuthHOTPService iPlanetAMAuthConfiguration sunAMAuthFederationService sunIdentityRepositoryService iPlanetAMPolicyConfigService iPlanetAMAuthService iPlanetAMAuthLDAPService sunAMAuthDataStoreService sunAMAuthSAEService sunAMDelegationService sunAMAuthWSSAuthModuleService iPlanetAMAuthOATHService

Services needed for the realm, including authentication modules

Creating Realms

OpenAM lets administrators create a realm by making an HTTP POST of the JSON representation of the profile to /json/realms/?_action=create.

You can create realms using an HTTP POST of the JSON representation of the profile to /json/realms/?_action=create, as shown in the following example. The only required data field is realm:

$ curl \
 --request POST \
 --header "Content-Type: application/json" \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 --data '{ "realm": "myRealm" }' \
 https://openam.example.com:8443/openam/json/realms/?_action=create
{"realmCreated":"/myRealm"}

Do not use the names of OpenAM REST endpoints as the name of a realm. The OpenAM REST endpoint names that should not be used includes: users, groups, realms, policies and applications.

You can also set the sunOrganizationAliases parameter, but it can only be assigned to one realm (usually the top level realm). Before setting this parameter, make sure it is not already assigned elsewhere. If you remove it from another realm, you will lose your configuration.

Alternatively, administrators can create realms by the specific realm name using the HTTP PUT of the JSON representation of the changes to /json/realms/realm-id, as shown in the following example:

$ curl \
 --request PUT \
 --header "If-None-Match: *" \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 --header "Content-Type: application/json" \
 --data '{ }' \
 https://openam.example.com:8443/openam/json/realms/myRealm

 {
  "realmCreated": "/myRealm"
 }

OpenAM returns an HTTP 201 Created status code, and the JSON representation of the realm on success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code. For example, if the If-None-Match header with a value of * is absent, an HTTP 404 Not Found status code is returned.

Reading Realms

OpenAM lets administrators read realms by requesting an HTTP GET on /json/realms/realm-id. This allows administrators to review all active realm services for the realm, like policy configuration and modules. If users or administrators see missing information (such as Active status) or incorrect information, they can write down the correct information and add it using "Updating Realms".

The following example shows an administrator receiving information about a realm called myRealm:

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/realms/myRealm
{
    "serviceNames":[
      "sunAMAuthHOTPService",
      "iPlanetAMAuthConfiguration",
      "sunAMAuthFederationService",
      "sunIdentityRepositoryService",
      "iPlanetAMPolicyConfigService",
      "iPlanetAMAuthService",
      "iPlanetAMAuthLDAPService",
      "sunAMAuthDataStoreService",
      "sunAMAuthSAEService",
      "sunAMDelegationService",
      "sunAMAuthWSSAuthModuleService",
      "iPlanetAMAuthOATHService"
    ]
}

As shown in the example, OpenAM returns the JSON representation of the profile on success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code.

To read the top-level realm, use toplevelrealm with the realms endpoint:

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/realms/toplevelrealm
{
      "serviceNames" : [
       "sunAMAuthFederationService",
       "sunEntitlementIndexes",
       "iPlanetAMAuthService",
       "sunAMAuthDataStoreService",
       "sunAMAuthWSSAuthModuleService",
       "sunAMDelegationService",
       "iPlanetAMAuthOATHService",
       "iPlanetAMAuthConfiguration",
       "sunAMAuthHOTPService",
       "sunIdentityRepositoryService",
       "iPlanetAMPolicyConfigService",
       "iPlanetAMAuthLDAPService",
       "sunEntitlementService",
       "iPlanetAMPolicyService",
       "sunAMAuthSAEService",
       "AgentService" ]
}

If the realm you want to read is not an immediate subrealm of the top-level realm, specify its parent realm to the left of realms in the URL, and specify the realm’s final qualifier to the right of realms. For example, to read the /myRealm/myRealmsChildRealm realm:

$ curl \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/myRealm/realms/myRealmsChildRealm
{
      "serviceNames" : [
       "sunAMAuthHOTPService",
       "iPlanetAMAuthConfiguration",
       "sunAMAuthFederationService",
       "sunIdentityRepositoryService",
       "iPlanetAMPolicyConfigService",
       "iPlanetAMAuthService",
       "iPlanetAMAuthLDAPService",
       "sunAMAuthDataStoreService",
       "sunAMAuthSAEService",
       "sunAMDelegationService",
       "sunAMAuthWSSAuthModuleService",
       "iPlanetAMAuthOATHService"
      ]
}
Listing Realms

To list a realm and its subrealms, perform an HTTP GET on the endpoint, set the _queryFilter query string parameter as in the following example, which lists the top-level realm and all of its subrealms:

$ curl \
 --header "iPlanetDirectoryPro: AQIC5..." \
 https://openam.example.com:8443/openam/json/realms?_queryFilter=true
 {
     "result" : [ "/", "/myRealm", "/myRealm/myRealmsChildRealm" ],
     "resultCount" : 3,
     "pagedResultsCookie" : null,
     "remainingPagedResults" : -1
 }

You can start listing realms from below the top-level realm by placing the starting realm name in the URL. The following example lists the realm myRealm and all of its subrealms:

$ curl \
 --header "iPlanetDirectoryPro: AQIC5..." \
 https://openam.example.com:8443/openam/json/myRealm/realms?_queryFilter=true
 {
     "result" : [ "/myRealm", "/myRealm/myRealmsChildRealm" ],
     "resultCount" : 2,
     "pagedResultsCookie" : null,
     "remainingPagedResults" : -1
 }
Updating Realms

OpenAM lets administrators update realms. To update a realm, do an HTTP PUT of the JSON representation of the changes to /json/realms/realm-id.

The following example shows how to update a realm called myRealm. The example command sets the realm’s status to Inactive:

$ curl \
 --request PUT \
 --header "iplanetDirectoryPro: AQIC5...Y3MTAx*" \
 --header "Content-Type: application/json" \
 --data '{ "sunOrganizationStatus": "Inactive" }' \
 https://openam.example.com:8443/openam/json/realms/myRealm

OpenAM returns the JSON representation of the profile on success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code.

Deleting Realms

OpenAM lets administrators delete a realm by making an HTTP DELETE call to /json/realms/realm-id.

The following example deletes a realm called myRealm. The top level realm cannot be deleted. Only administrators should delete realms. The name of the realm is the only field required to delete the realm.

Make sure that you do not have any information you need within a realm before deleting it. Once a realm is deleted, the only way to restore it is to return to a backed up deployment of OpenAM:

$ curl \
 --request DELETE \
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/realms/myRealm
{"success":"true"}

On success, OpenAM returns a JSON object indicating success. On failure, OpenAM returns a JSON representation of the error including the HTTP status code.

If the realm you want to delete is not an immediate subrealm of the top-level realm, specify its parent realm to the left of realms in the URL, and specify the realm’s final qualifier to the right of realms. For example, to delete the /myRealm/myRealmsChildRealm realm:

$ curl \
 --request DELETE
 --header "iplanetDirectoryPro: AQIC5w...2NzEz*" \
 https://openam.example.com:8443/openam/json/myRealm/realms/myRealmsChildRealm
 { "success":"true" }

RESTful Script Management

This section shows you how to manage scripts used for client-side and server-side scripted authentication, custom policy conditions, and handling OpenID Connect claims by using the REST API.

For information on managing scripts by using the OpenAM console, see "Managing Scripts" in the Administration Guide. For information on configuring script settings, see "Scripting" in the Reference. OpenAM provides the scripts REST endpoint for the following:

User-created scripts are realm-specific, hence the URI for the scripts' API can contain a realm component, such as /json{/realm}/scripts. If the realm is not specified in the URI, the top level realm is used.

OpenAM includes some global example scripts that can be used in any realm.

Scripts are represented in JSON and take the following form. Scripts are built from standard JSON objects and values (strings, numbers, objects, sets, arrays, true, false, and null). Each script has a system-generated universally unique identifier (UUID), which must be used when modifying existing scripts. Renaming a script will not affect the UUID:

{
    "_id": "7e3d7067-d50f-4674-8c76-a3e13a810c33",
    "name": "Scripted Module - Server Side",
    "description": "Default global script for server side Scripted Authentication Module",
    "script": "dmFyIFNUQVJUX1RJ...",
    "language": "JAVASCRIPT",
    "context": "AUTHENTICATION_SERVER_SIDE",
    "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1433147666269,
    "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1433147666269
}

The values for the fields shown in the example above are explained below:

_id

The UUID that OpenAM generates for the script.

name

The name provided for the script.

description

An optional text string to help identify the script.

script

The source code of the script. The source code is in UTF-8 format and encoded into Base64.

For example, a script such as the following:

var a = 123;
var b = 456;

When encoded into Base64 becomes:

dmFyIGEgPSAxMjM7IA0KdmFyIGIgPSA0NTY7
language

The language the script is written in - JAVASCRIPT or GROOVY.

Language Support per Context
Script Context Supported Languages

POLICY_CONDITION

JAVASCRIPT, GROOVY

AUTHENTICATION_SERVER_SIDE

JAVASCRIPT, GROOVY

AUTHENTICATION_CLIENT_SIDE

JAVASCRIPT

OIDC_CLAIMS

JAVASCRIPT, GROOVY

context

The context type of the script.

Supported values are:

POLICY_CONDITION

Policy Condition

AUTHENTICATION_SERVER_SIDE

Server-side Authentication

AUTHENTICATION_CLIENT_SIDE

Client-side Authentication

Client-side scripts must be written in JavaScript.

OIDC_CLAIMS

OIDC Claims

createdBy

A string containing the universal identifier DN of the subject that created the script.

creationDate

An integer containing the creation date and time, in ISO 8601 format.

lastModifiedBy

A string containing the universal identifier DN of the subject that most recently updated the resource type.

If the script has not been modified since it was created, this property will have the same value as createdBy.

lastModifiedDate

A string containing the last modified date and time, in ISO 8601 format.

If the script has not been modified since it was created, this property will have the same value as creationDate.

Querying Scripts

To list all the scripts in a realm, as well as any global scripts, perform an HTTP GET to the /json{/realm}/scripts endpoint with a _queryFilter parameter set to true.

If the realm is not specified in the URL, OpenAM returns scripts in the top level realm, as well as any global scripts.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/myrealm/scripts?_queryFilter=true
{
  "result": [
    {
      "_id": "9de3eb62-f131-4fac-a294-7bd170fd4acb",
      "name": "Scripted Policy Condition",
      "description": "Default global script for Scripted Policy Conditions",
      "script": "LyoqCiAqIFRoaXMg...",
      "language": "JAVASCRIPT",
      "context": "POLICY_CONDITION",
      "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
      "creationDate": 1433147666269,
      "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
      "lastModifiedDate": 1433147666269
    },
    {
      "_id": "7e3d7067-d50f-4674-8c76-a3e13a810c33",
      "name": "Scripted Module - Server Side",
      "description": "Default global script for server side Scripted Authentication Module",
      "script": "dmFyIFNUQVJUX1RJ...",
      "language": "JAVASCRIPT",
      "context": "AUTHENTICATION_SERVER_SIDE",
      "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
      "creationDate": 1433147666269,
      "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
      "lastModifiedDate": 1433147666269
    }
  ],
  "resultCount": 2,
  "pagedResultsCookie": null,
  "remainingPagedResults": -1
}

Additional query strings can be specified to alter the returned results. For more information, see "Filtering, Sorting, and Paging Results".

Supported _queryFilter Fields and Operators
Field Supported Operators

_id

Equals (eq), Contains (co), Starts with (sw)

name

Equals (eq), Contains (co), Starts with (sw)

description

Equals (eq), Contains (co), Starts with (sw)

script

Equals (eq), Contains (co), Starts with (sw)

language

Equals (eq), Contains (co), Starts with (sw)

context

Equals (eq), Contains (co), Starts with (sw)

Reading a Script

To read an individual script in a realm, perform an HTTP GET using the /json{/realm}/scripts endpoint, specifying the UUID in the URL.

To read a script in the top-level realm, or to read a built-in global script, do not specify a realm in the URL.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/myrealm/scripts/9de3eb62-f131-4fac-a294-7bd170fd4acb
{
    "_id": "9de3eb62-f131-4fac-a294-7bd170fd4acb",
    "name": "Scripted Policy Condition",
    "description": "Default global script for Scripted Policy Conditions",
    "script": "LyoqCiAqIFRoaXMg...",
    "language": "JAVASCRIPT",
    "context": "POLICY_CONDITION",
    "createdBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1433147666269,
    "lastModifiedBy": "id=dsameuser,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1433147666269
}

Validating a Script

To validate a script, perform an HTTP POST using the /json{/realm}/scripts endpoint, with an _action parameter set to validate. Include a JSON representation of the script and the script language, JAVASCRIPT or GROOVY, in the POST data.

The value for script must be in UTF-8 format and then encoded into Base64.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: AQIC5..." \
--data '{
    "script": "dmFyIGEgPSAxMjM7dmFyIGIgPSA0NTY7Cg==",
    "language": "JAVASCRIPT"
}' \
https://openam.example.com:8443/openam/json/myrealm/scripts/?_action=validate
{
  "success": true
}

If the script is valid the JSON response contains a success key with a value of true.

If the script is invalid the JSON response contains a success key with a value of false, and an indication of the problem and where it occurs, as shown below:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: AQIC5..." \
--data '{
    "script": "dmFyIGEgPSAxMjM7dmFyIGIgPSA0NTY7ID1WQUxJREFUSU9OIFNIT1VMRCBGQUlMPQo=",
    "language": "JAVASCRIPT"
}' \
https://openam.example.com:8443/openam/json/myrealm/scripts/?_action=validate
{
    "success": false,
    "errors": [
        {
            "line": 1,
            "column": 27,
            "message": "syntax error"
        }
    ]
}

Creating a Script

To create a script in a realm, perform an HTTP POST using the /json{/realm}/scripts endpoint, with an _action parameter set to create. Include a JSON representation of the script in the POST data.

The value for script must be in UTF-8 format and then encoded into Base64.

If the realm is not specified in the URL, OpenAM creates the script in the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: AQIC5..." \
--data '{
    "name": "MyJavaScript",
    "script": "dmFyIGEgPSAxMjM7CnZhciBiID0gNDU2Ow==",
    "language": "JAVASCRIPT",
    "context": "POLICY_CONDITION",
    "description": "An example script"
}' \
https://openam.example.com:8443/openam/json/myrealm/scripts/?_action=create
{
    "_id": "0168d494-015a-420f-ae5a-6a2a5c1126af",
    "name": "MyJavaScript",
    "description": "An example script",
    "script": "dmFyIGEgPSAxMjM7CnZhciBiID0gNDU2Ow==",
    "language": "JAVASCRIPT",
    "context": "POLICY_CONDITION",
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1436807766258,
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1436807766258
}

Updating a Script

To update an individual script in a realm, perform an HTTP PUT using the /json{/realm}/scripts endpoint, specifying the UUID in both the URL and the PUT body. Include a JSON representation of the updated script in the PUT data, alongside the UUID.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--header "iPlanetDirectoryPro: AQIC5..." \
--header "Content-Type: application/json" \
--request PUT \
--data '{
    "name": "MyUpdatedJavaScript",
    "script": "dmFyIGEgPSAxMjM7CnZhciBiID0gNDU2Ow==",
    "language": "JAVASCRIPT",
    "context": "POLICY_CONDITION",
    "description": "An updated example script configuration"
}' \
https://openam.example.com:8443/openam/json/myrealm/scripts/0168d494-015a-420f-ae5a-6a2a5c1126af
{
    "_id": "0168d494-015a-420f-ae5a-6a2a5c1126af",
    "name": "MyUpdatedJavaScript",
    "description": "An updated example script configuration",
    "script": "dmFyIGEgPSAxMjM7CnZhciBiID0gNDU2Ow==",
    "language": "JAVASCRIPT",
    "context": "POLICY_CONDITION",
    "createdBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "creationDate": 1436807766258,
    "lastModifiedBy": "id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org",
    "lastModifiedDate": 1436808364681
}

Deleting a Script

To delete an individual script in a realm, perform an HTTP DELETE using the /json{/realm}/scripts endpoint, specifying the UUID in the URL.

If the realm is not specified in the URL, OpenAM uses the top level realm.

The iPlanetDirectoryPro header is required and should contain the SSO token of an administrative user, such as amAdmin, who has access to perform the operation.

$ curl \
--request DELETE \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/myrealm/scripts/0168d494-015a-420f-ae5a-6a2a5c1126af
{}

RESTful Troubleshooting Information Recording

This section shows you how to start, stop, and get the status of a troubleshooting recording event using the REST API. OpenAM provides the /json/records REST endpoint for the following:

You must authenticate to OpenAM as an administrative user to obtain an SSO token prior to calling the /json/records REST endpoint. You then pass the SSO token in the iPlanetDirectoryPro header as proof of authentication.

You can also record troubleshooting information by using the ssoadm command. For more information, see "Recording Troubleshooting Information" in the Administration Guide.

The curl command output in the examples in this section is indented for ease of reading. The actual output is not indented, and the actions available from the /json/records endpoint do not support the _prettyPrint parameter.

Starting a Recording Event

To start a recording event, perform an HTTP POST using the /json/records endpoint, specifying the _action=start parameter in the URL. Specify a JSON payload identical in format to the input file for the ssoadm start-recording command, as described in "The Recording Control File" in the Administration Guide:

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: AQIC5..." \
--data ' {
  "issueID": 103572,
  "referenceID": "policyEvalFails",
  "description": "Troubleshooting artifacts in support of case 103572",
  "zipEnable": true,
  "configExport": {
   "enable": true,
   "password": "5x2RR70",
   "sharePassword": false
  },
  "debugLogs": {
   "debugLevel": "MESSAGE",
   "autoStop": {
    "time":  {
     "timeUnit": "SECONDS",
     "value": 15
    },
    "fileSize": {
     "sizeUnit": "GB",
     "value": 1
    }
   }
  },
  "threadDump" : {
   "enable": true,
   "delay" :  {
    "timeUnit": "SECONDS",
    "value": 5
   }
  }
 }' \
https://openam.example.com:8443/openam/json/records?_action=start
{
 "recording":true,
 "record":{
  "issueID":103572,
  "referenceID":"policyEvalFails",
  "description":"Troubleshooting artifacts in support of case 103572",
  "zipEnable":true,
  "threadDump":{
   "enable":true,
   "delay":{
    "timeUnit":"SECONDS",
    "value":5
   }
  },
  "configExport":{
   "enable":true,
   "password":"xxxxxx",
   "sharePassword":false
  },
  "debugLogs":{
   "debugLevel":"message",
   "autoStop":{
    "time":{
     "timeUnit":"MILLISECONDS",
     "value":15000
    },
    "fileSize":{
     "sizeUnit":"KB",
     "value":1048576
    }
   }
  },
  "status":"RUNNING",
  "folder":"/opt/demo/openam/config/openam/debug/record/103572/policyEvalFails/"
 }
}

Getting the Status of a Recording Event

To get the status of a recording event, perform an HTTP POST using the /json/records endpoint, specifying the _action=status parameter in the URL:

$ curl \
--request POST \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/records?_action=status

If there is no active recording event, the following output appears:

{
  "recording":false
}

If there is an active recording event, output similar to the following appears:

{
 "recording":true,
 "record":{
  "issueID":103572,
  "referenceID":"policyEvalFails",
  "description":"Troubleshooting artifacts in support of case 103572",
  "zipEnable":true,
  "threadDump":{
   "enable":true,
   "delay":{
    "timeUnit":"SECONDS",
    "value":5
   }
  },
  "configExport":{
   "enable":true,
   "password":"xxxxxx",
   "sharePassword":false
  },
  "debugLogs":{
   "debugLevel":"message",
   "autoStop":{
    "time":{
     "timeUnit":"MILLISECONDS",
     "value":15000
    },
    "fileSize":{
     "sizeUnit":"KB",
     "value":1048576
    }
   }
  },
  "status":"RUNNING",
  "folder":"/opt/demo/openam/config/openam/debug/record/103572/policyEvalFails/"
 }
}

Stopping a Recording Event

To stop a recording event, perform an HTTP POST using the /json/records endpoint, specifying the _action=stop parameter in the URL:

$ curl \
--request POST \
--header "iPlanetDirectoryPro: AQIC5..." \
https://openam.example.com:8443/openam/json/records?_action=stop

If there is no active recording event, OpenAM returns a 400 error code.

If there is an active recording event, output similar to the following appears:

{
 "recording":false,
 "record":{
  "issueID":103572,
  "referenceID":"policyEvalFails",
  "description":"Troubleshooting artifacts in support of case 103572",
  "zipEnable":true,
  "threadDump":{
   "enable":true,
   "delay":{
    "timeUnit":"SECONDS",
    "value":5
   }
  },
  "configExport":{
   "enable":true,
   "password":"xxxxxx",
   "sharePassword":false
  },
  "debugLogs":{
   "debugLevel":"message",
   "autoStop":{
    "time":{
     "timeUnit":"MILLISECONDS",
     "value":15000
    },
    "fileSize":{
     "sizeUnit":"KB",
     "value":1048576
    }
   }
  },
  "status":"STOPPED",
  "folder":"/opt/demo/openam/config/openam/debug/record/103572/policyEvalFails/"
 }
}

Using the OpenAM Java SDK

This section introduces OpenAM Java SDK. OpenAM Java SDK is delivered with the full version of OpenAM, OpenAM-15.1.5.zip.

Installing OpenAM Client SDK Samples

The full OpenAM download, OpenAM-15.1.5.zip, contains the Java Client SDK library, ClientSDK-15.1.5.jar, as well as samples for use on the command line in ExampleClientSDK-CLI-15.1.5.zip, and samples in a web application, ExampleClientSDK-WAR-15.1.5.war. The OpenAM Java SDK API Specification provides a reference to the public APIs.

To Deploy the Sample Web Application

The sample web application deploys in your container to show you the client SDK samples in action.

  1. Deploy the .war in your Java web application container such as Apache Tomcat or JBoss.

    $ cp ExampleClientSDK-WAR-{openam-version}.war /path/to/tomcat/webapps/client.war
  2. If you have run this procedure before, make sure to deploy a fresh copy of the .war file to a different location, such as /path/to/tomcat/webapps/client1.war

  3. Browse to the location where you deployed the client, and configure the application to access OpenAM using the application user name, UrlAccessAgent, and password configured when you set up OpenAM.

    config client sdk war

    Use the following hints to complete the configuration.

    Server Protocol

    Protocol to access OpenAM (http or https)

    Server Host

    Fully qualified domain name for OpenAM, such as openam.example.com

    Server Port

    OpenAM port number such as 8080 or 8443

    Server Deployment URI

    URI entry point to OpenAM such as /openam

    Debug directory

    Where to write the debug messages for the client samples

    Application user name

    An user agent configured to access OpenAM, such as UrlAccessAgent set up when OpenAM was installed

    Application user password

    The user agent password

    The sample client writes configuration information under $HOME/OpenAMClient/, where $HOME is that of the user running the web application container.

  4. Verify that you have properly configured the sample web application.

    1. In another browser tab page of the same browser instance, login to OpenAM as the OpenAM Administrator, amadmin.

      This signs you into OpenAM, storing the cookie in your browser.

    2. On the Samples tab page, click the link under Single Sign On Token Verification Servlet.

      If the sample web application is properly configured, you should see something like the following text in your browser.

      SSOToken host name: 127.0.0.1
      SSOToken Principal name: id=amadmin,ou=user,dc=openam,dc=forgerock,dc=org
      Authentication type used: DataStore
      IPAddress of the host: 127.0.0.1
      SSO Token validation test succeeded
      The token id is AQIC5...CMDEAAlNLABQtODY0Mjc5MDUwNDQzOTA2MzYxNg..*
      ...
      User Attributes: {... givenName=[amAdmin], ...roles=[Top-level Admin Role], ...}
To Build the Command-Line Sample Applications

Follow these steps to set up the command-line examples.

  1. Unpack the sample applications and related libraries.

    $ mkdir sdk && cd sdk
    $ unzip ~/Downloads/ExampleClientSDK-CLI-15.1.5.zip
  2. Configure the samples to access OpenAM.

    $ sh scripts/setup.sh
    Debug directory (make sure this directory exists): /Users/me/openam/openam/debug
    Application user (e.g. URLAccessAgent) password: secret12
    Protocol of the server: http
    Host name of the server: openam.example.com
    Port of the server: 8080
    Server's deployment URI: openam
    Naming URL (hit enter to accept default value,
          http://openam.example.com:8080/openam/namingservice):
    $
  3. Verify that you have properly configured the samples.

    $ sh scripts/Login.sh
    Realm (e.g. /): /
    Login module name (e.g. DataStore or LDAP): DataStore
    Login locale (e.g. en_US or fr_FR): fr_FR
    DataStore: Obtained login context
    Nom d'utilisateur :demo
    Mot de passe :changeit
    Login succeeded.
    Logged Out!!

About the OpenAM Java SDK

After installing the Java SDK command line samples, you see the following content.

  • lib/: SDK and other libraries

  • resources/: properties configuration files for the SDK and samples

  • scripts/: scripts to run the samples

  • source/: sample code

After deploying the Java SDK web application archive, you find the following content where the .war file was unpacked.

  • META-INF/: build information

  • WEB-INF/: sample classes and libraries

  • console/: images for sample UI

  • index.html: sample home page

  • keystore.jks: OpenAM test certificate, alias: test, keystore password: changeit

  • policy/: Policy Evaluator Client Sample page

  • saml2/: Secure Attribute Exchange example

  • sample.css: sample styles

  • sm/: Service Configuration sample

  • um/: User Profile sample

Registering Your Java SDK Client to Shut Down Gracefully

When writing a client using the OpenAM Java SDK, make sure you register hooks to make sure the application can be shut down gracefully. How you register for shutdown depends on the type of application.

  • For Java EE applications, make sure the OpenAM client SDK shuts down successfully by including the following context listener in your application’s web.xml file.

    <listener>
      <listener-class>
         com.sun.identity.common.ShutdownServletContextListener
      </listener-class>
    </listener>
  • For standalone applications, set the following JVM property.

    -Dopenam.runtime.shutdown.hook.enabled=true

Authenticating Using OpenAM Java SDK

This section looks at authentication with the OpenAM Java SDK and at the sample client, Login.java, which demonstrates authenticating to OpenAM from a client application, provided a realm, user name, and password. This is the sample you ran to test installation of the command-line SDK samples. The class shown in this section is com.sun.identity.samples.authentication.Login.

Before you continue, make sure that the packages described in "Installing OpenAM Client SDK Samples" are installed. With OpenAM, your client application performs the following steps to handle authentication.

  1. Sets up an AuthContext, based on the realm in which the user authenticates.

  2. Starts the login process by calling the AuthContext login() method.

  3. Handling authentication callbacks to retrieve credentials from the user who is authenticating.

    Your application loops through the authentication callbacks by using the AuthContext getRequirements() and hasMoreRequirements() methods. Each time it finishes populating a callback with the credentials retrieved, your application calls submitRequirements() to send the credentials to OpenAM’s Authentication Service.

  4. After handling all authentication callbacks, your application calls the AuthContext getStatus() method.

    On login success, OpenAM sets up an SSO token that holds information about the authentication, and also about the user’s environment and session.

  5. When the user logs out, your application can end the session by calling the AuthContext logout() method.

The AuthContext class is provided by the com.sun.identity.authentication package, part of the OpenAM client API. Callback classes are provided by the javax.security.auth.callback package, which provides callbacks for choices, confirmations, locales, names, passwords, text input, and text output.

See the OpenAM Public API JavaDoc for reference.

As the sample client gets the realm (called organization in the sample), locale, and authentication module to set up the authentication context, there is not need for a language callback to get the local afterwards. The Login.java example does, however, show simple ways of handling callbacks for the command-line context. The implementation of the sample client follows.

package com.sun.identity.samples.authentication;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.ChoiceCallback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import com.sun.identity.authentication.AuthContext;
import com.sun.identity.authentication.spi.AuthLoginException;
import com.sun.identity.shared.debug.Debug;

public class Login {
    private String loginIndexName;
    private String orgName;
    private String locale;

    private Login(String loginIndexName, String orgName) {
        this.loginIndexName = loginIndexName;
        this.orgName = orgName;
    }

    private Login(String loginIndexName, String orgName, String locale) {
        this.loginIndexName = loginIndexName;
        this.orgName = orgName;
        this.locale = locale;
    }

    protected AuthContext getAuthContext()
        throws AuthLoginException {
        AuthContext lc = new AuthContext(orgName);
        AuthContext.IndexType indexType = AuthContext.IndexType.MODULE_INSTANCE;
        if (locale == null || locale.length() == 0) {
            lc.login(indexType, loginIndexName);
        } else {
            lc.login(indexType, loginIndexName, locale);
        }
        debugMessage(loginIndexName + ": Obtained login context");
        return lc;
    }

    private void addLoginCallbackMessage(Callback[] callbacks)
    throws UnsupportedCallbackException {
        int i = 0;
        try {
            for (i = 0; i < callbacks.length; i++) {
                if (callbacks[i] instanceof TextOutputCallback) {
                    handleTextOutputCallback((TextOutputCallback)callbacks[i]);
                } else if (callbacks[i] instanceof NameCallback) {
                    handleNameCallback((NameCallback)callbacks[i]);
                } else if (callbacks[i] instanceof PasswordCallback) {
                    handlePasswordCallback((PasswordCallback)callbacks[i]);
                } else if (callbacks[i] instanceof TextInputCallback) {
                    handleTextInputCallback((TextInputCallback)callbacks[i]);
                } else if (callbacks[i] instanceof ChoiceCallback) {
                    handleChoiceCallback((ChoiceCallback)callbacks[i]);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new UnsupportedCallbackException(callbacks[i],e.getMessage());
        }
    }

    private void handleTextOutputCallback(TextOutputCallback toc) {
        debugMessage("Got TextOutputCallback");
        // display the message according to the specified type

        switch (toc.getMessageType()) {
            case TextOutputCallback.INFORMATION:
                debugMessage(toc.getMessage());
                break;
            case TextOutputCallback.ERROR:
                debugMessage("ERROR: " + toc.getMessage());
                break;
            case TextOutputCallback.WARNING:
                debugMessage("WARNING: " + toc.getMessage());
                break;
            default:
                debugMessage("Unsupported message type: " +
                    toc.getMessageType());
        }
    }

    private void handleNameCallback(NameCallback nc)
        throws IOException {
        // prompt the user for a username
        System.out.print(nc.getPrompt());
        System.out.flush();
        nc.setName((new BufferedReader
            (new InputStreamReader(System.in))).readLine());
    }

    private void handleTextInputCallback(TextInputCallback tic)
        throws IOException {
        // prompt for text input
        System.out.print(tic.getPrompt());
        System.out.flush();
        tic.setText((new BufferedReader
            (new InputStreamReader(System.in))).readLine());
    }

    private void handlePasswordCallback(PasswordCallback pc)
        throws IOException {
        // prompt the user for sensitive information
        System.out.print(pc.getPrompt());
        System.out.flush();
        String passwd = (new BufferedReader(new InputStreamReader(System.in))).
            readLine();
        pc.setPassword(passwd.toCharArray());
    }

    private void handleChoiceCallback(ChoiceCallback cc)
        throws IOException {
        // ignore the provided defaultValue
        System.out.print(cc.getPrompt());

        String[] strChoices = cc.getChoices();
        for (int j = 0; j < strChoices.length; j++) {
            System.out.print("choice[" + j + "] : " + strChoices[j]);
        }
        System.out.flush();
        cc.setSelectedIndex(Integer.parseInt((new BufferedReader
            (new InputStreamReader(System.in))).readLine()));
    }

    protected boolean login(AuthContext lc)
        throws UnsupportedCallbackException {
        boolean succeed = false;
        Callback[] callbacks = null;

        // get information requested from module
        while (lc.hasMoreRequirements()) {
            callbacks = lc.getRequirements();
            if (callbacks != null) {
                addLoginCallbackMessage(callbacks);
                lc.submitRequirements(callbacks);
            }
        }

        if (lc.getStatus() == AuthContext.Status.SUCCESS) {
            System.out.println("Login succeeded.");
            succeed = true;
        } else if (lc.getStatus() == AuthContext.Status.FAILED) {
            System.out.println("Login failed.");
        } else {
            System.out.println("Unknown status: " + lc.getStatus());
        }

        return succeed;
    }

    protected void logout(AuthContext lc)
        throws AuthLoginException {
        lc.logout();
        System.out.println("Logged Out!!");
    }

    static void debugMessage(String msg) {
        System.out.println(msg);
    }

    public static void main(String[] args) {
        try {
            System.out.print("Realm (e.g. /): ");
            String orgName = (new BufferedReader(
                new InputStreamReader(System.in))).readLine();

            System.out.print("Login module name (e.g. DataStore or LDAP): ");
            String moduleName = (new BufferedReader(
                new InputStreamReader(System.in))).readLine();

            System.out.print("Login locale (e.g. en_US or fr_FR): ");
            String locale = (new BufferedReader(
                new InputStreamReader(System.in))).readLine();

            Login login = new Login(moduleName, orgName, locale);
            AuthContext lc = login.getAuthContext();
            if (login.login(lc)) {
                login.logout(lc);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (AuthLoginException e) {
            e.printStackTrace();
        } catch (UnsupportedCallbackException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }
}

Encoding Passwords and Password Reset Questions and Answers

OpenAM uses symmetric encryption algorithms to encrypt and decrypt stored passwords, so that they can be retrieved or modified at later date if necessary. The OpenAM Java SDK provides the capability to encode passwords using the EncodeAction class in standalone applications. For example, you can encrypt and decrypt a password as follows:

String plainText = "helloworld";
String encrypted = AccessController.doPrivileged(new EncodeAction(plainText));
String decrypted = AccessController.doPrivileged(new DecodeAction(encrypted));
Assert plainText.equals(decrypted);

To use this class, you must ensure that the symmetric encryption key has the same value as configured in the server instances. You can run ssoadm to retrieve the password encryption key as follows:

ssoadm am.encryption.pwd

Next, in your application’s AMConfig.properties file, replace the @ENCRYPTION_KEY@ with the value of the password encryption key. The property ensures that OpenAM can decrypt the password.

am.encryption.pwd=@ENCRYPTION_KEY@

OpenAM’s password reset question and answer also uses symmetric key encryption in its configuration. You can use the encodeAction class to encrypt a password reset question and answer:

String encrypted = AccessController.doPrivileged(new EncodeAction(question + "\t" + \
   answer "+" "1"));

The last number in the previous example indicates whether the question/answer is enabled or disabled:

  • 0 = default question/answer that is disabled

  • 1 = default question/answer that is enabled

  • 2 = personal question/answer that is disabled

  • 3 = personal question/answer that is enabled

To encrypt or decrypt the password reset question and answer, you must retrieve the password encryption key using ssoadm am.encryption.key, and then set the am.encryption.key property with the value of the password encryption key in the AMConfig.properties file.

For additional information, see EncodeAction.

Handling Single Sign-On Using OpenAM Java SDK

This section looks at handling session tokens with the OpenAM Java SDK. The class shown in this section is com.sun.identity.samples.sso.SSOTokenSample.

When a user authenticates successfully, OpenAM sets up a single sign-on (SSO) session for the user. The session is associated with an SSO token that holds information about the authentication, and also about the user’s environment and session. OpenAM deletes the session when the authentication context logout() method is called, or when a session timeout is reached. At that point the SSO token is no longer valid.

Before you continue, make sure that the packages described in the "Installing OpenAM Client SDK Samples" chapter are installed.

When your application has an AuthContext after successful authentication, you can retrieve the SSO token from the context. You also can get the token as shown in the sample client by passing an SSO token ID from OpenAM to an SSOTokenManager.

If your application needs to be notified of changes, you can register an SSOTokenListener on the token by using the token’s addSSOTokenListener() method. OpenAM then calls your SSOTokenListener ssoTokenChanged() method when the session times out, is disposed of, or has a property that changes. Applications can receive notifications about changes to stateful sessions only. Adding an SSOTokenListener for a stateless session token does not generate notifications.

The sample client takes an SSO token ID to get the token from OpenAM, and then displays some information from the SSO token. The implementation of the sample client follows.

package com.sun.identity.samples.sso;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.InetAddress;
import com.iplanet.sso.SSOException;
import com.iplanet.sso.SSOToken;
import com.iplanet.sso.SSOTokenID;
import com.iplanet.sso.SSOTokenManager;

public class SSOTokenSample {
    private SSOTokenManager manager;
    private SSOToken token;

    private SSOTokenSample(String tokenID)
        throws SSOException
    {
        if (validateToken(tokenID)) {
            setGetProperties(token);
        }
    }

    private boolean validateToken(String tokenID)
        throws SSOException
    {
        boolean validated = false;
        manager = SSOTokenManager.getInstance();
        token = manager.createSSOToken(tokenID);

        // isValid method returns true for valid token.
        if (manager.isValidToken(token)) {
                // let us get all the values from the token
            String host = token.getHostName();
            java.security.Principal principal = token.getPrincipal();
            String authType = token.getAuthType();
            int level = token.getAuthLevel();
            InetAddress ipAddress = token.getIPAddress();
            long maxTime = token.getMaxSessionTime();
            long idleTime = token.getIdleTime();
            long maxIdleTime = token.getMaxIdleTime();

            System.out.println("SSOToken host name: " + host);
            System.out.println("SSOToken Principal name: " +
                principal.getName());
            System.out.println("Authentication type used: " + authType);
            System.out.println("IPAddress of the host: " +
                ipAddress.getHostAddress());
            validated = true;
        }

        return validated;
    }

    private void setGetProperties(SSOToken token)
        throws SSOException
    {
        /*
         * Validate the token again, with another method
         * if token is invalid, this method throws an exception
         */
        manager.validateToken(token);
        System.out.println("SSO Token validation test Succeeded.");

        // Get the SSOTokenID associated with the token and print it.
        SSOTokenID id = token.getTokenID();
        String tokenId = id.toString();
        System.out.println("Token ID: " + tokenId);

        // Set and get properties in the token.
        token.setProperty("TimeZone", "PST");
        token.setProperty("County", "SantaClara");
        String tZone = token.getProperty("TimeZone");
        String county = token.getProperty("County");

        System.out.println("Property: TimeZone: " + tZone);
        System.out.println("Property: County: " + county);
    }

    public static void main(String[] args) {
        try {
            System.out.print("Enter SSOToken ID: ");
            String ssoTokenID = (new BufferedReader(
                new InputStreamReader(System.in))).readLine();
            new SSOTokenSample(ssoTokenID.trim());
        } catch (SSOException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.exit(0);
    }

}

Before you run the script that calls the sample, authenticate to OpenAM in order to have OpenAM generate the SSO token ID. To see the SSO token ID, use the RESTful authenticate command as shown in the following example, or alternatively run the SSOTokenSampleServlet web-based sample.

$ curl \
 --request POST \
 --data "username=demo&password=changeit" \
 http://openam.example.com:8080/openam/identity/authenticate
token.id=AQIC5wM2LY4Sfcyy10grl...AlNLABQtNjI4OTkyNTUxNTc4MDQ3NzEzOQ..*
$ sh scripts/SSOTokenSample.sh
Enter SSOToken ID: AQIC5wM2LY4Sfcyy10grl...AlNLABQtNjI4OTkyNTUxNTc4MDQ3NzEzOQ..*
SSOToken host name: 172.16.203.239
SSOToken Principal name: id=demo,ou=user,dc=openam,dc=forgerock,dc=org
Authentication type used: DataStore
IPAddress of the host: 172.16.203.239
SSO Token validation test Succeeded.
Token ID: AQIC5wM2LY4Sfcyy10grl...AlNLABQtNjI4OTkyNTUxNTc4MDQ3NzEzOQ..*
Property: TimeZone: PST
Property: County: SantaClara

Notice both the properties populated by OpenAM, and also the two properties, TimeZone and County, that are set by the sample client.

Receiving Notifications

If your application implements a listener for change notification, such as a SessionListener to handle notification when a stateful session is invalidated, then you must configure the following settings in the AMConfig.properties configuration file for your application.

com.iplanet.am.notification.url

Set this parameter to http://host:port/context/notificationservice.

com.iplanet.am.sdk.caching.enabled

Set this parameter to true.

com.iplanet.am.serverMode

Set this parameter to false.

com.sun.identity.client.notification.url

Set this parameter to http://host:port/context/notificationservice.

com.sun.identity.idm.cache.enabled

Set this parameter to true.

com.sun.identity.idm.remote.notification.enabled

Set this parameter to true.

com.sun.identity.sm.cache.enabled

Set this parameter to true.

com.sun.identity.sm.enableDataStoreNotification

Set this parameter to true.

The above configuration to access the notification service also applies for other types of listeners, such as ServiceListener, and IdEventListener implementations. See the OpenAM Java SDK API Specification for details on the available listener interfaces.

Requesting Policy Decisions Using OpenAM Java SDK

This section shows how to request policy decision by using OpenAM Java SDK. The chapter focuses on the sample client, source/samples/policy/PolicyEvaluationSample.java, which demonstrates making a request to OpenAM for a policy decision about access to a web resource.

Before you continue, make sure that the packages described in "Installing OpenAM Client SDK Samples" are installed.

OpenAM centralizes policy administration, policy evaluation, and policy decision making so that your applications do not have to do so. In many deployments, OpenAM policy agents and the Open Identity gateway can handle policy enforcement independently from your application code.

If your application does need to request a policy decision from OpenAM, then your application can retrieve a PolicyEvaluator from a client-side PolicyEvaluatorFactory, and then call the PolicyEvaluator getPolicyDecision() method. For boolean decisions such as allow or deny, your application can also call the isAllowed() method.

To make a policy decision, OpenAM needs an SSO token, the resource to access, the action the user wants to perform on the resource such as HTTP GET or POST, and a Map of environment settings you can use to specify conditions and attributes in the session or can pass back as an empty Map if your policy does not include conditions and response attributes.

The PolicyEvaluationSample class takes as its configuration the user credentials, service name, resource, and action that you provide in a Java properties file. It then authenticates the user to get an SSO token using the TokenUtils.java helper methods. At that point it has sufficient information to request a policy decision.

The implementation of the sample client follows.

package samples.policy;

import com.iplanet.sso.SSOToken;
import com.iplanet.sso.SSOTokenManager;

import com.sun.identity.policy.PolicyDecision;
import com.sun.identity.policy.client.PolicyEvaluator;
import com.sun.identity.policy.client.PolicyEvaluatorFactory;

import samples.policy.TokenUtils;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.HashSet;
import java.util.Properties;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;

public class PolicyEvaluationSample {


    public PolicyEvaluationSample() {
    }

    public static void main(String[] args) throws Exception {
        PolicyEvaluationSample clientSample = new PolicyEvaluationSample();
        clientSample.runSample(args);
        System.exit(0);
    }

    public void runSample(String[] args) throws Exception {
        if (args.length == 0 || args.length > 1) {
            System.out.println("Missing argument:"
                    + "properties file name not specified");
        } else {
            System.out.println("Using properties file:" + args[0]);
            Properties sampleProperties = getProperties(args[0]);
            SSOToken ssoToken = getSSOToken(
                (String)sampleProperties.get("user.name"),
                (String)sampleProperties.get("user.password")
            );
            getPolicyDecision(
                ssoToken,
                (String)sampleProperties.get("service.name"),
                (String)sampleProperties.get("resource.name"),
                (String)sampleProperties.get("action.name")
            );
        }
    }

    private SSOToken getSSOToken(
            String userName, String password) throws Exception {
        System.out.println("Entering getSSOToken():"
                + "userName=" + userName + ","
                + "password=" + password);
        SSOToken ssoToken = TokenUtils.getSessionToken("/",
                userName, password);
        System.out.println("TokenID:" + ssoToken.getTokenID().toString());
        System.out.println("returning from getSSOToken()");
        return ssoToken;
    }

    private void getPolicyDecision(
            SSOToken ssoToken,
            String serviceName,
            String resourceName,
            String actionName)
            throws Exception {

        System.out.println("Entering getPolicyDecision():"
                + "resourceName=" + resourceName + ","
                + "serviceName=" + serviceName + ","
                + "actionName=" + actionName);
        PolicyEvaluator pe = PolicyEvaluatorFactory.getInstance().
                    getPolicyEvaluator(serviceName);

        Map env = new HashMap();
        Set attrSet = new HashSet();
        Set actions = new HashSet();
        actions.add(actionName);
        PolicyDecision pd = pe.getPolicyDecision(ssoToken, resourceName,
                actions, env);
        System.out.println("policyDecision:" + pd.toXML());

        System.out.println("returning from getPolicyDecision()");
    }

    private Properties getProperties(String file)
      throws MissingResourceException {
        Properties properties = new Properties();
        ResourceBundle bundle = ResourceBundle.getBundle(file);
        Enumeration e = bundle.getKeys();
        System.out.println("sample properties:");
        while (e.hasMoreElements()) {
            String key = (String) e.nextElement();
            String value = bundle.getString(key);
            properties.put(key, value);
            System.out.println(key + ":" + value);
        }
        return properties;
    }
}

Before you run the script that calls the sample, edit the properties file, resources/policyEvaluationSample.properties, to indicate the user credentials, resource to access, and HTTP method to use. You can use a resource that might not exist for the purposes of this example, but you will need to set up a policy for that resource to get meaningful results.

user.name=demo
user.password=changeit
service.name=iPlanetAMWebAgentService
resource.name=http://www.example.com:80/banner.html
action.name=GET

Also, set up a policy in OpenAM that corresponds to the resource in question. You can set up the policy in OpenAM console under Realms > Realm Name > Authorization. Concerning the Realm Name, notice that unless you change the code, the sample uses the top-level realm, / to authenticate the user.

With the properties configured and policy in place, get the decision from OpenAM using the script, scripts/run-policy-evaluation-sample.sh.

$ sh scripts/run-policy-evaluation-sample.sh
Using properties file:policyEvaluationSample
sample properties:
user.password:changeit
service.name:iPlanetAMWebAgentService
user.name:demo
resource.name:http://www.example.com:80/banner.html
action.name:GET
------------------------------------------------------------------------------:
Entering getSSOToken():userName=demo,password=changeit
TokenID:AQIC5wM2LY4Sfcx3aQGFRKu5-r1a-Vfyjb...5ODM4NDY0MzE0ODYzODQ1*
returning from getSSOToken()
Entering getPolicyDecision():resourceName=http://www.example.com:80/banner.html,
 serviceName=iPlanetAMWebAgentService,actionName=GET
policyDecision:<PolicyDecision>
<ResponseAttributes>
</ResponseAttributes>
<ActionDecision timeToLive="9223372036854775807">
<AttributeValuePair>
<Attribute name="GET"/>
<Value>allow</Value>
</AttributeValuePair>
<Advices>
</Advices>
</ActionDecision>
</PolicyDecision>

returning from getPolicyDecision()

As you see, the policy decision response is formatted here as an XML document.[1] Notice here the line showing that OpenAM has allowed access to the resource.

<Value>allow</Value>

Requesting a XACML Policy Decision Using OpenAM Java SDK

This section shows how to request a XACML policy decision with OpenAM Java SDK, using the sample client, source/samples/xacml/XACMLClientSample.java. The sample client relies on an OpenAM server acting as a policy decision point and another OpenAM server acting as a policy enforcement point.

Before you continue, make sure that the packages described in the "Installing OpenAM Client SDK Samples" chapter are installed.

The sample client uses the XACML ContextFactory to create the XACML request. It then uses the XACMLRequestProcessor to get a decision as XACML Response from OpenAM. Most of the work in the sample is done setting up the request.

The implementation of the XACMLClientSample class follows.

package samples.xacml;

import com.sun.identity.saml2.common.SAML2Exception;
import com.sun.identity.xacml.client.XACMLRequestProcessor;
import com.sun.identity.xacml.common.XACMLConstants;
import com.sun.identity.xacml.common.XACMLException;
import com.sun.identity.xacml.context.ContextFactory;
import com.sun.identity.xacml.context.Action;
import com.sun.identity.xacml.context.Attribute;
import com.sun.identity.xacml.context.Environment;
import com.sun.identity.xacml.context.Request;
import com.sun.identity.xacml.context.Resource;
import com.sun.identity.xacml.context.Response;
import com.sun.identity.xacml.context.Subject;
import java.net.URI;
import java.net.URISyntaxException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;

public class XACMLClientSample {

    public XACMLClientSample() {
    }

    public static void main(String[] args) throws Exception {
        XACMLClientSample clientSample = new XACMLClientSample();
        clientSample.runSample(args);
        System.exit(0);
    }

    public void runSample(String[] args) throws Exception {
        if (args.length == 0 || args.length > 1) {
            System.out.println("Missing argument:"
                    + "properties file name not specified");
        } else {
            System.out.println("Using properties file:" + args[0]);
            Properties sampleProperties = getProperties(args[0]);
            testProcessRequest(
                (String)sampleProperties.get("pdp.entityId"),
                (String)sampleProperties.get("pep.entityId"),
                (String)sampleProperties.get("subject.id"),
                (String)sampleProperties.get("subject.id.datatype"),
                (String)sampleProperties.get("subject.category"),
                (String)sampleProperties.get("resource.id"),
                (String)sampleProperties.get("resource.id.datatype"),
                (String)sampleProperties.get("resource.servicename"),
                (String)sampleProperties.get("resource.servicename.datatype"),
                (String)sampleProperties.get("action.id"),
                (String)sampleProperties.get("action.id.datatype")
            );
        }
    }

    private void testProcessRequest(
            String pdpEntityId, String pepEntityId,
            String subjectId, String subjectIdType,
            String subjectCategory,
            String resourceId, String resourceIdType,
            String serviceName, String serviceNameType,
            String actionId, String actionIdType)
            throws XACMLException, SAML2Exception,
            URISyntaxException, Exception {

        Request xacmlRequest = createSampleXacmlRequest(
            subjectId, subjectIdType,
            subjectCategory,
            resourceId, resourceIdType,
            serviceName, serviceNameType,
            actionId, actionIdType);

        System.out.println("\ntestProcessRequest():xacmlRequest:\n"
                + xacmlRequest.toXMLString(true, true));

        Response xacmlResponse = XACMLRequestProcessor.getInstance()
                .processRequest(xacmlRequest, pdpEntityId, pepEntityId);

        System.out.println("testProcessRequest():xacmlResponse:\n"
                + xacmlResponse.toXMLString(true, true));
    }

    private Request createSampleXacmlRequest(
            String subjectId, String subjectIdType,
            String subjectCategory,
            String resourceId, String resourceIdType,
            String serviceName, String serviceNameType,
            String actionId, String actionIdType)
            throws XACMLException, URISyntaxException {

        Request request = ContextFactory.getInstance().createRequest();

        //Subject
        Subject subject = ContextFactory.getInstance().createSubject();
        subject.setSubjectCategory(new URI(subjectCategory));

        //set subject id
        Attribute attribute = ContextFactory.getInstance().createAttribute();
        attribute.setAttributeId(new URI(XACMLConstants.SUBJECT_ID));
        attribute.setDataType(new URI(subjectIdType));
        List valueList = new ArrayList();
        valueList.add(subjectId);
        attribute.setAttributeStringValues(valueList);
        List attributeList = new ArrayList();
        attributeList.add(attribute);
        subject.setAttributes(attributeList);

        //set Subject in Request
        List subjectList = new ArrayList();
        subjectList.add(subject);
        request.setSubjects(subjectList);

        //Resource
        Resource resource = ContextFactory.getInstance().createResource();

        //set resource id
        attribute = ContextFactory.getInstance().createAttribute();
        attribute.setAttributeId(new URI(XACMLConstants.RESOURCE_ID));
        attribute.setDataType( new URI(resourceIdType));
        valueList = new ArrayList();
        valueList.add(resourceId);
        attribute.setAttributeStringValues(valueList);
        attributeList = new ArrayList();
        attributeList.add(attribute);

        //set serviceName
        attribute = ContextFactory.getInstance().createAttribute();
        attribute.setAttributeId(new URI(XACMLConstants.TARGET_SERVICE));
        attribute.setDataType(new URI(serviceNameType));
        valueList = new ArrayList();
        valueList.add(serviceName);
        attribute.setAttributeStringValues(valueList);
        attributeList.add(attribute);
        resource.setAttributes(attributeList);

        //set Resource in Request
        List resourceList = new ArrayList();
        resourceList.add(resource);
        request.setResources(resourceList);

        //Action
        Action action = ContextFactory.getInstance().createAction();
        attribute = ContextFactory.getInstance().createAttribute();
        attribute.setAttributeId(new URI(XACMLConstants.ACTION_ID));
        attribute.setDataType(new URI(actionIdType));

        //set actionId
        valueList = new ArrayList();
        valueList.add(actionId);
        attribute.setAttributeStringValues(valueList);
        attributeList = new ArrayList();
        attributeList.add(attribute);
        action.setAttributes(attributeList);

        //set Action in Request
        request.setAction(action);

        //Environment, our PDP does not use environment now
        Environment environment = ContextFactory.getInstance()
            .createEnvironment();
        request.setEnvironment(environment);
        return request;
    }

    private Properties getProperties(String file)
        throws MissingResourceException {
        Properties properties = new Properties();
        ResourceBundle bundle = ResourceBundle.getBundle(file);
        Enumeration e = bundle.getKeys();
        System.out.println("sample properties:");
        while (e.hasMoreElements()) {
            String key = (String) e.nextElement();
            String value = bundle.getString(key);
            properties.put(key, value);
            System.out.println(key + ":" + value);
        }
        return properties;
    }
}

Before running the sample client, you must set up the configuration as described in the comments at the outset of the scripts/run-xacml-client-sample.sh script.

  • Check resources/AMConfig.properties to see which OpenAM server the SDK is configured to use.

    The relevant settings from resources/AMConfig.properties specify the server protocol, host, port and deployment URI.

    com.iplanet.am.server.protocol=http
    com.iplanet.am.server.host=openam.example.com
    com.iplanet.am.server.port=8080
    com.iplanet.am.services.deploymentDescriptor=openam

    For the purpose of this example, the XACML policy decision point (PDP) and the XACML policy enforcement point (PEP) are configured on this server.

  • Edit resources/xacmlClientSample.properties and resources/policyEvaluationSample.properties to set up the configuration for the sample client.

    The relevant settings from resources/xacmlClientSample.properties are the following.

    pdp.entityId=xacmlPdpEntity
    pep.entityId=xacmlPepEntity
    subject.id=id=demo,ou=user,dc=openam,dc=forgerock,dc=org
    subject.id.datatype=urn:oasis:names:tc:xacml:1.0:data-type:x500Name
    subject.category=urn:oasis:names:tc:xacml:1.0:subject-category:access-subject
    resource.id=http://www.example.com:80/banner.html
    resource.id.datatype=http://www.w3.org/2001/XMLSchema#string
    resource.servicename=iPlanetAMWebAgentService
    resource.servicename.datatype=http://www.w3.org/2001/XMLSchema#string
    action.id=GET
    action.id.datatype=http://www.w3.org/2001/XMLSchema#string

    The relevant settings from resources/policyEvaluationSample.properties are the following.

    user.name=demo
    user.password=changeit
    service.name=iPlanetAMWebAgentService
    resource.name=http://www.example.com:80/banner.html
    action.name=GET

    These settings use the default demo user as the subject, who has ID id=demo,ou=user,dc=openam,dc=forgerock,dc=org, and password changeit. If you choose a different subject, then change the subject.id value in resources/xacmlClientSample.properties, and the user.name and user.password values in resources/policyEvaluationSample.properties.

  • The client accesses an OpenAM server acting as the policy enforcement point, configured in a circle of trust with the OpenAM server acting as the policy decision point. When you set up the sample clients, you pointed them to an OpenAM server. For this example, configure that server to function as a policy enforcement point and also as a policy decision point.

    1. In OpenAM console, browse to Configure > Global Services, click SAMLv2 SOAP Binding, and then configure a new request handler with Key /xacmlPdpEntity and Class com.sun.identity.xacml.plugins.XACMLAuthzDecisionQueryHandler.

    2. Set up the circle of trust, and then create and import the metadata for the policy enforcement point and the policy decision point. In the following simplified example, both the policy enforcement point and policy decision point are hosted on the same OpenAM server. You could also set up the policy enforcement point and policy decision point on separate servers, as long as the circles of trust on both servers each include both the policy enforcement point and the policy decision point. You can set up the trust relationship between the two entities either by using the ssoadm command as shown below, or by using the ssoadm.jsp page, which you can activate as described in "OpenAM ssoadm.jsp" in the Administration Guide.

      $ ssoadm \
       create-cot \
       --adminid amadmin \
       --password-file /tmp/pwd.txt \
       --cot cot
      
      Circle of trust, cot was created.
      
      $ ssoadm \
       create-metadata-templ \
       --adminid amadmin \
       --password-file /tmp/pwd.txt \
       --entityid xacmlPepEntity \
       --xacmlpep /xacmlPepEntity \
       --meta-data-file xacmlPep.xml \
       --extended-data-file xacmlPep-extended.xml
      
      Hosted entity configuration was written to xacmlPep-extended.xml.
      Hosted entity descriptor was written to xacmlPep.xml.
      
      $ ssoadm \
       import-entity \
       --adminid amadmin \
       --password-file /tmp/pwd.txt \
       --cot cot \
       --meta-data-file xacmlPep.xml \
       --extended-data-file xacmlPep-extended.xml
      
      Import file, xacmlPep.xml.
      Import file, xacmlPep-extended.xml.
      
      $ ssoadm \
       create-metadata-templ \
       --adminid amadmin \
       --password-file /tmp/pwd.txt \
       --entityid xacmlPdpEntity \
       --xacmlpdp /xacmlPdpEntity \
       --meta-data-file xacmlPdp.xml \
       --extended-data-file xacmlPdp-extended.xml
      
      Hosted entity configuration was written to xacmlPdp-extended.xml.
      Hosted entity descriptor was written to xacmlPdp.xml.
      
      $ ssoadm \
       import-entity \
       --adminid amadmin \
       --password-file /tmp/pwd.txt \
       --cot cot \
       --meta-data-file xacmlPdp.xml \
       --extended-data-file xacmlPdp-extended.xml
      
      Import file, xacmlPdp.xml.
      Import file, xacmlPdp-extended.xml.
  • Create a policy that allows authenticated users to perform an HTTP GET on the sample resource.id URL you configured, such as http://www.example.com:80/banner.html.

    See "Defining Authorization Policies" in the Administration Guide for details.

After you have configured OpenAM and the properties files, run the sample client script, and observe the XACML request and response.

$ sh scripts/run-xacml-client-sample.sh

Using properties file:xacmlClientSample
sample properties:
subject.id.datatype:urn:oasis:names:tc:xacml:1.0:data-type:x500Name
pdp.entityId:xacmlPdpEntity
resource.servicename.datatype:http://www.w3.org/2001/XMLSchema#string
resource.id:http://www.example.com:80/banner.html
resource.servicename:iPlanetAMWebAgentService
action.id.datatype:http://www.w3.org/2001/XMLSchema#string
resource.id.datatype:http://www.w3.org/2001/XMLSchema#string
action.id:GET
subject.category:urn:oasis:names:tc:xacml:1.0:subject-category:access-subject
pep.entityId:xacmlPepEntity
subject.id:id=demo,ou=user,dc=openam,dc=forgerock,dc=org

testProcessRequest():xacmlRequest:

<xacml-context:Request
 xmlns:xacml-context="urn:oasis:names:tc:xacml:2.0:context:schema:os"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="urn:oasis:names:tc:xacml:2.0:context:schema:os
  http://docs.oasis-open.org/xacml/access_control-xacml-2.0-context-schema-os.xsd">
<Subject SubjectCategory=
 "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
<Attribute
 AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id"
 DataType="urn:oasis:names:tc:xacml:1.0:data-type:x500Name" >
<AttributeValue
 >id=demo,ou=user,dc=openam,dc=forgerock,dc=org</AttributeValue>
</Attribute>
</Subject>
<xacml-context:Resource>
<Attribute
 AttributeId="ResourceId"
 DataType="http://www.w3.org/2001/XMLSchema#string" >
<AttributeValue>http://www.example.com:80/banner.html</AttributeValue>
</Attribute>
<Attribute
  AttributeId="urn:sun:names:xacml:2.0:resource:target-service"
  DataType="http://www.w3.org/2001/XMLSchema#string" >
<AttributeValue>iPlanetAMWebAgentService</AttributeValue>
</Attribute>
</xacml-context:Resource>
<xacml-context:Action>
<Attribute
 AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
 DataType="http://www.w3.org/2001/XMLSchema#string" >
<AttributeValue>GET</AttributeValue>
</Attribute>
</xacml-context:Action>
<xacml-context:Environment></xacml-context:Environment>
</xacml-context:Request>

testProcessRequest():xacmlResponse:
<xacml-context:Response
 xmlns:xacml-context="urn:oasis:names:tc:xacml:2.0:context:schema:os" >
<xacml-context:Result ResourceId="http://www.example.com:80/banner.html">
<xacml-context:Decision>Permit</xacml-context:Decision>
<xacml-context:Status>
<xacml-context:StatusCode
 Value="urn:oasis:names:tc:xacml:1.0:status:ok">
</xacml-context:StatusCode>
<xacml-context:StatusMessage>ok</xacml-context:StatusMessage>
<xacml-context:StatusDetail
 xmlns:xacml-context="urn:oasis:names:tc:xacml:2.0:context:schema:cd:04">
<xacml-context:StatusDetail/></xacml-context:StatusDetail>
</xacml-context:Status>
</xacml-context:Result>
</xacml-context:Response>

Using the OpenAM C SDK

This section introduces OpenAM C SDK, which is available for selected platforms. Contact an approved vendor if you need OpenAM C SDK support.

To prepare to install OpenAM C SDK, first download the version for your platform and unpack the archive as in the following example.

$ mkdir -p /path/to/openam-client
$ cd /path/to/openam-client
$ unzip ~/Downloads/common_3_0_Linux_64bit.zip

All C SDK deliveries are .zip files, and the filenames are self-explanatory. The SunOS in some of the .zip files refer to the Solaris OS.

  • common_3_0_Linux.zip

  • common_3_0_Linux_64bit.zip

  • common_3_0_windows.zip

  • common_3_0_windows_64bit.zip

  • common_3_0_SunOS_x86.zip

  • common_3_0_SunOS_64bit.zip

  • common_3_0_SunOS_sparc.zip

  • common_3_0_SunOS_sparc_64bit.zip

Once unpacked, you have several directories that include the SDK, and also sample client applications.

bin/

The crypt_util or cryptit.exe command for encrypting passwords

config/

Configuration data for the SDK

include/

Header files for the SDK

lib/

SDK and other required libraries

samples/

Sample code

To Build OpenAM C SDK Samples
  1. Review the samples/README.TXT file to complete any specific instructions required for your platform. The two commands shown here confirm that the specified system is a 64-bit Linux OS. Make sure it matches the C SDK package that you have downloaded.

    $ uname -s
    Linux
    $ uname -m
    x86_64
  2. Set up OpenSSOAgentBootstrap.properties and OpenSSOAgentConfiguration.properties as appropriate for your environment.

    Base your work on the template files in the config/ directory. You can find the Password Encryption Key in the OpenAM console under Deployment > Servers > Server Name > Security.

  3. Try one of the samples you built to test your build.

    $ LD_LIBRARY_PATH=../lib \
     ./am_auth_test \
     -f ../config/OpenSSOAgentBootstrap.properties \
     -u demo \
     -p changeit \
     -o /
       Login  1 Succeeded!
          SSOToken = AQIC5wM2LY4SfcxZfk4EzC9Y46P9cXG9ogwf2ixnYOeZ0K0.*AAJTSQACMDE.*
          Organization = /
          Module Instance Name [0] = SAE
          Module Instance Name [1] = LDAP
          Module Instance Name [2] = WSSAuthModule
          Module Instance Name [3] = Federation
          Module Instance Name [4] = HOTP
          Module Instance Name [5] = DataStore
       Logout 1 Succeeded!

1. The`PolicyDecision`element is defined in`openam/WEB-INF/remoteInterface.dtd`whereopenamis the location where the OpenAM web application is deployed.