Chapter 3. RESTful Web Services

Table of Contents
3.1. About the RESTful APIs
3.2. REST API Versioning
3.3. Token Encoding
3.4. Authentication & Logout
3.5. Server Information
3.6. Cookie Information
3.7. Token Validation and Session Information
3.8. Logging
3.9. REST Status Codes

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

3.1. 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 application. The designs of both HTTP 1.1 and also 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 and OpenID Connect 1.0.

ForgeRock 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 and OpenID Connect 1.0 APIs follow the standards.) APIs covered in sections labelled (Legacy API) predate CREST, and do not use the CREST verbs.

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 PUT (or POST).

_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 what the API can do 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 these access and identity management operations:

This chapter also includes a section on REST Status Codes.

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

3.2. 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.

3.2.1. Supported REST API Versions

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

Supported protocol versions

The protocol versions supported in OpenAM 12.0.0 are:

1.0
Supported resource versions

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

Table 3.1. Supported resource Versions
BaseEnd PointSupported Versions
/json/authenticate1.1, 2.0
/users1.1, 2.0
/groups1.1, 2.0
/agents1.1, 2.0
/realms1.0
/dashboard1.0
/sessions1.1
/serverinfo/*1.1
/users/{user-id}/devices/trusted1.0
/applications1.0
/policies1.0
/applicationtypes1.0
/conditiontypes1.0
/subjecttypes1.0
/decisioncombiners1.0
/frrest/token1.0
/client1.0

The OpenAM Release Notes section, OpenAM Changes & Deprecated Functionality describes the differences between API versions.

3.2.2. 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 "Content-Type: application/json" \
 --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 OpenAM Administration Guide.

3.2.3. 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 OpenAM 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 "Content-Type: application/json" \
 --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."
}

Tip

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

3.3. 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 chapter. 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.*

3.4. Authentication & Logout

OpenAM provides REST APIs for authentication and for logout.

Tip

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 the Installation Guide section, Handling HTTP Request Headers.

3.4.1. REST APIs for Authentication & Logout

The simplest user name/password authentication returns a tokenId that applications can present as a cookie value for other operations that require authentication. In this case 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 "X-OpenAM-Username: demo" \
 --header "X-OpenAM-Password: changeit" \
 --header "Content-Type: application/json" \
 --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 \
 --header "Content-Type: application/json" \
 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 Core 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 "Content-Type: application/json" \
 --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 the Administration Guide section on, Authentication Levels & Session Upgrade.

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..*" \
 --header "Content-Type: application/json" \
 "https://openam.example.com:8443/openam/json/sessions/?_action=logout"

{"result":"Successfully logged out"}
   

3.4.2. Authentication & Logout (Legacy API)

Interface Stability: Deprecated

Simple authentication with a user name and password returns a token.

$ curl \
 --request POST \
 --data "username=bjensen&password=hifalutin" \
 https://openam.example.com:8443/openam/identity/authenticate

token.id=AQIC5wM2LY4SfcxvdvHOXjtC_eWSs2RB54tgvgK8SuYi7aQ.*AAJTSQACMDE.*
    

If you must specify parameters as when authenticating to /UI/Login, you provide a percent encoded string of the parameters as the value of the uri parameter. The /UI/Login parameter deals with the realm, module, and service parameters. Setting the client parameter sets the user's IP address as part of the token following successful authentication. The default for the client parameter is the IP of the machine making the REST request.

$ curl \
 --request POST \
 --data "username=bjensen&password=hifalutin&uri=realm%3D%2F%26module%3DDataStore\
&client=192.168.1.1" \
 https://openam.example.com:8443/openam/identity/authenticate

token.id=AQIC5wM2LY4SfcxvdvHOXjtC_eWSs2RB54tgvgK8SuYi7aQ.*AAJTSQACMDE.*
    

You log out using the token to end the user session.

$ curl \
 --request POST \
 --data "subjectid=AQIC5w...*AAJTSQACMDE.*" \
 https://openam.example.com:8443/openam/identity/logout
    

3.5. Server Information

You can retrieve OpenAM server information by using HTTP GET on /json/serverinfo/*.

$ curl https://openam.example.com:8443/openam/json/serverinfo/*
{
    "domains": [
        ".example.com"
    ],
    "protectedUserAttributes": [],
    "cookieName": "iPlanetDirectoryPro",
    "forgotPassword": "false",
    "selfRegistration": "false",
    "lang": "en",
    "successfulUserRegistrationDestination": "default",
    "socialImplementations": [
        {
            "iconPath": "XUI/images/dashboard/facebook.png",
            "authnChain": "FacebookSocialAuthenticationService",
            "displayName": "Facebook",
            "valid": true
        }
    ]
}

3.6. Cookie Information

You can retrieve the cookie domains that OpenAM supports by HTTP GET on /json/serverinfo/cookieDomains.

$ curl https://openam.example.com:8443/openam/json/serverinfo/cookieDomains
{"domains":[".example.com"]}
  

You can retrieve the name of the cookie used for storing the session token. By default it is iPlanetDirectoryPro.

$ curl https://openam.example.com:8443/openam/identity/getCookieNameForToken
string=iPlanetDirectoryPro
  

You can also retrieve the name of the cookie used for storing the session token and the names of the cookies to forward with requests.

$ curl https://openam.example.com:8443/openam/identity/getCookieNamesToForward
string=iPlanetDirectoryPro
string=amlbcookie
  

3.7. Token Validation and Session Information

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

3.7.1. Token Validation

To check over REST whether a 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"}
   

An invalid token returns only information about the validity.

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

3.7.2. Session Information

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 session has been idle

  • Reset a session's idle time to 0

For these REST endpoints, specify two SSO tokens. Provide the SSO token 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 SSO token about which you want information as the tokenId query string parameter of the REST URL. In the examples in this section, AQIC5w...NTcy* is the SSO token 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 getMaxTime 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=getMaxTime&tokenId=BXCCq...NX*1*
    {"maxtime":7022}
   

To check the amount of time (in seconds) that a 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}
   

To reset a 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}
   

3.7.3. Token Validation, Attribute Retrieval (Legacy API)

Interface Stability: Deprecated

You check whether a token is valid as follows:

$ curl \
 --request POST \
 --data "tokenid=AQIC5w...*AAJTSQACMDE.*" \
 https://openam.example.com:8443/openam/identity/isTokenValid
boolean=true
   

An invalid token returns boolean=false.

$ curl \
 --request POST \
 --data "tokenid=INVALID" \
 https://openam.example.com:8443/openam/identity/isTokenValid
boolean=false
   

With a valid token, you can retrieve attributes about the subject. OpenAM returns a series of name, value pairs.

The newer API for retrieving user information is demonstrated in Reading Identities. What follows describes the legacy API.

$ curl \
 --request POST \
 --data "subjectid=AQIC5w...*AAJTSQACMDE.*" \
 https://openam.example.com:8443/openam/identity/attributes
userdetails.token.id=
 AQIC5wM2LY4SfcxuxIP0VnP2lVjs7ypEM6VDx6srk56CN1Q.*AAJTSQACMDE.*
userdetails.attribute.name=uid
userdetails.attribute.value=bjensen
userdetails.attribute.name=mail
userdetails.attribute.value=bjensen@example.com
userdetails.attribute.name=sn
userdetails.attribute.value=Jensen
userdetails.attribute.name=userpassword
userdetails.attribute.value={SSHA}rhusOfYpkapDWEHcfT2Y7y83LMuC++F4Abqvig==
userdetails.attribute.name=cn
userdetails.attribute.value=Babs Jensen
userdetails.attribute.value=Barbara Jensen
userdetails.attribute.name=givenname
userdetails.attribute.value=Barbara
userdetails.attribute.name=dn
userdetails.attribute.value=uid=bjensen,ou=people,dc=example,dc=com
userdetails.attribute.name=telephonenumber
userdetails.attribute.value=+1 408 555 1862
userdetails.attribute.name=objectclass
userdetails.attribute.value=organizationalPerson
userdetails.attribute.value=person
userdetails.attribute.value=posixAccount
userdetails.attribute.value=inetOrgPerson
userdetails.attribute.value=krbprincipalaux
userdetails.attribute.value=krbTicketPolicyAux
userdetails.attribute.value=top
   

You can specify attributes to limit what you retrieve.

$ curl "https://openam.example.com:8443/openam/identity/attributes?\
subjectid=AQIC5wM2LY4SfcxuxIP0VnP2lVjs7ypEM6VDx6srk56CN1Q.*AAJTSQACMDE.*\
&attributenames=mail\
&attributenames=uid"
userdetails.token.id=
 AQIC5wM2LY4SfcxuxIP0VnP2lVjs7ypEM6VDx6srk56CN1Q.*AAJTSQACMDE.*
userdetails.attribute.name=uid
userdetails.attribute.value=bjensen
userdetails.attribute.name=mail
userdetails.attribute.value=bjensen@example.com
   

When retrieving attributes, you can refresh the session thus setting the idle time to 0, by adding the boolean parameter refresh=true to the query string.

$ curl "https://openam.example.com:8443/openam/identity/attributes?\
subjectid=AQIC5wM2LY4SfcxuxIP0VnP2lVjs7ypEM6VDx6srk56CN1Q.*AAJTSQACMDE.*\
&attributenames=cn\
&refresh=true"
userdetails.token.id=
 AQIC5wM2LY4SfcxuxIP0VnP2lVjs7ypEM6VDx6srk56CN1Q.*AAJTSQACMDE.*
userdetails.attribute.name=cn
userdetails.attribute.value=Babs Jensen
userdetails.attribute.value=Barbara Jensen
   

You can specify the following attributes to retrieve information about the user's session time limits and current session: maxsessiontime (maximum length of a session), maxidletime (maximum idle time allowed during a session), idletime (actual idle time during the current session), timeleft (actual time left in session). The unit for maximum times is minutes. The unit for actual times is seconds.

Also use the parameter refresh=false to avoid changing the idletime with your request.

$ curl \
--data "subjectid=AQIC5w....*AAJTSQACMDE.*\
 &attributenames=idletime\
 &attributenames=maxidletime\
 &attributenames=timeleft\
 &attributenames=maxsessiontime\
 &refresh=false" \
 https://openam.example.com:8443/openam/identity/attributes

userdetails.token.id=AQIC5w....*AAJTSQACMDE.*
userdetails.attribute.name=maxsessiontime
userdetails.attribute.value=120
userdetails.attribute.name=maxidletime
userdetails.attribute.value=30
userdetails.attribute.name=idletime
userdetails.attribute.value=664
userdetails.attribute.name=timeleft
userdetails.attribute.value=6319
  

3.8. Logging

OpenAM supports access and audit logging for any request going to a CREST endpoint and writes the data 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 has a key field, 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.

You can also send OpenAM messages to log, specifying the message content and the log file in which to write your message. Logging takes a valid appid token for the subject with access to log the message, and also a subjectid token for the user whom the message concerns. If the tokens are valid and the access rights correct, your message ends up in the log specified.

$ curl "https://openam.example.com:8443/openam/identity/log?\
appid=AQIC5wM2LY4SfcwyCZkk-1JXzx6q1EzgagabHfBjMidb5jI.*AAJTSQACMDE.*\
&subjectid=AQIC5wM2LY4SfcxuxIP0VnP2lVjs7ypEM6VDx6srk56CN1Q.*AAJTSQACMDE.*\
&logname=amRest.access\
&message=Hello%20World"
  

3.9. 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 "Content-Type: application/json" \
 --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."
}