PingAM 7.5.0

Authorization

This guide covers concepts, implementation procedures, and customization techniques for working with the authorization features of PingAM.

Name changes for ForgeRock products

Product names changed when ForgeRock became part of Ping Identity.

The following name changes have been in effect since early 2024:

Old name New name

ForgeRock Identity Cloud

PingOne Advanced Identity Cloud

ForgeRock Access Management

PingAM

ForgeRock Directory Services

PingDS

ForgeRock Identity Management

PingIDM

ForgeRock Identity Gateway

PingGateway

Learn more about the name changes in New names for ForgeRock products in the Knowledge Base.

Authorization and policy decisions

AM provides access management, which consists of:

  • Authentication: determining who is trying to access a resource

  • Authorization: determining whether to grant or deny access to the resource

The decision to grant access depends on a number of factors:

  • the policies governing access

  • who is trying to gain access

  • possible additional conditions, such as whether the access needs to happen over a secure channel or what time of day it is.

AM relies on policies to reach authorization decisions, such as whether to grant or deny access to a resource, or to grant or deny OAuth 2.0 scopes.

Related information: Dynamic OAuth 2.0 authorization

Protect resources

When you configure policy sets to protect resources, AM acts as the policy decision point (PDP), whereas AM web and Java agents act as policy enforcement points (PEP). In other words, an agent or other PEP takes responsibility only for enforcing a policy decision rendered by AM. When you configured applications and their policies in AM, you used AM as a policy administration point (PAP).

Concretely speaking, when a PEP requests a policy decision from AM, it specifies the target resource(s), the policy set (default: iPlanetAMWebAgentService), and information about the subject and the environment. AM as the PDP retrieves policies within the specified policy set that apply to the target resource(s). AM then evaluates those policies to make a decision based on the conditions matching those of the subject and environment. When multiple policies apply for a particular resource, the default logic for combining decisions is that the first evaluation resulting in a decision to deny access takes precedence over all other evaluations. AM only allows access if all applicable policies evaluate to a decision to allow access.

AM communicates the policy decision to the PEP. The concrete decision, applying policy for a subject under the specified conditions, is called an entitlement.

The entitlement indicates the resource(s) it applies to, the actions permitted and denied for each resource, and optionally, response attributes and advice.

Shows the relationship between realms, policies, and policy sets.
Figure 1. Protecting pages or applications

When AM denies a request due to a failed condition, AM can send advice to the PEP, and the PEP can then take remedial action. For instance, suppose a user comes to a website after authenticating with an email address and password, which is configured as authentication level 0. Had the user authenticated using a one-time password, the user would have had authentication level 1 in their session. Yet, because they have authentication level 0, they currently cannot access the desired page, as the policy governing access requires authentication level 1. AM sends advice, prompting the PEP to have the user re-authenticate using a one-time password, gaining authentication level 1, and thus having AM grant access to the protected page.

Policy decisions

AM has to match policies to resources to take policy decisions. For a policy to match, the resource has to match one of the resource patterns defined in the policy. The user making the request has to match a subject. Furthermore, at least one condition for each condition type has to be satisfied.

If more than one policy matches, AM has to reconcile differences. When multiple policies match, the order in which AM uses them to make a policy decision is not deterministic. However, a deny decision overrides an allow decision and so, by default, once AM reaches a deny decision, it stops checking further policies. If you want AM to continue checking despite the deny decision, go to Configure > Global Services > Policy Configuration, and enable Continue Evaluation on Deny Decision.

Example

Consider the case where AM protects a user profile web page. An AM web agent installed in the web server intercepts client requests to enforce policy. The policy says that only authenticated users can access the page to view and to update their profiles.

When a user browses to the profile page, the AM agent intercepts the request. The web agent notices that the request is to access a protected resource, but the request is coming from a user who has not yet logged in and consequently has no authorization to visit the page. The web agent therefore redirects the user’s browser to AM to authenticate.

AM receives the redirected user, serving a login page that collects the user’s email and password. With the email and password credentials, AM authenticates the user, and creates a session for the user. AM then redirects the user to the web agent, which gets the policy decision from AM for the page to access, and grants access to the page.

While the user has a valid session with AM, the user can go away to another page in the browser, come back to the profile page, and gain access without having to enter their email and password again.

Notice how AM and the web agent handle the access in the example. The website developer can offer a profile page, but the website developer never has to manage login, or handle who can access a page. As AM administrator, you can change authentication and authorization independently of updates to the website. You might need to agree with website developers on how AM identifies users, so web developers can identify users by their own names when they log in. By using AM and web or Java agents for authentication and authorization, your organization no longer needs to update web applications when you want to add external access to your Intranet for roaming users, open some of your sites to partners, only let managers access certain pages of your HR website, or allow users already logged in to their desktops to visit protected sites without having to type their credentials again.

Policies

Authorization policies let AM determine whether to grant a subject access to a resource.

A policy defines the following:

resources

The resource to which access is restricted, such as a web page, a mobile app, or a boarding area in an airport.

actions

The verbs that describe what users can do to the resource, such as read a web page, submit a web form, or access a boarding area.

subject conditions

Who the policy applies to, such as all authenticated users, only administrators, or only passengers with valid tickets for planes leaving soon.

environment conditions

The circumstances under which the policy applies, such as only during work hours, only when accessing from a specific IP address, or only when the flight is scheduled to leave within the next four hours.

response attributes

Information that AM attaches to a response following a policy decision, such as a name, email address, or frequent flyer status.

Policy conditions don’t determine the outcome of the policy but determine whether a specific policy is applicable and whether its actions should contribute towards the overall policy decision. If a condition fails (due to authentication failure, for example), AM disregards the corresponding policy and assesses any other configured policies to make the authorization decision.

Policies in the UI

A policy can only be created as part of a policy set.

You manage policies through the AM admin UI. Go to Realms > Realm Name > Authorization > Policy Sets and select the name of the policy set in which to configure a policy.

To…​ Action

Create a policy

Click Add a Policy.

When creating a policy, specify a name, a resource type, and at least one resource.

Click Create.

Modify a policy

Click the policy name or the pencil icon ().

Delete a policy

Click the delete icon () or click the policy name then x Delete.

Policy type names

Do not use any of the following characters in policy, policy set, or resource type names:

Double quotes (")
Plus sign (+)
Comma (,)
Less than (<)
Equals (=)
Greater than (>)
Backslash (\)
Forward slash (/)
Semicolon (;)
Null (\u0000)

Resources

To define resources that the policy applies to:

  1. Click the Resources pencil icon () or the Resources tab.

  2. Select a resource type from the Resource Type drop-down list.

    The resource type determines which resource patterns are available. The OAuth2 Scope resource type contains the same resource patterns as the URL resource type, as well as the * pattern.

    Use the resource patterns that are most relevant for the scopes in your environment.

    For information on configuring resource types, refer to Resource types.

  3. Select a resource pattern from the Resources drop-down list.

  4. Replace the asterisks with values for matching resources, and click Add.

    For information on configuring resource patterns, refer to Resource type patterns.

  5. Optionally, click Add Resource to add further resource patterns, or click () to delete a resource pattern.

  6. Save your changes.

Policy actions

To define policy actions that allow or deny access to a resource:

  1. Click the Actions pencil icon () or the Actions tab.

  2. Click Add an Action to select an action from the drop-down list.

  3. Select whether to allow or deny the action on the resources.

  4. Optionally, add further actions, or click () to delete actions.

  5. Save your changes.

Conditions

To define subject and environment conditions:

  • Combine logical operators with blocks of configured parameters to create a rule set. The policy uses this rule set to filter requests for resources.

  • Use drag and drop to nest logical operators at multiple levels to create complex rule sets.

Nested subject conditions
  • A gray horizontal bar indicates a valid point to drop a block.

    Drop blocks into drop points, which are shown as a gray horizontal band.

Subjects

To define the subject conditions the policy applies to:

  1. Click Add a Subject Condition, choose the type from the drop-down menu, and provide any required subject values.

  2. When complete, click the check icon () and drag the block into a valid drop point in the rule set.

  3. To add a logical operator, click Add a Logical Operator, choose between All Of, Not, and Any Of from the drop-down list, and drag the block into a valid drop point in the rule set.

  4. To edit a condition, click the edit icon (), or click () to delete.

  5. Continue combining logical operators and subject conditions and click Save Changes when you’ve finished.

Subject condition types Description

Authenticated Users

Any user that has successfully authenticated with AM.

Users & Groups

Search for and select one or more users or groups that are defined in AM admin UI under the Realms > Realm Name > Identities or the Groups tab.

OpenID Connect/Jwt Claim

Validate a claim within a JSON Web Token (JWT).

Type the name of the claim to validate in the Claim Name field, for example, sub, and the required value in the Claim Value field, and click the check icon ().

Repeat the step to enter additional claims.

The claim(s) will be part of the JWT payload together with the JWT header and signature. The JWT is sent in the authorization header of the bearer token.

This condition type only supports string equality comparisons, and is case-sensitive.

Never Match

Never match any subject. This disables the policy.

If you do not set a subject condition, Never Match is the default. In other words, you must set a subject condition for the policy to apply.

To match regardless of the subject, configure a Never Match subject condition inside a logical Not block.

Environments

To define the environment conditions the policy applies to:

  1. Click Add an Environment Condition, choose the type from the drop-down menu, and provide any required subject values.

    Script is the only environmental condition available for OAuth 2.0 policies.
  2. When complete, click the check icon () button and drag the block into a valid drop point in the rule set.

  3. To add a logical operator, click Add a Logical Operator, choose between All Of, Not, and Any Of from the drop-down list, and drag the block into a valid drop point in the rule set.

  4. To edit a condition, click the edit icon (), or click () to delete.

  5. Continue combining logical operators and subject conditions and click Save Changes when you’ve finished.

Environment condition types Description

Active Session Time

Set a condition for the maximum duration the user’s session has been active. To end the session if it has been active for longer than Max Session Time, set Terminate Sessions to True. The user will need to reauthenticate.

Authentication by Module Chain

Make the policy test the service that was used to authenticate the user.

Authentication by Module Instance

Make the policy test the authentication module used to authenticate, specified in Authentication Scheme. Specify a timeout for application authentication in Application Idle Timeout Scheme, and the name of the application in Application Name.

Authentication Level (greater than or equal to)

The minimum acceptable authentication level required by the policy.

Authentication Level (less than or equal to)

The maximum acceptable authentication level required by the policy.

Authentication to a Realm

Make the policy test the realm to which the user authenticated.

A session can only belong to one realm, and session upgrade between realms is not allowed.

Current Session Properties

Evaluate property values set in the user’s session.

Set Ignore Value Case to True to make the test case-insensitive.

Specify one or more pairs of session properties and values using the format property:value. For example, use clientType:genericHTML to test whether the value of the clientType property is equal to genericHTML.

Identity Membership

Make the policy apply if the user’s UUID is a member of at least one of the AMIdentity objects specified in AM Identity Name. For example, use this type to filter requests on the identity of a Web Service Client (WSC).

Java agents and web agents do not support the Identity Membership environment condition. Instead, use the Users & Groups subject condition.

IPv4 Address/DNS Name

The IP version 4 address from which the request originated.

The IP address is taken from the requestIp value of policy decision requests. If this is not provided, the IP address stored in the SSO token is used instead.

Specify a range of addresses to test against by entering four sets of up to three digits, separated by periods (.) in both Start IP and End IP.

If only one of these values is provided, it is used as a single IP address to match.

Optionally, specify a DNS name in DNS Name to filter requests to that domain.

IPv6 Address/DNS Name

The IP version 6 address from which the request originated.

The IP address is taken from the requestIp value of policy decision requests. If this is not provided, the IP address stored in the SSO token is used instead.

Specify a range of addresses to test against by entering eight sets of four hexadecimal characters, separated by a colon (:) in both Start IP and End IP.

If only one of these values is provided, it is used as a single IP address to match.

Optionally, specify a DNS name in DNS Name to filter requests to those from the specified domain.

Use an asterisk (*) in the DNS name to match multiple subdomains. For example, *.example.com applies to requests from www.example.com, secure.example.com, or any other subdomain of example.com.

LDAP Filter Condition

Make the policy test whether the user’s entry can be found using the LDAP search filter you specify in the directory configured for the policy service.

If you define a filter condition that uses LDAP accounts or groups in a different identity repository, you must configure the LDAP settings under Realms > Realm Name > Services > Policy Configuration.

OAuth2 Scope

Set a condition that an authorization request includes all the specified OAuth 2.0 scopes.

Scope names must follow OAuth 2.0 scope syntax described in RFC 6749, Access Token Scope. Separate multiple scope strings with spaces, such as openid profile.

The scope strings match regardless of order in which they occur, so openid profile is equivalent to profile openid.

The condition is also met when additional scope strings are provided beyond those required to match the specified list. For example, if the condition specifies openid profile, then openid profile email also matches.

Resource/Environment/IP Address

Define a complex condition, such as whether the user is making a request from the localhost, and has also authenticated in a particular way.

Entries must take the form of an IF…​ELSE statement. The IF statement can specify either IP to match the user’s IP address, or dnsName to match their DNS name.

If the IF statement is true, the THEN statement must also be true for the condition to be fulfilled. If not, relevant advice is returned in the policy evaluation request.

The available parameters for the THEN statement are as follows:

  • module: The module used to authenticate the user, for example, DataStore.

  • service: The service 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 the user was redirected from.

  • realm: The realm that was used to authenticate the user.

The IP address can be IPv4, IPv6, or a hybrid of the two. Example: IF IP=[127.0.0.1] THEN role=admins.

Script

Make the policy depend on the outcome of a JavaScript executed at the time of the policy evaluation.

For information on scripting policy conditions, refer to Scripted policy conditions.

Script is the only environmental condition available for OAuth 2.0 policies. Use scripts to capture the ClientId environmental attribute.

Time (day, date, time, and timezone)

Make the policy test when the policy is evaluated.

The values for day, date and time must be set in pairs that comprise a start and an end.

Day, date and time conditions in policies must consist of a start and an end value.

Transaction

Make the policy depend on the successful completion of transactional authorization.

Transactional authorization requires the user to authenticate for each access to the resource.

Transactions support the following authentication strategies:

  • Authenticate to Chain: The authentication chain the user must successfully complete to access the protected resource.

  • Authenticate to Realm: The full path of a realm in which the user must successfully authenticate to access the protected resource. For example, /alpha.

  • Authenticate to Tree: The authentication journey the user must successfully traverse to access the protected resource.

  • Authenticate to Module: The authentication module the user must successfully authenticate against to access the protected resource.

  • Auth Level:The minimum authentication level the user must achieve to access the protected resource.

If you specify a minimum, you must ensure there are methods available to users to reach that level.

If none are found, the policy returns a 400 Bad request error when attempting to complete the transaction.

Response attributes

Add user attributes from the identity repository as response attributes—either as subject attribute or static attributes—to the request header at policy decision time.

Note that response attributes are not available for the OAuth2 Scope resource type.

The web or Java agent for the protected resources/applications, or the protected resources/applications themselves, retrieve the policy response attributes to customize the application.

To define response attributes in the policy:

  1. Click the Response Attributes edit icon () or the Response Attributes tab.

  2. To add subject attributes, select them from the Subject attributes drop-down list.

    To remove an entry, select the value, and then press Delete (Windows/GNU/Linux) or Backspace (Mac OS X).

  3. To add a static attribute, specify the key-value pair for each static attribute. Enter the Property Name and its corresponding Property Value in the fields, and click Add (+).

    To edit a static attribute, click the edit icon (), or click () to delete.

  4. Continue adding subject and static attributes, and when finished, click Save Changes.

Example

This example policy requires authenticated users to have a session no longer than 30 minutes to access resources at https://www.example.com:*/*.

Example policy

Before testing your OAuth 2.0 policies, ensure your OAuth 2.0 provider is configured to interact with AM’s authorization service:

  1. In the AM admin UI, go to Realms > Realm Name > Services > OAuth2 Provider.

  2. Ensure Use Policy Engine for Scope decisions is enabled.

For more information about testing OAuth 2.0 policies, refer to Dynamic OAuth 2.0 authorization.

Policies over REST

You can manage policies over REST at the policies endpoint.

Policies belong to a policy set.

Policy resource objects

The policy resources are JSON objects. A policy object can include the following fields. The fields have JSON values—​strings, numbers, objects, sets, arrays, true, false, and null.

Policy field Description

_id, name(1)

A string identifying the policy.

This string matches the policy name part of the URL path to the resource.

Do not use any of the following characters in policy, policy set, or resource type names:

Double quotes (")
Plus sign (+)
Comma (,)
Less than (<)
Equals (=)
Greater than (>)
Backslash (\)
Forward slash (/)
Semicolon (;)
Null (\u0000)

_rev(1)

A system-generated revision string.

actionValues

An object where each field is an action name.

The resource type of the policy set governs the available actions.

The value for each action name field is a boolean indicating whether to allow the action by default. (AM also accepts 0 for false and any non-zero numeric value for true.)

active

A boolean indicating whether AM considers the policy active for evaluation purposes.

Default: false.

applicationName

A string identifying the policy set that contains the policy.

condition

An optional object specifying the environment conditions where the policy applies.

description

A string describing the policy.

resourceAttributes

An optional array of response attribute objects; does not apply to OAuth2 Scope resource types.

The default implementation returns statically defined attributes and attributes from user profiles. A response attribute object has these fields:

type

The implementation type:

  • Static for statically defined attributes

  • User for attributes from the user profile

propertyName

The attribute name.

propertyValues
  • For static attributes, the attribute values.

  • For user attributes, not used; AM determines the values when evaluating the policy.

resources

An array of the resource name pattern strings to which the policy applies.

The resource type must allow the patterns.

resourceTypeUuid

An optional string identifying the resource type that governs the policy.

subject

An optional object specifying the subject conditions where the policy applies.

createdBy(1)

A string indicating who created the policy.

creationDate(1)

An integer containing the creation time in milliseconds since January 1, 1970.

lastModifiedBy(1)

A string indicating who last changed the policy.

lastModifiedDate(1)

An integer containing the last modified time in milliseconds since January 1, 1970.

(1) Do not change the value of this field.

Environment conditions

Environment conditions clarify where the policy applies.

Express environment conditions as single conditions or combine them using boolean operators. The following example demonstrates a single environment condition that requires an access OAuth 2.0 scope:

{
  "type": "OAuth2Scope",
  "requiredScopes": ["access"]
}

The following example demonstrates a combined subject condition that excludes Saturday, Sunday, and a range of 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"
    }]
  }
}

The boolean operator strings to combine conditions in JSON correspond to these in the AM admin UI:

  • AND is All of.

  • OR is Any of.

  • NOT is Not.

Use the following environment conditions in your policies:

AMIdentityMembership

Applies to this array of users and groups.

{
  "type": "AMIdentityMembership",
  "amIdentityName": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
}

AM Java and web agents do not support the AMIdentityMembership environment condition. Use the Identity subject condition instead.

AuthLevel

Requires at least the specified authentication level.

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

Requires authentication with the specified module, policy set, and timeout.

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

Requires authentication to the specified realm.

{
  "type": "AuthenticateToRealm",
  "authenticateToRealm": "alpha"
}
AuthenticateToService

Requires authentication with the specified journey (tree).

{
    "type": "AuthenticateToService",
    "authenticateToService": "PushAuthentication"
}
IPv4 or IPv6

Requires a request from the specified IP address range or domain name.

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

Omit startIp and endIp and use the dnsName field to specify an array of domain name strings:

{
  "type": "IPv4",
  "dnsName": ["*.example.com"]
}
LDAPFilter

Requires the LDAP representation of the user’s profile matches the specified LDAP search filter.

{
  "type": "LDAPFilter",
  "ldapFilter": "(&(c=US)(preferredLanguage=en-us))"
}
LEAuthLevel

Requires at most the specified authentication level.

{
  "type": "LEAuthLevel",
  "authLevel": 2
}
OAuth2Scope

Requires the specified OAuth 2.0 scopes.

{
  "type": "OAuth2Scope",
  "requiredScopes": ["access"]
}
ResourceEnvIP

Requires a complex condition.

The following example requires an authentication level of at least 4 for requests from an IP address in 127.168.10.*:

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

Each resourceEnvIPConditionValue has one or more IF...THEN...[ELSE...THEN] statements.

When the IF statement is true, a true THEN statement fulfills the condition.

The IF statement specifies either:

  • An IPv4, IPv6, or hybrid address to match the IP address. The IP address can include wildcards.

  • A dnsName to match DNS name. The IP address can be IPv4 or IPv6 format, or a hybrid of the two, and can include wildcard characters.

THEN parameter Description

authlevel

The minimum required authentication level

realm

The realm where authentication completed

redirectURL

The URL the user was redirected from

role

The role of the authenticated user

service

The authentication journey

user

The name of the authenticated user

Session

Sets a maximum age of the session, and whether to terminate old sessions, forcing re-authentication.

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

Require attributes set in the user’s session.

{
  "type": "SessionProperty",
  "ignoreValueCase": true,
  "properties": {
    "CharSet": ["UTF-8"],
    "clientType": ["genericHTML"]
  }
}
SimpleTime

Set a time range. The type is the only required field.

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

Subject conditions

Subject conditions specify who the policy targets.

Express subject conditions as single conditions or combine them using boolean operators. The following example of a single subject condition means the policy applies to all authenticated users:

{"type": "AuthenticatedUsers"}

The following example of a combined subject condition means the policy applies to either of two users:

{
  "type": "OR",
  "subjects": [{
    "type": "Identity",
    "subjectValues": ["id=scarter,ou=user,o=alpha,ou=services,ou=am-config"]
  }, {
    "type": "Identity",
    "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
  }]
}

The boolean operator strings to combine conditions in JSON correspond to these in the AM admin UI:

  • AND is All of.

  • OR is Any of.

  • NOT is Not.

The type field specifies the subject:

AuthenticatedUsers

Applies to any user that successfully authenticated to AM regardless of the realm.

To limit this to a specific realm, add an AuthenticateToRealm environment condition to the policy.

Identity

Applies to the specified users or groups.

The following example means the policy applies to members of the account administrators group:

{
  "type": "Identity",
  "subjectValues": ["id=account-administrators,ou=group,o=alpha,ou=services,ou=am-config"]
}
JwtClaim

Applies based on a claim in a user’s JSON web token (JWT).

{
  "type": "JwtClaim",
  "claimName": "sub",
  "claimValue": "bjensen"
}
NONE

Never applies; AM never evaluates the policy as part of a decision.

Access the endpoints

The REST calls to manage policies rely on an account with the appropriate privileges:

  1. Create a resource type administrator.

    In the AM admin UI, select Realm > Realm Name > Identities > + Add Identity and fill the required fields.

    Record the username and password.

  2. Create a group that grants the privileges to the policy administrator.

    In the AM admin UI, select Realms > Realm Name > Identities > Groups > + Add Group to create a group with the following settings:

    Group ID

    am-policy-admins

    Members

    The policy administrator whose username you recorded

    Privileges

    Policy Admin
    Condition Types Read Access
    Decision Combiners Read Access
    Entitlement Rest Access
    Subject Types Read Access

  3. Before making REST calls to manage policies, authenticate as the policy administrator:

    $ curl \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'X-OpenAM-Username: <policy-admin-username>' \
    --header 'X-OpenAM-Password: <policy-admin-password>' \
    --header 'Accept-API-Version: resource=2.0, protocol=1.0' \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {"tokenId":"<policy-admin-tokenId>","successUrl":"/enduser/?realm=/alpha","realm":"/alpha"}

    For additional details, refer to Session token after authentication.

    Use the <policy-admin-tokenId> as the value of the AM session cookie (default name: iPlanetDirectoryPro) to access the REST endpoints.

Query policies

To list all the policy sets defined for a realm, send an HTTP GET request to the /json/realms/root/realms/Realm Name/policies endpoint with _queryFilter=true as the query string parameter.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0, protocol=2.1" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_queryFilter=true'
{
  "result": [{
    "_id": "myExamplePolicy",
    "_rev": "1669650078159",
    "name": "myExamplePolicy",
    "active": true,
    "description": "",
    "resources": ["*://*:*/*", "*://*:*/*?*"],
    "applicationName": "myPolicySet",
    "actionValues": {
      "GET": true,
      "PUT": true
    },
    "subject": {
      "type": "Identity",
      "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
    },
    "lastModifiedBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
    "lastModifiedDate": "2022-11-28T15:41:18.159Z",
    "createdBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
    "creationDate": "2022-11-28T15:39:04.82Z"
  }],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

Adapt the query string parameters to refine the results.

Field Supported _queryFilter operators

name

Equals (eq)

applicationName

description

createdBy

lastModifiedBy

creationDate

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

lastModifiedDate

(1) Do not use regular expression patterns with eq.

To list policies that explicitly reference a user or group as part of a subject condition, send an HTTP GET request to the /json/realms/root/realms/Realm Name/policies endpoint with the query string parameters _queryId=queryByIdentityUid and uid=universal-uid, where universal-uid is the universal ID for the user or group.

$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_queryId=queryByIdentityUid&uid=id=bjensen,ou=user,o=alpha,ou=services,ou=am-config'
{
  "result": [{
    "_id": "myExamplePolicy",
    "_rev": "1669650078159",
    "name": "myExamplePolicy",
    "active": true,
    "description": "",
    "resources": ["*://*:*/*", "*://*:*/*?*"],
    "applicationName": "myPolicySet",
    "actionValues": {
      "GET": true,
      "PUT": true
    },
    "subject": {
      "type": "Identity",
      "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
    },
    "lastModifiedBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
    "lastModifiedDate": "2022-11-28T15:41:18.159Z",
    "createdBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
    "creationDate": "2022-11-28T15:39:04.82Z"
  }],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

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

  • AM does not evaluate group membership.

    When you specify only groups in the condition, AM does not also return policies for users who are members of the specified groups.

  • AM supports only exact matches for users and groups; you cannot use wildcards.

  • AM only returns policies with Identity subject conditions—​not AMIdentityMembership environment conditions.

  • AM does not return policies with subject conditions that only contain the user or group in a logical NOT operator.

Read a policy

To read an individual policy in a realm, send an HTTP GET request to the /json/realms/root/realms/Realm Name/policies/policy-name endpoint.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies/myExamplePolicy'
{
  "_id": "myExamplePolicy",
  "_rev": "1669650078159",
  "name": "myExamplePolicy",
  "active": true,
  "description": "",
  "resources": ["*://*:*/*", "*://*:*/*?*"],
  "applicationName": "myPolicySet",
  "actionValues": {
    "GET": true,
    "PUT": true
  },
  "subject": {
    "type": "Identity",
    "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
  },
  "lastModifiedBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
  "lastModifiedDate": "2022-11-28T15:41:18.159Z",
  "createdBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
  "creationDate": "2022-11-28T15:39:04.82Z"
}

Create a policy

To create a policy in a realm, send an HTTP POST request to the /json/realms/root/realms/Realm Name/policies endpoint with _action=create as the query string parameter and a JSON representation of the policy as the POST data.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request POST \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--data '{
  "name": "myNewExamplePolicy",
  "active": true,
  "description": "Example policy",
  "applicationName": "myPolicySet",
  "actionValues": {
    "POST": false,
    "GET": true
  },
  "resources": ["https://www.example.com:443/*", "https://www.example.com:443/*?*"],
  "subject": {
    "type": "Identity",
    "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
  },
  "resourceTypeUuid": "76656a38-5f8e-401b-83aa-4ccb74ce88d2"
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies/?_action=create'
{
  "_id": "myExamplePolicy",
  "_rev": "1669650078159",
  "name": "myExamplePolicy",
  "active": true,
  "description": "",
  "resources": ["https://www.example.com:443/*", "https://www.example.com:443/*?*"],
  "applicationName": "myPolicySet",
  "actionValues": {
    "GET": true,
    "POST": false
  },
  "subject": {
    "type": "Identity",
    "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
  },
  "lastModifiedBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
  "lastModifiedDate": "2022-11-28T15:41:18.159Z",
  "createdBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,ou=am-config",
  "creationDate": "2022-11-28T15:39:04.82Z"
}

Before testing OAuth 2.0 policies, configure the OAuth2 Provider service for the realm to Use Policy Engine for Scope decisions.

For details, refer to Dynamic OAuth 2.0 authorization.

Update a policy

To update an individual policy in a realm, send an HTTP PUT request to the /json/realms/root/realms/Realm Name/policies/policy-name endpoint with a JSON representation of the updated policy as the PUT data.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request PUT \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
--header "Content-Type: application/json" \
--data '{
  "_id": "myNewExamplePolicy",
  "_rev": "1669721075177",
  "name": "myNewExamplePolicy",
  "active": true,
  "description": "Example policy",
  "resources": ["https://www.example.com:443/*?*", "https://www.example.com:443/*"],
  "applicationName": "myPolicySet",
  "actionValues": {
    "POST": true,
    "GET": true
  },
  "subject": {
    "type": "Identity",
    "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
  }
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies/myNewExamplePolicy'
{
  "_id": "myNewExamplePolicy",
  "_rev": "1669721293147",
  "name": "myNewExamplePolicy",
  "active": true,
  "description": "Example policy",
  "resources": ["https://www.example.com:443/*?*", "https://www.example.com:443/*"],
  "applicationName": "myPolicySet",
  "actionValues": {
    "POST": true,
    "GET": true
  },
  "subject": {
    "type": "Identity",
    "subjectValues": ["id=bjensen,ou=user,o=alpha,ou=services,ou=am-config"]
  },
  "lastModifiedBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,o=alpha,ou=services,ou=am-config",
  "lastModifiedDate": "2022-11-29T11:28:13.147Z",
  "createdBy": "id=policy-administrator,ou=user,ou=alpha,ou=services,o=alpha,ou=services,ou=am-config",
  "creationDate": "2022-11-29T11:24:35.177Z"
}

Delete a policy

To delete an individual policy in a realm, send an HTTP DELETE request to the /json/realms/root/realms/Realm Name/policies/policy-name endpoint.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request DELETE \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies/myNewExamplePolicy'
{"_id":"myNewExamplePolicy","_rev":"0"}

Copy and move policies

To copy or move an individual policy, send an HTTP POST request to the /json/realms/root/realms/Realm Name/policies/policyName endpoint. Include the appropriate parameters and POST data.

If you omit the realm path from the URL, AM uses the Top Level Realm.

The appropriate parameters for copying and moving policies take the following into account:

  • The realm in the URL is the realm of the policy or policies to copy or to move.

  • The policy name in the URL is the name of an individual policy to copy or to move.

  • Specify either _action=copy or _action=move as the query string parameter.

  • When moving policies from one realm to another, use the administrator’s AM session cookie to authenticate.

    The policy administrator is a member of a realm, and does not have access to change another realm’s settings.

The following example copies myExamplePolicy from the alpha realm to Copied policy in the bravo realm.

$ curl \
--request POST \
--header "iPlanetDirectoryPro: <amAdmin-tokenId>" \
--header "Accept-API-Version: resource=2.1" \
--header "Content-Type: application/json" \
--data '{
  "to": {
    "name": "Copied policy",
    "realm": "/bravo",
    "resourceType": "76656a38-5f8e-401b-83aa-4ccb74ce88d2"
  }
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies/myExamplePolicy?_action=copy'
{
  "name": "Copied policy",
  "…​": "…​"
}

The POST data JSON object for copying and moving individual policies has these fields:

Outer field Inner field Description

to

name

The target policy.

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

application

The target policy set.

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

realm

The target realm.

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

resourceType

The resource type UUID for the target policy.

The resource type must exist in the target realm.

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

The following example moves myExamplePolicy to Moved policy in the same realm. The policy administrator can complete this request because the target is in the same realm.

$ curl \
--request POST \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=2.1" \
--header "Content-Type: application/json" \
--data '{
  "to": {
    "name": "Moved policy",
    "realm": "/alpha",
    "resourceType": "76656a38-5f8e-401b-83aa-4ccb74ce88d2"
  }
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies/myExamplePolicy?_action=move'
{
  "name": "Moved policy",
  "…​": "…​"
}

To copy or move multiple policies, send an HTTP POST request to the /json/realms/root/realms/Realm Name/policies endpoint with the appropriate parameters and POST data.

The following example copies all the policies in myPolicySet to the bravo realm:

  • The target policy set already exists in the bravo realm. It allows the same policies as its counterpart in the alpha realm.

  • The bravo realm has resource types matching those in the alpha realm.

$ curl \
--request POST \
--header "iPlanetDirectoryPro: <amAdmin-tokenId>" \
--header "Accept-API-Version: resource=2.1" \
--header "Content-Type: application/json" \
--data '{
  "from": {
    "application": "myPolicySet"
  },
  "to": {
    "realm": "/bravo",
    "namePostfix": "-copy"
  },
  "resourceTypeMapping": {
    "d60b7a71-1dc6-44a5-8e48-e4b9d92dee8b": "d60b7a71-1dc6-44a5-8e48-e4b9d92dee8b",
    "76656a38-5f8e-401b-83aa-4ccb74ce88d2": "76656a38-5f8e-401b-83aa-4ccb74ce88d2"
  }
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_action=copy'
[{
  "name": "Moved policy-copy",
  "…​": "…​"
}]

The POST data JSON object for copying and moving multiple policies has these fields:

Outer field Inner field Description

from

application

The policy set to copy or move policies from.

Required.

to

application

The target policy set.

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

realm

The target realm.

Required when copying or moving policies to a different realm.

namePostfix

A string appended to target policy names to prevent clashes.

Required.

resourceTypeMapping

The UUID(s) of the original resource type(s).

The UUID(s) of the target resource type(s).

Each pair of resource types must have the same resource patterns.

Required when copying or moving policies to a different realm.

Environment conditions

AM lets you read and query environment condition schema over REST.

The schemas describe the environment condition JSON objects that you include in authorization policies. Each environment condition schema has these fields:

title

The short name for the environment condition.

logical

Whether the type is a logical operator or takes a predicate.

config

The layout of the environment condition object.

Environment conditions have these characteristics:

  • Environment conditions are the same for each realm.

  • The only environment condition for OAuth 2.0 policies is Script. Use scripts to capture the ClientId environment attribute.

To list all environment condition schemas, send an HTTP GET request to the /json/realms/root/realms/Realm Name/conditiontypes endpoint with _queryFilter=true as the query string parameter.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0, protocol=2.1" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/conditiontypes?_queryFilter=true'
Display output
{
  "result": [{
    "_id": "AMIdentityMembership",
    "title": "AMIdentityMembership",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "amIdentityName": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }, {
    "_id": "AND",
    "title": "AND",
    "logical": true,
    "config": {
      "type": "object",
      "properties": {
        "conditions": {
          "type": "array"
        }
      }
    }
  }, {
    "_id": "AuthLevel",
    "title": "AuthLevel",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "authLevel": {
          "type": "integer"
        }
      }
    }
  }, {
    "_id": "AuthScheme",
    "title": "AuthScheme",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "authScheme": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "applicationIdleTimeout": {
          "type": "integer"
        },
        "applicationName": {
          "type": "string"
        }
      }
    }
  }, {
    "_id": "AuthenticateToRealm",
    "title": "AuthenticateToRealm",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "authenticateToRealm": {
          "type": "string"
        }
      }
    }
  }, {
    "_id": "AuthenticateToService",
    "title": "AuthenticateToService",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "authenticateToService": {
          "type": "string"
        }
      }
    }
  }, {
    "_id": "IPv4",
    "title": "IPv4",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "startIp": {
          "type": "string"
        },
        "endIp": {
          "type": "string"
        },
        "dnsName": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }, {
    "_id": "IPv6",
    "title": "IPv6",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "startIp": {
          "type": "string"
        },
        "endIp": {
          "type": "string"
        },
        "dnsName": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }, {
    "_id": "LDAPFilter",
    "title": "LDAPFilter",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "ldapFilter": {
          "type": "string"
        }
      }
    }
  }, {
    "_id": "LEAuthLevel",
    "title": "LEAuthLevel",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "authLevel": {
          "type": "integer"
        }
      }
    }
  }, {
    "_id": "NOT",
    "title": "NOT",
    "logical": true,
    "config": {
      "type": "object",
      "properties": {
        "condition": {
          "type": "object",
          "properties": {}
        }
      }
    }
  }, {
    "_id": "OAuth2Scope",
    "title": "OAuth2Scope",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "requiredScopes": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }, {
    "_id": "OR",
    "title": "OR",
    "logical": true,
    "config": {
      "type": "object",
      "properties": {
        "conditions": {
          "type": "array"
        }
      }
    }
  }, {
    "_id": "Policy",
    "title": "Policy",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "className": {
          "type": "string"
        },
        "properties": {
          "type": "object"
        }
      }
    }
  }, {
    "_id": "ResourceEnvIP",
    "title": "ResourceEnvIP",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "resourceEnvIPConditionValue": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }, {
    "_id": "Script",
    "title": "Script",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "scriptId": {
          "type": "string"
        }
      }
    }
  }, {
    "_id": "Session",
    "title": "Session",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "maxSessionTime": {
          "type": "number"
        },
        "terminateSession": {
          "type": "boolean",
          "required": true
        }
      }
    }
  }, {
    "_id": "SessionProperty",
    "title": "SessionProperty",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "ignoreValueCase": {
          "type": "boolean",
          "required": true
        },
        "properties": {
          "type": "object"
        }
      }
    }
  }, {
    "_id": "SimpleTime",
    "title": "SimpleTime",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "startTime": {
          "type": "string"
        },
        "endTime": {
          "type": "string"
        },
        "startDay": {
          "type": "string"
        },
        "endDay": {
          "type": "string"
        },
        "startDate": {
          "type": "string"
        },
        "endDate": {
          "type": "string"
        },
        "enforcementTimeZone": {
          "type": "string"
        }
      }
    }
  }, {
    "_id": "Transaction",
    "title": "Transaction",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "authenticationStrategy": {
          "type": "string"
        },
        "strategySpecifier": {
          "type": "string"
        }
      }
    }
  }],
  "resultCount": 20,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

To read an environment condition schema, send an HTTP GET request to the /json/realms/root/realms/Realm Name/conditiontypes/condition-type endpoint.

$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/conditiontypes/IPv4'
{
  "_id": "IPv4",
  "_rev": "1669721841603",
  "title": "IPv4",
  "logical": false,
  "config": {
    "type": "object",
    "properties": {
      "startIp": {
        "type": "string"
      },
      "endIp": {
        "type": "string"
      },
      "dnsName": {
        "type": "array",
        "items": {
          "type": "string"
        }
      }
    }
  }
}

Subject conditions

AM lets you read and query subject condition schema over REST.

The schemas describe the subject condition JSON objects that you include in authorization policies. Each environment condition schema has these fields:

title

The short name for the subject condition.

logical

Whether the type is a logical operator or takes a predicate.

config

The layout of the subject condition object.

Subject conditions are the same for each realm.

To list all subject condition schemas, send an HTTP GET request to the /json/realms/root/realms/Realm Name/subjecttypes endpoint with _queryFilter=true as the query string parameter.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0, protocol=2.1" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/subjecttypes?_queryFilter=true'
Display output
{
  "result": [{
    "_id": "AND",
    "title": "AND",
    "logical": true,
    "config": {
      "type": "object",
      "properties": {
        "subjects": {
          "type": "array"
        }
      }
    }
  }, {
    "_id": "AuthenticatedUsers",
    "title": "AuthenticatedUsers",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {}
    }
  }, {
    "_id": "Identity",
    "title": "Identity",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "subjectValues": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }, {
    "_id": "JwtClaim",
    "title": "JwtClaim",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "claimName": {
          "type": "string"
        },
        "claimValue": {
          "type": "string"
        }
      }
    }
  }, {
    "_id": "NONE",
    "title": "NONE",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {}
    }
  }, {
    "_id": "NOT",
    "title": "NOT",
    "logical": true,
    "config": {
      "type": "object",
      "properties": {
        "subject": {
          "type": "object",
          "properties": {}
        }
      }
    }
  }, {
    "_id": "OR",
    "title": "OR",
    "logical": true,
    "config": {
      "type": "object",
      "properties": {
        "subjects": {
          "type": "array"
        }
      }
    }
  }, {
    "_id": "Policy",
    "title": "Policy",
    "logical": false,
    "config": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string"
        },
        "className": {
          "type": "string"
        },
        "values": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }],
  "resultCount": 8,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

To read a subject condition schema, send an HTTP GET request to the /json/realms/root/realms/Realm Name/subjecttypes/subject-type endpoint.

$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0, protocol=2.1" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/subjecttypes/Identity'
{
  "_id": "Identity",
  "_rev": "1669721896953",
  "title": "Identity",
  "logical": false,
  "config": {
    "type": "object",
    "properties": {
      "subjectValues": {
        "type": "array",
        "items": {
          "type": "string"
        }
      }
    }
  }
}

Query subject attributes

When you define a policy subject condition, the condition can depend on the values of subject attributes stored in a user’s profile. The subject attributes that you can use depend on the LDAP User Attributes configured for the identity store where AM looks up the user’s profile. For more information on these attributes, refer to Identity stores.

To list the available subject attributes, send an HTTP GET request 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.

For example:

$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/subjectattributes/?_queryFilter=true'
{
  "result" : [
      "sunIdentityServerPPInformalName",
      "sunIdentityServerPPFacadeGreetSound",
      "uid",
      "manager",
      "sunIdentityServerPPCommonNameMN",
      "sunIdentityServerPPLegalIdentityGender",
      "preferredLocale",
      "…​",
      "…​",
      "…​"
  ],
  "resultCount": 87,
  "pagedResultsCookie": null,
  "remainingPagedResults": 0
}
No pagination cookie is set and the subject attribute names are all returned as part of the result array.

Decision combiners

Decision combiners describe how to resolve policy decisions when multiple policies apply.

Decision combiners are the same for each realm.

To list all decision combiners, send an HTTP GET request to the /json/realms/root/realms/Realm Name/decisioncombiners endpoint with _queryFilter=true as the query string parameter.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0, protocol=2.1" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/decisioncombiners?_queryFilter=true'
{
  "result": [{
    "_id": "DenyOverride",
    "title": "DenyOverride"
  }],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

To read a decision combiner, send an HTTP GET request to the /json/realms/root/realms/Realm Name/decisioncombiners/decision-combiner endpoint.

$ curl \
--header "iPlanetDirectoryPro: <policy-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/decisioncombiners/DenyOverride'
{"_id":"DenyOverride","_rev":"1669722054745","title":"DenyOverride"}

Resource types

Resource types define a template for the resources that policies apply to, and the actions that can be performed on those resources.

AM needs a policy to decide whether a user can access a resource. When you configure a policy, you also configure a resource (or a pattern to match several resources) that the policy applies to, and the actions that the policy allows or denies.

Resource types are templates that you can define once and reuse in several policies. For example, you could create a template that always allows PUT and POST operations from your internal network.

Default resource types

AM includes two resource types by default: URL and OAuth2 Scope. These default resource types are sufficient for most environments.

URL resource type

The URL resource type acts as a template for protecting web pages or applications. It contains resource patterns, such as *://*:*/*?*, that can be more specific when used in the policy.

This resource type supports the following actions:

GET
POST
PUT
HEAD
PATCH
DELETE
OPTIONS

For example, an application for Example.com’s HR service might contain resource types that constrain all policies to apply to URL resource types under http*://example.com/hr* and http*://example.com/hr*?*, and only allow HTTP GET and POST actions.

OAuth2 Scope resource type

The OAuth2 Scope resource type acts as a template for granting or denying OAuth 2.0 scopes. It contains a string-based scope pattern, *, and two URL-based scope patterns, such as *://*:*/*?*.

The resource supports the GRANT action, which can be allowed or denied.

Resource types in the UI

You manage resource types through the AM admin UI. Go to Realms > Realm Name > Authorization > Resource Types.

To…​ Action

Create a resource type

Click New Resource Type.

When creating a resource type, specify at least one action and one pattern.

Modify a resource type

Click the resource type name or the pencil icon ().

Delete a resource type

Click the delete icon () or click the resource type name then the x Delete button.

The AM admin UI prevents deletion if any policies or policy sets depend on the resource type.

Resource type names

Do not use any of the following characters in policy, policy set, or resource type names:

Double quotes (")
Plus sign (+)
Comma (,)
Less than (<)
Equals (=)
Greater than (>)
Backslash (\)
Forward slash (/)
Semicolon (;)
Null (\u0000)

Resource type patterns

Policies apply to resources that match their patterns.

  • A policy belongs to a policy set.

  • A policy set permits one or more resource types in their policies.

  • A policy can only define patterns that fit the patterns of its resource types.

Wildcards

Resource type patterns can include a mix of literal characters and wildcards, * or -*- by default. Wildcards can appear anywhere in a resource type pattern to match resources, such as URLs or OAuth 2.0 scopes.

  • Do not mix * and -*- in the same pattern.

  • Wildcards cannot be escaped.

  • By default, comparisons are not case-sensitive.

    To configure the delimiter, wildcards, and case-sensitivity, in the AM admin UI, go to Configure > Global Services > Policy Configuration, and edit the Resource Comparator.

Wildcards in schemes, hosts, and port numbers

When using wildcards for the scheme and authority parts of a URL:

  • The pattern *://*:*/* matches these URLs:

    http://www.example.com:80/index.html
    https://www.example.com:443/index.html
    http://www.example.net:8080/index.html

  • Omitting the port number implies the default port number for the scheme:

    http://www.example.com/* is the same as http://www.example.com:80/*.

    https://www.example.com/* is the same as https://www.example.com:443/*.

Wildcards in paths

Wildcards have these properties in a URL path:

  • The wildcard * matches multiple path segments.

    For example, https://www.example.com/* matches https://www.example.com/, https://www.example.com/index.html, and https://www.example.com/company/images/logo.png.

  • The wildcard -*- matches a single path segment.

    For example, https://www.example.com/-*- matches https://www.example.com/index.html.

    It does not match https://www.example.com/company/resource.html or https://www.example.com/company/images/logo.png.

  • Duplicate slashes (//) count as a single slash.

    http://www.example.com//path/ and http://www.example.com/path// are equivalent.

  • A trailing slash counts as a distinct part of the resource to match.

    https://www.example.com/path and https://www.example.com/path/ are not equivalent.

Wildcards in query strings

Wildcards do not match ?.

Add explicit patterns to match URLs with query strings:

  • When matching URLs protected by a web or Java agent, an asterisk (*) at the end of a pattern after ? matches one or more characters, not zero or more characters.

    For example, https://www.example.com/*?* matches https://www.example.com/users?_action=create, not https://www.example.com/users?.

    To match all URLs under https://www.example.com/, specify three patterns:

    https://www.example.com/*
    https://www.example.com/*?
    https://www.example.com/*?*

  • When matching resources with a policies?_action=evaluate REST call, an asterisk (*) at the end of a pattern after ? matches zero or more characters.

    For example, https://www.example.com/*?* matches https://www.example.com/users?_action=create and https://www.example.com/users?.

    To match all URLs under http://www.example.com/, specify two patterns:

    https://www.example.com/*
    https://www.example.com/*?*

  • AM normalizes query strings before checking whether a policy matches a resource.

    To normalize the query string, AM sorts the query string field-value pairs alphabetically by field name. These query strings are equivalent:

    ?subject=SPBnfm+t5PlP+ISyQhVlplE22A8=&action=get
    ?action=get&subject=SPBnfm+t5PlP+ISyQhVlplE22A8=

Non-ASCII characters

Use percent-encoding for non-ASCII characters in resource patterns.

For example, to match resources under the Internationalized Resource Identifier (IRI) https://www.example.com/forstå/ use:

https://www.example.com:443/forst%C3%A5/*
https://www.example.com:443/forst%C3%A5/*?*

Resource type actions

AM policies use actions to grant or deny access to a resource. A policy can only determine actions defined by its resource types.

Choose a name that summarizes the action the principal aims to perform on the resource. The default state for each action is either Allow or Deny.

Example

The following screen creates a resource type for policies to switch lights on and off:

Add the patterns and actions that policies using this resource type can make use of.
Figure 2. Configuring a resource type in the UI

Resource types over REST

You can manage resource types over REST at the resourcetypes endpoint.

AM stores resource types as JSON objects. A resource type can include the following fields. The fields have JSON values—​strings, numbers, objects, sets, arrays, true, false, and null.

Resource type field Description

_id, uuid(1)

A unique, system-generated UUID string.

Use this string to identify a specific resource type. Do not change the generated UUID.

_rev(1)

A system-generated revision string.

name

A human-readable name string for the resource type.

Do not use any of the following characters in policy, policy set, or resource type names:

Double quotes (")
Plus sign (+)
Comma (,)
Less than (<)
Equals (=)
Greater than (>)
Backslash (\)
Forward slash (/)
Semicolon (;)
Null (\u0000)

description

An optional text string to help identify the resource type.

patterns

An array of resource pattern strings specifying URLs or resource names to protect.

For details, refer to Resource type patterns.

actions

An object where each field is an action name.

The value for each action name field is a boolean indicating whether to allow the action by default in policies that derive from this resource type.

createdBy(1)

A string indicating who created the resource type.

creationDate(1)

An integer containing the creation time in milliseconds since January 1, 1970.

lastModifiedBy(1)

A string indicating who last changed the resource type.

lastModifiedDate(1)

An integer containing the last modified time in milliseconds since January 1, 1970.

(1) Do not change the value of this field.

Access the endpoints

The REST calls to manage resource types rely on an account with the appropriate privileges:

  1. Create a resource type administrator.

    In the AM admin UI, select Realm > Realm Name > Identities > + Add Identity and fill the required fields.

    Record the username and password.

  2. Create a group that grants the privileges to the resource type administrator.

    Select Realms > Realm Name > Identities > Groups > + Add Group to create a group with the following settings:

    Group ID

    am-resource-type-admins

    Members

    The resource type administrator whose username you recorded

    Privileges

    Policy Admin
    Resource Type Modify Access
    Resource Type Read Access

  3. Before making REST calls to manage resource types, authenticate as the resource type administrator:

    $ curl \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'X-OpenAM-Username: <resource-type-admin-username>' \
    --header 'X-OpenAM-Password: <resource-type-admin-password>' \
    --header 'Accept-API-Version: resource=2.0, protocol=1.0' \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {"tokenId":"<resource-type-admin-tokenId>","successUrl":"/enduser/?realm=/alpha","realm":"/alpha"}

    For additional details, refer to Session token after authentication.

    Use the <resource-type-admin-tokenId> as the value of the AM session cookie (default name: iPlanetDirectoryPro) to access the REST endpoints.

Query resource types

To list all the resource types defined for a realm, send an HTTP GET request to the /json/realms/root/realms/Realm Name/resourcetypes endpoint with _queryFilter=true as the query string parameter.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <resource-type-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/resourcetypes?_queryFilter=true'
[{
  "result": [{
    "_id": "fcaee7dc-f99c-43b1-b10d-592e1c4bd394",
    "uuid": "fcaee7dc-f99c-43b1-b10d-592e1c4bd394",
    "name": "Light",
    "description": "",
    "patterns": ["light://*/*"],
    "actions": {
      "switch_off": false,
      "switch_on": false
    },
    "createdBy": "id=a980a458-2654-4d4f-a12a-d4bfa39534f7,ou=user,ou=am-config",
    "creationDate": 1669038769034,
    "lastModifiedBy": "id=a980a458-2654-4d4f-a12a-d4bfa39534f7,ou=user,ou=am-config",
    "lastModifiedDate": 1669038769034
  }, {
    "_id": "76656a38-5f8e-401b-83aa-4ccb74ce88d2",
    "uuid": "76656a38-5f8e-401b-83aa-4ccb74ce88d2",
    "name": "URL…​"
  }, {
    "_id": "d60b7a71-1dc6-44a5-8e48-e4b9d92dee8b",
    "uuid": "d60b7a71-1dc6-44a5-8e48-e4b9d92dee8b",
    "name": "OAuth2 Scope…​"
  }],
  "resultCount": 3,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

Adapt the query string parameters to refine the results.

Field Supported _queryFilter operators

uuid

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

name

description

patterns

actions

Read a resource type

To read a resource type in a realm, send an HTTP GET request to the /json/realms/root/realms/Realm Name/resourcetypes/uuid endpoint, where uuid is the value of the "uuid" field for the resource.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <resource-type-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/resourcetypes/fcaee7dc-f99c-43b1-b10d-592e1c4bd394'
{
  "_id": "fcaee7dc-f99c-43b1-b10d-592e1c4bd394",
  "_rev": "1669045336245",
  "uuid": "fcaee7dc-f99c-43b1-b10d-592e1c4bd394",
  "name": "Light",
  "description": "",
  "patterns": ["light://*/*"],
  "actions": {
    "switch_off": false,
    "switch_on": false
  },
  "createdBy": "id=a980a458-2654-4d4f-a12a-d4bfa39534f7,ou=user,ou=am-config",
  "creationDate": 1669038769034,
  "lastModifiedBy": "id=a980a458-2654-4d4f-a12a-d4bfa39534f7,ou=user,ou=am-config",
  "lastModifiedDate": 1669038769034
}

Create a resource type

To create a resource type in a realm, send an HTTP POST request to the /json/realms/root/realms/Realm Name/resourcetypes endpoint with _action=create as the query string parameter and a JSON representation of the resource type as the POST data.

If you omit the realm path from the URL, AM uses the Top Level Realm.

AM generates the UUID for the resource.

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: <resource-type-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
--data '{
  "name": "My Resource Type",
  "actions": {
    "LEFT": true,
    "RIGHT": true,
    "UP": true,
    "DOWN": true
  },
  "patterns": ["https://device/location/*"]
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/resourcetypes/?_action=create'
{
  "_id": "c7e09ca1-a0db-4434-9327-ca685ae99899",
  "uuid": "c7e09ca1-a0db-4434-9327-ca685ae99899",
  "name": "My Resource Type",
  "description": null,
  "patterns": ["https://device/location/*"],
  "actions": {
    "RIGHT": true,
    "DOWN": true,
    "UP": true,
    "LEFT": true
  },
  "createdBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "creationDate": 1669045619375,
  "lastModifiedBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "lastModifiedDate": 1669045619375
}

Update a resource type

To update a resource type in a realm, send an HTTP PUT request to the /json/realms/root/realms/Realm Name/resourcetypes/uuid endpoint, where uuid is the value of the "uuid" field for the resource. Include a JSON representation of the resource type as the PUT body, making sure the "uuid" and "_id" fields match the original resource.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request PUT \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: <resource-type-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
--data '{
  "name": "My Resource Type",
  "actions": {
    "LEFT": true,
    "RIGHT": true,
    "UP": false,
    "DOWN": false
  },
  "patterns": ["https://device/location/*"]
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/resourcetypes/c7e09ca1-a0db-4434-9327-ca685ae99899'
{
  "_id": "c7e09ca1-a0db-4434-9327-ca685ae99899",
  "uuid": "c7e09ca1-a0db-4434-9327-ca685ae99899",
  "name": "My Resource Type",
  "description": null,
  "patterns": ["https://device/location/*"],
  "actions": {
    "RIGHT": true,
    "DOWN": false,
    "UP": false,
    "LEFT": true
  },
  "createdBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "creationDate": 1669045619375,
  "lastModifiedBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "lastModifiedDate": 1669045765822
}

Delete a resource type

To delete a resource type from a realm, send an HTTP DELETE request to the /json/realms/root/realms/Realm Name/resourcetypes/uuid endpoint, where uuid is the value of the "uuid" field for the resource.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request DELETE \
--header "iPlanetDirectoryPro: <resource-type-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/resourcetypes/c7e09ca1-a0db-4434-9327-ca685ae99899'
{"_id":"c7e09ca1-a0db-4434-9327-ca685ae99899","_rev":"0"}

AM does not permit deletion of a resource type when a policy set or policy depends on it. If you attempt to delete a resource type that is in use, AM returns an HTTP 409 Conflict status code and a message like the one in the following example:

$ curl \
--request DELETE \
--header "iPlanetDirectoryPro: <resource-type-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/resourcetypes/76656a38-5f8e-401b-83aa-4ccb74ce88d2'
{
  "code": 409,
  "reason": "Conflict",
  "message": "Unable to remove resource type 76656a38-5f8e-401b-83aa-4ccb74ce88d2 because it is referenced in the policy model."
}

Remove the dependency on the resource type from all policy sets and policies before you delete it.

Policy sets

AM uses a policy to determine whether to grant a principal access to a resource.

Policies belong to policy sets. Policy sets define a template for policies that apply to one or more resource types. A policy set groups policies with similar characteristics that protect websites, web applications, or other resources. It eliminates the need to configure the same basic settings repeatedly for each policy.

AM includes the following default policy sets:

  • The Default Policy Set, iPlanetAMWebAgentService, for web and Java agents. You can create new policy sets for agents and configure them in the agent profile.

  • The Default OAuth2 Scopes Policy Set, oauth2Scopes, for the OAuth 2.0 service.

Application types are templates for policy sets. The AM admin UI does not show application types. When you define a policy or policy set over REST, the application type appears in the JSON resource. You only configure application types using the REST API. The default application types suffice for most use cases.

When creating and editing policy sets, consider the following points:

  • You can specify the realm and policy set in an AM web or Java agent profile.

    AM directs requests from the agent to the specified realm and policy set, providing compatibility with older web and Java agents.

    For details, refer to the agent documentation:

  • AM only honors OAuth2 Scope resource type policies. Configure policies for your OAuth 2.0 service in a custom policy set with OAuth2 Scope resource type policies, or use the existing Default OAuth2 Scopes Policy Set.

  • AM creates a policy set with policies for UMA 2.0 resources and identities. A resource owner using UMA 2.0 relies on the policies to share their registered resources.

    These policies appear in the AM admin UI as read-only. Even the administrative users like amAdmin cannot edit them. Policy administrators can view and delete the policies.

Policy sets in the UI

You manage policy sets through the AM admin UI. Go to Realms > Realm Name > Authorization > Policy Sets.

To…​ Action

Create a policy set

Click + New Policy Set.

When creating a policy set, specify an ID and select at least one resource type.

You cannot change the ID after you create the policy set.

Modify a policy set

Click the policy set name or the pencil icon ().

Delete a policy set

Click the delete icon () or click the policy set name then the x Delete button.

The AM admin UI prevents deletion if the set contains any policies.

Policy set names

Do not use any of the following characters in policy, policy set, or resource type names:

Double quotes (")
Plus sign (+)
Comma (,)
Less than (<)
Equals (=)
Greater than (>)
Backslash (\)
Forward slash (/)
Semicolon (;)
Null (\u0000)

Policy sets over REST

You can manage policy sets over REST at the applications endpoint. ("Application" is the internal AM name for a policy set.)

Policy sets are realm-specific. The URI for the policy set API can therefore contain a realm component; for example, /json/realms/root/realms/Realm Name/applications. If you omit the realm path from the URL, AM uses the Top Level Realm.

AM stores policy sets as JSON objects. A policy set can include the following fields. The fields have JSON values—​strings, numbers, objects, sets, arrays, true, false, and null.

Policy set field Description

_id, name

A unique string identifying the policy set.

Do not use any of the following characters in policy, policy set, or resource type names:

Double quotes (")
Plus sign (+)
Comma (,)
Less than (<)
Equals (=)
Greater than (>)
Backslash (\)
Forward slash (/)
Semicolon (;)
Null (\u0000)

_rev(1)

A system-generated revision string.

actions

An object where each field is an action name.

The value for each action name field is a boolean indicating whether to allow the action by default.

applicationType

A string containing the application type name.

For more information, refer to Policy set application types over REST.

attributeNames

An optional array of response attribute name strings restricting what policies in this set can return.

conditions

An array of environment condition identifier strings defining environment conditions allowed for policies in this set.

description

An optional text string to help identify the policy set.

editable

A boolean indicating whether you can edit this policy set definition after creation.

entitlementCombiner

An optional string identifying how AM evaluates multiple policies for a resource.

For more information, refer to Manage decision combiners.

realm

A string identifying the realm for this policy set.

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.

resources

An array of resource pattern strings for resources governed by policies in this set.

resourceComparator

An optional string identifying the fully qualified class name of the implementation to match resources for policies.

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

An optional string identifying the fully qualified class name of the implementation to save indexes for policies.

searchIndex

An optional string identifying the fully qualified class name of the implementation to index policies.

subjects

Array of subject type identifier strings defining subject types allowed for policies in this set.

For more information, refer to Policies over REST and Subject conditions.

createdBy(1)

A string indicating who created the policy set.

creationDate(1)

An integer containing the creation time in milliseconds since January 1, 1970.

lastModifiedBy(1)

A string indicating who last changed the policy set.

lastModifiedDate(1)

An integer containing the last modified time in milliseconds since January 1, 1970.

(1) Do not change the value of this field.

Access the endpoint

The REST calls to manage policy sets rely on an account with the appropriate privileges:

  1. Create a policy set administrator.

    In the AM admin UI, select Realm > Realm Name > Identities > + Add Identity and fill the required fields.

    Record the username and password.

  2. Create a group that grants the privileges to the policy set administrator.

    In the AM admin UI, select Realms > Realm Name > Identities > Groups > + Add Group to create a group with the following settings:

    Group ID

    am-policy-set-admins

    Members

    The policy set administrator whose username you recorded

    Privileges

    Policy Admin
    Application Modify Access
    Application Read Access

  3. Before making REST calls to manage policy sets, authenticate as the policy set administrator.

    For example:

    $ curl \
    --request POST \
    --header 'Content-Type: application/json' \
    --header 'X-OpenAM-Username: <policy-set-admin-username>' \
    --header 'X-OpenAM-Password: <policy-set-admin-password>' \
    --header 'Accept-API-Version: resource=2.0, protocol=1.0' \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {"tokenId":"<policy-set-admin-tokenId>","successUrl":"/enduser/?realm=/alpha","realm":"/alpha"}

    For additional details, refer to Session token after authentication.

    Use the <policy-set-admin-tokenId> as the value of the AM session cookie (default name: iPlanetDirectoryPro) to access the REST endpoints.

Query policy sets

To list all the policy sets defined for a realm, send an HTTP GET request to the /json/realms/root/realms/Realm Name/applications endpoint with _queryFilter=true as the query string parameter.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <policy-set-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/applications?_queryFilter=true'
{
  "result": [{
    "_id": "oauth2Scopes",
    "name": "oauth2Scopes",
    "description": "A policy set for policies based on OAuth 2.0 scopes",
    "attributeNames": [],
    "createdBy": "id=dsameuser,ou=user,ou=am-config",
    "conditions": ["Script", "AMIdentityMembership", "IPv6", "SimpleTime", "IPv4", "LEAuthLevel", "LDAPFilter", "AuthScheme", "Session", "AND", "AuthenticateToRealm", "ResourceEnvIP", "SessionProperty", "OAuth2Scope", "OR", "Transaction", "NOT", "AuthLevel", "AuthenticateToService"],
    "lastModifiedBy": "id=dsameuser,ou=user,ou=am-config",
    "creationDate": 1578580064992,
    "lastModifiedDate": 1595479030629,
    "subjects": ["AuthenticatedUsers", "NOT", "Identity", "OR", "AND", "NONE", "JwtClaim"],
    "saveIndex": null,
    "searchIndex": null,
    "entitlementCombiner": "DenyOverride",
    "resourceComparator": null,
    "editable": true,
    "applicationType": "iPlanetAMWebAgentService",
    "actions": {
      "GRANT": true
    },
    "resources": ["*://*:*/*", "*://*:*/*?*", "*"],
    "realm": "/alpha"
  }],
  "resultCount": 1,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

Adapt the query string parameters to refine the results.

Field Supported _queryFilter operators

name

Equals (eq)

description

createdBy

lastModifiedBy

creationDate

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

lastModifiedDate

(1) Do not use regular expression patterns with eq.

Read a policy set

To read a specific policy set in a realm, send an HTTP GET request to the /json/realms/root/realms/Realm Name/applications/policy-set-name endpoint.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--header "iPlanetDirectoryPro: <policy-set-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/applications/oauth2Scopes'
{
  "_id": "oauth2Scopes",
  "_rev": "1595479030629",
  "name": "oauth2Scopes",
  "description": "A policy set for policies based on OAuth 2.0 scopes",
  "attributeNames": [],
  "createdBy": "id=dsameuser,ou=user,ou=am-config",
  "conditions": ["Script", "AMIdentityMembership", "IPv6", "SimpleTime", "IPv4", "LEAuthLevel", "LDAPFilter", "AuthScheme", "Session", "AND", "AuthenticateToRealm", "ResourceEnvIP", "SessionProperty", "OAuth2Scope", "OR", "Transaction", "NOT", "AuthLevel", "AuthenticateToService"],
  "lastModifiedBy": "id=dsameuser,ou=user,ou=am-config",
  "creationDate": 1578580064992,
  "lastModifiedDate": 1595479030629,
  "subjects": ["AuthenticatedUsers", "NOT", "Identity", "OR", "AND", "NONE", "JwtClaim"],
  "saveIndex": null,
  "searchIndex": null,
  "entitlementCombiner": "DenyOverride",
  "resourceComparator": null,
  "editable": true,
  "applicationType": "iPlanetAMWebAgentService",
  "actions": {
    "GRANT": true
  },
  "resources": ["*://*:*/*", "*://*:*/*?*", "*"],
  "realm": "/alpha"
}

Create a policy set

To create a policy set in a realm, send an HTTP POST request to the /json/realms/root/realms/Realm Name/applications endpoint with _action=create as the query string parameter and a JSON representation of the policy set as the POST data.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: <policy-set-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
--data '{
  "name": "samplePolicySet",
  "description": "Sample policy set",
  "conditions": ["Script", "AMIdentityMembership", "IPv6", "IPv4", "SimpleTime", "LEAuthLevel", "LDAPFilter", "AuthScheme", "Session", "AND", "AuthenticateToRealm", "ResourceEnvIP", "Policy", "OAuth2Scope", "SessionProperty", "OR", "Transaction", "NOT", "AuthLevel", "AuthenticateToService"],
  "subjects": ["AuthenticatedUsers", "NOT", "Identity", "OR", "AND", "NONE", "Policy", "JwtClaim"],
  "entitlementCombiner": "DenyOverride",
  "attributeNames": [],
  "saveIndex": null,
  "searchIndex": null,
  "resourceComparator": null,
  "applicationType": "iPlanetAMWebAgentService",
  "actions": {
    "HEAD": true,
    "DELETE": true,
    "POST": true,
    "GET": true,
    "OPTIONS": true,
    "PUT": true,
    "PATCH": true
  },
  "resources": ["*://*:*/*", "*://*:*/*?*"],
  "realm": "/alpha"
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/applications/?_action=create'
{
  "_id": "samplePolicySet",
  "_rev": "1669134131264",
  "name": "samplePolicySet",
  "description": "Sample policy set",
  "attributeNames": [],
  "createdBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "conditions": ["Script", "AMIdentityMembership", "IPv6", "IPv4", "SimpleTime", "LEAuthLevel", "LDAPFilter", "AuthScheme", "Session", "AND", "AuthenticateToRealm", "ResourceEnvIP", "Policy", "OAuth2Scope", "SessionProperty", "OR", "Transaction", "NOT", "AuthLevel", "AuthenticateToService"],
  "lastModifiedBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "creationDate": 1669134131264,
  "lastModifiedDate": 1669134131264,
  "subjects": ["AuthenticatedUsers", "NOT", "Identity", "OR", "AND", "NONE", "Policy", "JwtClaim"],
  "saveIndex": null,
  "searchIndex": null,
  "entitlementCombiner": "DenyOverride",
  "resourceComparator": null,
  "editable": true,
  "applicationType": "iPlanetAMWebAgentService",
  "actions": {
    "HEAD": true,
    "DELETE": true,
    "POST": true,
    "GET": true,
    "OPTIONS": true,
    "PUT": true,
    "PATCH": true
  },
  "resources": ["*://*:*/*", "*://*:*/*?*"],
  "realm": "/alpha"
}

Update a policy set

To update a specific policy set in a realm, send an HTTP PUT request to the /json/realms/root/realms/Realm Name/applications/policy-set-name endpoint with a JSON representation of the updated policy set as the PUT data.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request PUT \
--header "Content-Type: application/json" \
--header "iPlanetDirectoryPro: <policy-set-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
--data '{
  "name": "samplePolicySet",
  "description": "Sample policy set",
  "conditions": ["Script", "AMIdentityMembership", "IPv6", "IPv4", "SimpleTime", "LEAuthLevel", "LDAPFilter", "AuthScheme", "Session", "AND", "AuthenticateToRealm", "ResourceEnvIP", "Policy", "OAuth2Scope", "SessionProperty", "OR", "Transaction", "NOT", "AuthLevel", "AuthenticateToService"],
  "subjects": ["AuthenticatedUsers", "NOT", "Identity", "OR", "AND", "NONE", "Policy", "JwtClaim"],
  "entitlementCombiner": "DenyOverride",
  "attributeNames": [],
  "saveIndex": null,
  "searchIndex": null,
  "resourceComparator": null,
  "applicationType": "iPlanetAMWebAgentService",
  "actions": {
    "HEAD": true,
    "DELETE": false,
    "POST": true,
    "GET": true,
    "OPTIONS": true,
    "PUT": false,
    "PATCH": false
  },
  "resources": ["*://*:*/*", "*://*:*/*?*"],
  "realm": "/alpha"
}' \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/applications/samplePolicySet'
{
  "_id": "samplePolicySet",
  "_rev": "1669134221194",
  "name": "samplePolicySet",
  "description": "Sample policy set",
  "attributeNames": [],
  "createdBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "conditions": ["Script", "AMIdentityMembership", "IPv6", "IPv4", "SimpleTime", "LEAuthLevel", "LDAPFilter", "AuthScheme", "Session", "AND", "AuthenticateToRealm", "ResourceEnvIP", "Policy", "OAuth2Scope", "SessionProperty", "OR", "Transaction", "NOT", "AuthLevel", "AuthenticateToService"],
  "lastModifiedBy": "id=1dff18dc-ac57-4388-8127-dff309f80002,ou=user,o=alpha,ou=services,ou=am-config",
  "creationDate": 1669134131264,
  "lastModifiedDate": 1669134221194,
  "subjects": ["AuthenticatedUsers", "NOT", "Identity", "OR", "AND", "NONE", "Policy", "JwtClaim"],
  "saveIndex": null,
  "searchIndex": null,
  "entitlementCombiner": "DenyOverride",
  "resourceComparator": null,
  "editable": true,
  "applicationType": "iPlanetAMWebAgentService",
  "actions": {
    "HEAD": true,
    "DELETE": false,
    "POST": true,
    "GET": true,
    "OPTIONS": true,
    "PATCH": false,
    "PUT": false
  },
  "resources": ["*://*:*/*", "*://*:*/*?*"],
  "realm": "/alpha"
}

Delete a policy set

To delete a policy set in a realm, send an HTTP DELETE request to the /json/realms/root/realms/Realm Name/applications/policy-set-name endpoint.

If you omit the realm path from the URL, AM uses the Top Level Realm.
$ curl \
--request DELETE \
--header "iPlanetDirectoryPro: <policy-set-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/applications/samplePolicySet'
{"_id":"samplePolicySet","_rev":"0"}

AM does not permit deletion of a policy set containing policies. If you attempt to delete the policy set, AM returns an HTTP 409 Conflict status code and a message like the one in the following example:

$ curl \
--request DELETE \
--header "iPlanetDirectoryPro: <policy-set-admin-tokenId>" \
--header "Accept-API-Version: resource=1.0" \
'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/applications/oauth2Scopes'
{
  "code": 409,
  "reason": "Conflict",
  "message": "Application cannot be altered because policies exist within the Application. Remove all policies from the Application before attempting to delete the Application."
}

Remove the policies from the set before you delete it.

Policy set application types over REST

Application types define how to compare resources and index policies. The default application type, iPlanetAMWebAgentService, represents web resources. The policy set for web and Java agents (also called iPlanetAMWebAgentService) is based on this default application type.

The applicationtypes REST endpoint lets you do the following:

Applications types are configured per server, not per realm. Therefore, the URI for the application types API does not include a realm component, and is simply /json/applicationtypes.

Application types are represented in JSON format, for example:

{
    "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"
}

An application type object includes the following information:

name

Name of the application type.

actions

Set of actions for that application type, each with a boolean value indicating whether the action is allowed.

resourceComparator

The 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".

Query application types

To list all application types, send an HTTP GET request 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…​" \
--header "Accept-API-Version: resource=1.0" \
"https://openam.example.com:8443/openam/json/applicationtypes?_queryFilter=true"
{
  "result": [
    {
      "_id": "umaApplicationType",
      "applicationClassName": "com.sun.identity.entitlement.Application",
      "saveIndex": "org.forgerock.openam.uma.UmaPolicySaveIndex",
      "searchIndex": "org.forgerock.openam.uma.UmaPolicySearchIndex",
      "resourceComparator": "org.forgerock.openam.uma.UmaPolicyResourceMatcher",
      "name": "umaApplicationType",
      "actions": {}
    },
    {
      "_id": "sunAMDelegationService",
      "applicationClassName": "com.sun.identity.entitlement.Application",
      "saveIndex": "com.sun.identity.entitlement.opensso.DelegationResourceNameIndexGenerator",
      "searchIndex": "com.sun.identity.entitlement.opensso.DelegationResourceNameSplitter",
      "resourceComparator": "com.sun.identity.entitlement.RegExResourceName",
      "name": "sunAMDelegationService",
      "actions": {
        "READ": true,
        "MODIFY": true,
        "DELEGATE": true
      }
    },
    {
      "_id": "iPlanetAMWebAgentService",
      "applicationClassName": "com.sun.identity.entitlement.Application",
      "saveIndex": "org.forgerock.openam.entitlement.indextree.TreeSaveIndex",
      "searchIndex": "org.forgerock.openam.entitlement.indextree.TreeSearchIndex",
      "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
      "name": "iPlanetAMWebAgentService",
      "actions": {
        "HEAD": true,
        "DELETE": true,
        "POST": true,
        "GET": true,
        "OPTIONS": true,
        "PUT": true,
        "PATCH": true
      }
    }
  ],
  "resultCount": 3,
  "pagedResultsCookie": null,
  "totalPagedResultsPolicy": "NONE",
  "totalPagedResults": -1,
  "remainingPagedResults": 0
}

Use additional query strings to narrow down the results. For details, refer to Query.

Read a specific application type

To read an specific application type, send an HTTP GET request to the /json/applicationtypes endpoint, specifying 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…​" \
--header "Accept-API-Version: resource=1.0" \
"https://openam.example.com:8443/openam/json/applicationtypes/iPlanetAMWebAgentService"
{
  "_id": "iPlanetAMWebAgentService",
  "_rev": "1664877005610",
  "applicationClassName": "com.sun.identity.entitlement.Application",
  "saveIndex": "org.forgerock.openam.entitlement.indextree.TreeSaveIndex",
  "searchIndex": "org.forgerock.openam.entitlement.indextree.TreeSearchIndex",
  "resourceComparator": "com.sun.identity.entitlement.URLResourceName",
  "name": "iPlanetAMWebAgentService",
  "actions": {
    "HEAD": true,
    "DELETE": true,
    "POST": true,
    "GET": true,
    "OPTIONS": true,
    "PUT": true,
    "PATCH": true
  }
}

Import and export policies

You can import and export policies to and from files.

You can use these files to back up policies, transfer policies between AM instances, or store policy configuration in a version control system such as Git or Subversion.

AM supports exporting policies in JSON and eXtensible Access Control Markup Language (XACML) Version 3.0 format.

Comparison of policy import/export formats
Feature Supported for JSON? Supported for XACML?

Can be imported/exported from within the AM admin UI?

No

Yes

Can be imported/exported on the command line, using the ssoadm command?

Yes

Yes

Exports policies?

Yes

Yes

Exports policy sets?

Yes

Partial(1)

Exports resource types?

Yes

Partial

Creates an exact copy of the original policy sets, resource types, and policies upon import?

Yes

Partial(2)

(1) Only the details of policy sets and resource types that are actually used within a policy are exported to the XACML format. The full definition is not exported.

(2) Policy sets and resource types will be generated from the details in the XML, but may not match the definitions of the originals. For example, the names are auto-generated.

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

Importing and exporting JSON:

Importing and exporting XACML:

Export policies in JSON format (ssoadm)

  1. Use the ssoadm policy-export command:

    $ ssoadm \
      policy-export \
      --realm "/" \
      --servername "https://openam.example.com:8443/openam" \
      --jsonfile "myPolicies.json" \
      --adminid uid=amAdmin,ou=People,dc=openam,dc=forgerock,dc=org \
      --password-file /tmp/pwd.txt
    {
      "RESOURCE_TYPE" : 1,
      "POLICY" : 1,
      "APPLICATION" : 1
    }

    If exporting from a subrealm, include the top level realm (/) in the --realm value. For example, --realm "/myRealm".

    For more information on the syntax of this command, see ssoadm policy-export.

Import policies in JSON format (ssoadm)

  1. Use the ssoadm policy-import command:

    $ ssoadm \
      policy-import \
      --realm "/myRealm" \
      --servername "https://openam.example.com:8443/openam" \
      --jsonfile "myPolicies.json" \
      --adminid uid=amAdmin,ou=People,dc=openam,dc=forgerock,dc=org \
      --password-file /tmp/pwd.txt
    {
      "POLICY" : {
        "CREATE_SUCCESS" : {
          "count" : 1
        }
      },
      "RESOURCE_TYPE" : {
        "CREATE_SUCCESS" : {
          "count" : 1
        }
      },
      "APPLICATION" : {
        "CREATE_SUCCESS" : {
          "count" : 1
        }
      }
    }

    If importing to a subrealm, include the top level realm (/) in the --realm value. For example, --realm "/myRealm".

    For more information on the syntax of this command, see ssoadm policy-import.

Export to XACML

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

Policy sets to XACML mappings
AM 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

When exporting AM policies to XACML 3.0 policy sets, AM maps its policies to XACML 3.0 policy elements.

Policies to XACML mappings
AM 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.

Export policies in XACML format (UI)

  1. In the AM admin UI, go to Realms > Realm Name > Authorization > Policy Sets, and click Export Policy Sets.

    All policy sets, and the policies within will be exported in XACML format.

Export policies in XACML format (REST)

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

https://openam.example.com:8443/openam/xacml/policies https://openam.example.com:8443/openam/xacml/realm/policies

Here, realm is the name of a specific realm.

You can filter your XACML exports using query search filters. See Export policies in XACML format with search filters (REST).

  1. Use the /xacml/policies endpoint to export the AM 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…​" \
    "https://openam.example.com:8443/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*?*">
      …​

Export policies in XACML format with search filters (REST)

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.

    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…​" \
      "https://openam.example.com:8443/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…​" \
      "https://openam.example.com:8443/openam/xacml/policies?filter=createdby=amadmin&filter=creationdate=135563832"

Export policies in XACML format (ssoadm)

  1. Use the ssoadm list-xacml command:

    $ ssoadm \
     list-xacml \
     --realm "/" \
     --adminid uid=amAdmin,ou=People,dc=openam,dc=forgerock,dc=org \
     --password-file /tmp/pwd.txt
    <?xml version="1.0" encoding="UTF-8"?>
    <PolicySet
    …​
    Policy definitions were returned under realm, /.

    For more information on the syntax of this command, see ssoadm list-xacml.

Import from XACML

To test an import, AM 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.

Import policies in XACML format (UI)

  1. In the AM admin UI, go to Realms > Realm Name > Authorization > Policy Sets, and click Import Policy Sets.

  2. Browse to the XACML format file, select it, and click Open.

    Any policy sets, and the policies within will be imported from the selected XACML format file.

    Policy sets and resource types will be generated from the details in the XACML format file, but may not match the definitions of the originals, for example the names are auto-generated.

Import policies in XACML format (REST)

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

https://openam.example.com:8443/openam/xacml/policies https://openam.example.com:8443/openam/xacml/realm/policies

Here, realm is the name of a specific realm.

  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 \
    "https://openam.example.com:8443/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 \
    "https://openam.example.com:8443/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 \"
    "https://openam.example.com:8443/openam/xacml/realm/policies"

Import policies in XACML format (ssoadm)

Use the ssoadm create-xacml command:

$ ssoadm \
 create-xacml \
 --realm "/" \
 --adminid uid=amAdmin,ou=People,dc=openam,dc=forgerock,dc=org \
 --password-file /tmp/pwd.txt \
 --xmlfile policy.xml
Policies were created under realm, /.

For more information on the syntax of this command, see ssoadm create-xacml.

Request authorization from AM

When you have configured AM to determine whether to grant or deny access based on your configured policies, you must configure policy enforcement points (PEPs) to use AM.

The Ping Identity Platform provides the following PEPs:

Web agents and Java agents

Add-on components installed on the web server or container that serves your applications. The web and Java agents are tightly integrated with AM and serve exclusively as PEPs.

For more information, refer to Policy enforcement in the ForgeRock web agents documentation, or to Policy enforcement in the ForgeRock Java agents documentation.

PingGateway

A high-performance reverse proxy server that can also function as a PEP.

For more information, refer to Policy enforcement in the PingGateway documentation.

The Ping Identity Platform PEPs intercept inbound client requests to access resources in your website or application. Based on internal rules, the PEPs can defer requests to AM for policy evaluation. Because they are tightly integrated with AM, you do not need additional code to request policy evaluation or to manage advices.

Use the Ping Identity Platform PEPs where possible. If your deployment has specific requirements that aren’t met by the Ping Identity Platform PEPs, you can write your own PEPs that make REST calls to AM to request policy evaluation.

Related information: Request policy decisions over REST

Request policy decisions over REST

You can request policy decisions from AM over REST. AM evaluates requests based on the context and the configured policies, and returns decisions that indicate what actions are allowed or denied, as well as any attributes or advices for the specified resources.

This section does not apply to OAuth 2.0 policies.

Request policy evaluation at the /json/realms/root/realms/Realm Name/policies endpoint.

When making a REST API call, specify the realm in the path component of the endpoint. You must specify the entire hierarchy of the realm, starting at the Top Level Realm. Prefix each realm in the hierarchy with the realms/ keyword. For example, /realms/root/realms/customers/realms/europe.

Before making a REST API call to manage a policy, you must have:

  • Authenticated successfully to AM 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 AM session token and its use in REST API calls, refer to Session token after authentication.

To request decisions for specific resources, refer to Request policy decisions for a specific resource.

To request decisions for a resource and all resources beneath it, refer to Request policy decisions for a tree of resources.

Request policy decisions for a specific resource

To request policy decisions for specific resources, send a POST request to the policies endpoint, with the evaluate action. For example:

/json/realms/root/realms/Realm Name/policies?_action=evaluate.

When making a REST API call, specify the realm in the path component of the endpoint. You must specify the entire hierarchy of the realm, starting at the Top Level Realm. Prefix each realm in the hierarchy with the realms/ keyword. For example, /realms/root/realms/customers/realms/europe.

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 input fields are as follows:

resources

(Required) 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

The name of the policy set. Defaults to "iPlanetAMWebAgentService", if not specified.

For more on policy sets, refer to Policy sets over REST.

subject

(Optional). Holds an object that represents the subject. If you do not specify the subject, AM uses the SSO token ID of the subject making the request.

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 Authenticate over REST.

You can use an OpenID Connect ID token if the client that the token has been issued for is authorized to use ID tokens as session tokens. For details, refer to Using ID Tokens as Session Tokens.

jwt

The value is a JWT string.

If you pass the subject details as a JWT, AM does not attempt to validate the JWT signature or the claims in the JWT. It is assumed that you have already validated the JWT before calling the authorization endpoint.

For AM-issued ID Tokens, you can, instead, pass the ID Token as the value of the ssoToken field (after adding your client to the Authorized SSO Clients list). In this case, AM will validate the token. For more information, refer to ID tokens as subjects in policy evaluation.

claims

The value is an object (map) of JWT claims to their values. Any string is permitted, but you must include the sub claim.

environment

(Optional). Holds a map of keys to lists of values.

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

The following example 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 "Accept-API-Version: resource=2.1" \
--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/realms/root/realms/alpha/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, AM includes these fields.

resource

The resource specified in the request.

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

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 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 about what AM requires to make an 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"
        ]
    }
}

Refer to 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.

Request policy decisions for a tree of resources

To request policy decisions for a resource, and all other resources in the subtree, send a POST request to the policies endpoint, with the evaluateTree action. For example:

/json/realms/root/realms/Realm Name/policies?_action=evaluateTree

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

(Required) 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

The name of the policy set. Defaults to "iPlanetAMWebAgentService" if not specified.

For more on policy sets, refer to Policy sets over REST.

subject

(Optional) 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 that correspond to any type in the request.

ssoToken

The SSO token ID string for the subject, returned on successful authentication, as described in Authenticate over REST.

jwt

The value is a JWT string.

If you pass the subject details as a JWT, AM does not attempt to validate the JWT signature or the claims in the JWT. It is assumed that you have already validated the JWT before calling the authorization endpoint.

For AM-issued ID Tokens, you can, instead, pass the ID Token as the value of the ssoToken field (after adding your client to the Authorized SSO Clients list). In this case, AM will validate the token. For more information, refer to Using ID Tokens as Subjects in Policy Decisions.

claims

An object (map) of JWT claims to their values. If you do not specify the subject, AM uses the SSO token ID of the subject making the request.

environment

(Optional) A map of keys to lists of values.

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

The following example 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. 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*" \
--header "Accept-API-Version: resource=1.0" \
--data '{
    "resource": "http://www.example.com/",
    "subject": { "ssoToken": "AQIC5…​zE4*" }
}' \
"https://openam.example.com:8443/openam/json/realms/root/realms/alpha/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"
            ]
        }
    }
]

AM 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, AM 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 AM needs, to make 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.

Policy decision advice

When AM 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.

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

"AuthLevel" and "LEAuthLevel" condition failures can result in an 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 an 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 an 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 an advice showing the name of the required authentication chain or tree. For example, failure against the following condition:

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

Leads to this advice:

{
    "AuthenticateToServiceConditionAdvice": [
        "MyAuthnChain"
    ]
}

A ResourceEnvIP condition failure can result in an advice that indicates corrective action to be taken. 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 an advice showing that access was denied because the user’s session was active longer than allowed by the condition.

If terminateSession is true and policy evaluation is requested, AM sends the session advice to the Java, Web, or PingGateway agent when the maxSessionTime elapses.

For example, failure against the following condition:

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

Leads to this advice:

{
    "SessionConditionAdvice": [
        "deny"
    ]
}

When AM receives the terminate advice, the user is redirected to the login page to reauthenticate.

If terminateSession is false and policy evaluation is requested, AM doesn’t send the session advice to the Java, Web, or PingGateway agent when the maxSessionTime elapses. Instead of being redirected to the login page, the user receives a 403 Forbidden response for the protected resource.

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

  • IPv4

  • IPv6

  • LDAPFilter

  • OAuth2Scope

  • SessionProperty

  • SimpleTime

When policy evaluation is requested for a nonexistent or inactive subject, AM returns an HTTP 200 code and a response that contains no actions or advice. Access to the resource is denied.

Transactional authorization

Transactional authorization requires a user to authorize every access to a resource. It’s part of an AM policy that grants single-use or one-shot access.

For example, a user might approve a financial transaction with a one-time password (OTP) sent to their device, or respond to a push notification to confirm that they have indeed signed on from an unexpected location.

Performing the additional action successfully grants access to the protected resource but only once. Additional attempts to access the resource require the user to perform the configured actions again.

Transactional authorization is implemented as an environment condition type in an authorization policy, and affects the authorization decision.

Transactional authorization isn’t designed to work with account lockout and doesn’t increment lockout counters. As such, don’t use transactional authorization with authentication mechanisms that are susceptible to brute force attacks, such as simple username/password authentication, or OTP authentication. Configure transactional authorization if you’re using a strong authentication mechanism, such as MFA: Push authentication, that isn’t susceptible to brute force attacks. If you do use transactional authorization with a weaker authentication mechanism like OTP authentication, you must manage rate-limiting in some other way.

Understand transactional authorization

The following diagram describes the sequence of events that occur when accessing a resource that is protected by a REST application, and an AM policy containing a transactional environment condition:

Accessing resources with transactional authorization
Figure 3. Accessing resources with transactional authorization

The sequence of events for a transaction authorization is as follows:

  1. An authenticated user attempts to access a resource that’s protected by an AM server.

  2. The REST application, a resource server, contacts AM to evaluate the policies that apply.

  3. Because the policy contains a transaction environment condition, AM creates a transaction token in the Core Token Service (CTS) store.

    The initial transaction token state is set to CREATED.

    The transaction token contains information about the policy evaluation, including the:

    • Realm

    • Resource

    • Subject

    • Audit tracking ID

    • Authentication method

    To protect against tampering, AM verifies that these details do not change and match those in the incoming requests for the duration of the transaction.

    The transaction token has a time-to-live (default 180 seconds) defined in the Transaction Authentication Service. If the transaction is not completed within this time, the token is deleted, and the flow must be restarted. Alter the default time-to-live if the transaction includes authentication actions that take more time to complete; for example, using HOTP authentication for an OTP over email.

    The time-to-live can be configured globally, or per-realm. For details, refer to Transaction Authentication Service.

  4. In the JSON response to the policy evaluation request, AM returns the transaction ID—​the unique ID of the newly created transaction token—​in the TransactionConditionAdvice array of the advices object; for example:

    {
        "resource": "https://bank.example.com:443/withdraw?amount=100.00",
        "actions": {},
        "attributes": {},
        "advices": {
            "TransactionConditionAdvice": [
                "7b8bfd4c-60fe-4271-928d-d09b94496f84"
            ]
        },
        "ttl": 0
    }
  5. Because the response to the evaluation request does not grant any actions but contains advices, the REST application extracts the transaction ID and returns it to the authentication service to start the authentication.

    The transaction ID is included in the TransactionConditionAdvice attribute value pair in the composite advice query parameters sent as part of the request for actions.

  6. AM extracts the transaction ID from the composite advice, verifies the corresponding transaction token, and changes the state to IN_PROGRESS.

    If the transaction ID is not in the expected state or does not exist AM returns a 401 Unauthorized error; for example:

    {
        "code": 401,
        "reason": "Unauthorized",
        "message": "Unable to read transaction.",
        "detail": {
            "errorCode": "128"
        }
    }
  7. AM responds with the callbacks necessary to satisfy any environment conditions.

    The advices returned by transaction environment conditions have the lowest precedence when compared to the other condition advices. End users must respond to non-transactional condition advices before they respond to the transactional condition advices.

  8. The REST application renders the callbacks and presents them to the user.

  9. The user completes the required actions.

    For example, the user completes the tree specified in the policy by responding to a push notification on their registered mobile device to confirm a transaction.

    If the user does not complete the required actions, AM returns an HTTP 200 message and the user is redirected to the protected resource. Policy evaluation fails because the transactional authorization process failed.

    To return an HTTP 401 message and redirect the user to the failure URL, configure the org.forgerock.openam.auth.transactionauth.returnErrorOnAuthFailure advanced server property.

  10. The REST application completes the callbacks and returns the result to AM.

  11. AM verifies the transaction token and changes the state to COMPLETED.

  12. With the transaction now complete, AM returns the original token.

    Authentication performed as part of an authorization flow does not behave the same as a standard authentication. The differences are as follows:

    • The user’s original session is not upgraded or altered in any way.

    • Failing the authentication during the authorization flow does not increment account lockout counters.

  13. The REST application requests the policy decision again, including the ID of the completed transaction as a value in the TxId array of the environment object:

    {
        "resources" : ["https://bank.example.com:443/withdraw?amount=100.00"],
        "application" : "iPlanetAMWebAgentService",
        "subject" : {
            "ssoToken" : "AQIC5w....*AJTMQAA*"
        },
        "environment": {
            "TxId": ["7b8bfd4c-60fe-4271-928d-d09b94496f84"]
        }
    }
  14. AM verifies the transaction was authorized and that the transaction token is in the COMPLETED state.

  15. If the transaction was completed successfully, the authorization continues.

    The transaction token is marked for deletion so that it cannot be used to grant more than a single access.

  16. Because the authentication required to complete the transaction was successful, AM returns the result of the policy reevaluation.

    For example, the following response grants the POST and GET actions to the resource https://bank.example.com:443/withdraw?amount=100.00:

    {
        "resource": "https://bank.example.com:443/withdraw?amount=100.00",
        "actions": {
            "POST": true,
            "GET": true
        },
        "attributes": {},
        "advices": {},
        "ttl": 0
    }

    Successful transactional authorization responses set the time-to-live (ttl) value to zero to ensure that the policy decision is not cached and cannot be used more than once.

    ForgeRock agents prior to version 5 do not support a time-to-live value of zero and cannot be used for transactional authorization.

  17. The user is able to access the protected resource once.

    Additional attempts to access a resource protected by a policy containing a transactional environment condition require a new transaction to be completed.

Configure transactional authorization

To use transactional authorization, you must coordinate the configuration of the following elements:

  • An appropriate authentication tree for the transaction.

  • The AM policy or policies that use the tree.

  • Support for transactional authorization in your applications.

The authentication tree

The tree communicates to the user what they are authorizing when they approve the transaction, and gives them the means to approve (or reject) the operation.

For example, if the transaction involves a withdrawal from the user’s bank account, you could configure a multi-factor authentication tree that displays "Confirm $100 withdrawal from Online Bank?" with Yes and No options for a push notification to a registered device, or sends a one-time password to a registered device with a similar message.

Configure the tree in the same realm as the policy.

The policy

A transactional authorization policy specifies the conditions that trigger the required authorization. It also specifies a tree the end user must complete to authorize the transaction. In other respects, it is a normal AM authorization policy.

You configure the policy in the AM admin UI. For example, this completed policy applies to the /withdraw endpoint. Its transactional authorization environment condition specifies that the user must complete the AuthorizeTransaction tree to authorize access to the endpoint:

Policy to approve withdrawls

To add the environment condition, set:

Type

Transaction

Authentication Strategy

Authenticate to Tree

Strategy Specifier

The name of the tree

Your application

A quick way to protect your application is to use Ping Identity software. PingGateway, SDKs, and agents all support transactional authorization.

  • When using PingGateway to protect your application, configure it for use with AM.

    Refer to the installation pages in the PingGateway documentation.

    Also refer to the PingGateway documentation for policy enforcement. PingGateway as a PEP transparently manages redirection when AM policy requires transactional authorization.

  • When using a ForgeRock SDK, refer to Perform transactional authorization in the SDKs docs.

  • When using a ForgeRock agent to protect your application, refer to the Java agent page on policy enforcement or the web agent page on policy enforcement.

Demonstrate transactional authorization

After configuring the tree, the policy, and your application, access the protected resource.

The example described here involves a bank withdrawal operation. The following steps put the end user interaction with AM in context:

  1. Barbara Jensen browses her online bank at https://bank.example.com and signs on to access her account:

    Signing on at the online bank
  2. Barbara prepares to withdraw $100 from her account using the online bank application.

    The application as PEP continues to contact AM for policy decisions as Barbara browses through the application.

  3. Barbara confirms her intention to complete the withdrawal, triggering the application to access the /withdraw endpoint.

    When requesting a policy decision for this endpoint, the application gets advices indicating transactional authorization.

    It redirects Barbara to the tree required for this transaction according to the policy. The important step of the tree is the decision to authorize the withdrawal:

    Confirming a withdrawal
  4. Barbara receives the money and a receipt page after the application finishes processing the transaction with AM.

The steps for transactional authorization are identical to those for session upgrade.

Transactional authorization over REST

  1. Obtain a session token from AM for user demo with password Ch4ng31t:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. Request a policy evaluation with the tokenId from the previous step as the subject, and a resource URL that is protected by the policy you edited.

    The authenticated user must have the privileges required to access the policy endpoints.

    For additional details, refer to Authenticate over REST.

    $ curl \
    --cookie "iPlanetDirectoryPro=AQIC5wM2L…​zEAAA.." \
    --request POST \
    --header "Content-Type: application/json" \
    --header "Accept-API-Version: resource=2.0" \
    --data '{
        "resources" : ["https://bank.example.com:443/withdraw?amount=100.00"],
        "subject" : {
            "ssoToken" : "AQIC5w…​NTcy"
        },
        "application": "iPlanetAMWebAgentService"
    }' \
    "https://openam.example.com:8443/openam/json/realms/root/policies/?_action=evaluate"
    {
       "resource": "https://bank.example.com:443/withdraw?amount=100.00",
       "actions": {},
       "attributes": {},
       "advices": {
           "TransactionConditionAdvice": [
               "9dae2c80-fe7a-4a36-b57b-4fb1271b0687"
           ]
       },
       "ttl": 0
    }

    The application is the name of your policy set, which defaults to iPlanetAMWebAgentService.

    AM returns an empty actions element, and a transaction ID in the TransactionConditionAdvice property, because a transactional authorization is required to access the resource.

  3. Initiate authentication, including the transaction ID in the composite advice.

    The policy enforcement point must return the transaction ID in a composite advice query parameter, wrapped in URL-encoded XML. The XML format is as follows:

    <Advices>
        <AttributeValuePair>
            <Attribute name="TransactionConditionAdvice"/>
            <Value>Transaction Id</Value>
        </AttributeValuePair>
    </Advices>

    Use the SSO token of the demo user for this request.

    The following command URL-encodes the XML values. The -G parameter appends them as query string parameters to the URL:

    $ curl -G \
    --cookie "iPlanetDirectoryPro=AQIC5w…​NTcy*" \
    --request POST \
    --header "Content-Type: application/json" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    --data-urlencode 'authIndexType=composite_advice' \
    --data-urlencode 'authIndexValue=<Advices>
        <AttributeValuePair>
            <Attribute name="TransactionConditionAdvice"/>
            <Value>9dae2c80-fe7a-4a36-b57b-4fb1271b0687</Value>
        </AttributeValuePair>
    </Advices>' \
    'https://openam.example.com:8443/openam/json/realms/root/authenticate'
    Sample response
    {
      "authId": "eyJ0eXAiOi…​WLxJ-1d6ovYKHQ",
      "template": "",
      "stage": "AuthenticatorPush3",
      "header": "Authenticator Push",
      "callbacks": [
        {
          "type": "PollingWaitCallback",
          "output": [
            {
              "name": "waitTime",
              "value": "10000"
            }
          ]
        },
        {
          "type": "ConfirmationCallback",
          "output": [
            {
              "name": "prompt",
              "value": ""
            },
            {
              "name": "messageType",
              "value": 0
            },
            {
              "name": "options",
              "value": [
                "Use Emergency Code"
              ]
            },
            {
              "name": "optionType",
              "value": -1
            },
            {
              "name": "defaultOption",
              "value": 0
            }
          ],
          "input": [
            {
              "name": "IDToken2",
              "value": 100
            }
          ]
        }
      ]
    }

    The mobile device registered to the demo user receives a push notification message to authorize in the ForgeRock Authenticator app.

  4. Ensure that the time specified in the waitTime property in the callbacks has passed, in this case at least 10 seconds, and then complete and return the requested callbacks.

    Also return the value of the authId property and the URL-encoded transaction ID.

    Use the SSO token of the demo user for this request.

    In this example, the required XML parameters have been URL-encoded and added to the URL.

    The curl command is not able to use the --data-urlencode option for query-string parameters when sending a JSON payload.

    $ curl \
    --cookie "iPlanetDirectoryPro=AQIC5w…​NTcy*" \
    --request POST \
    --header "Content-Type: application/json" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    --data '{
        "authId":"eyJ0eXAiOi…​WLxJ-1d6ovYKHQ",
        "template":"",
        "stage":"AuthenticatorPush3",
        "header":"Authenticator Push",
        "callbacks":[
            {
                "type":"PollingWaitCallback",
                "output":[
                    {
                        "name":"waitTime",
                        "value":"10000"
                    }
                ]
            },
            {
                "type":"ConfirmationCallback",
                "output":[
                    {
                        "name":"prompt",
                        "value":""
                    },
                    {
                        "name":"messageType",
                        "value":0
                    },
                    {
                        "name":"options",
                        "value":[
                            "Use Emergency Code"
                        ]
                    },
                    {
                        "name":"optionType",
                        "value":-1
                    },
                    {
                        "name":"defaultOption",
                        "value":0
                    }
                ],
                "input":[
                    {
                        "name":"IDToken2",
                        "value":100
                    }
                ]
            }
        ]
    }' \
    "https://openam.example.com:8443/openam/json/realms/root/authenticate\
    ?authIndexType=composite_advice\
    &authIndexValue=%3CAdvices%3E%0A\
    %3CAttributeValuePair%3E%0A%3CAttribute%20name%3D\
    %22TransactionConditionAdvice%22%2F%3E%0A\
    %3CValue%3E9dae2c80-fe7a-4a36-b57b-4fb1271b0687\
    %3C%2FValue%3E%0A%3C%2FAttributeValuePair\
    %3E%0A%3C%2FAdvices%3E"
    {
        "tokenId":"AQIC5w…​NTcy*",
        "successUrl":"https://bank.example.com:443/withdraw?amount=100.00",
        "realm":"/"
    }

    If the callbacks are correctly completed and the push was approved in the ForgeRock Authenticator application, AM returns the original tokenId value.

    If the push notification has not yet been responded to in the ForgeRock Authenticator application, AM returns the required callbacks again, as in the previous step. Wait until the amount of time specified in the waitTime element has passed and retry the request until the tokenId returns.

  5. Reevaluate the policy, including the transaction ID as the value of a TxId property in the environment element:

    $ curl \
    --cookie "iPlanetDirectoryPro=AQIC5wM2L…​zEAAA.." \
    --request POST \
    --header "Content-Type: application/json" \
    --header "Accept-API-Version: resource=1.0" \
    --data '{
        "resources" : ["http://www.example.com:8000/index.html"],
        "subject" : {
            "ssoToken" : "AQIC5w…​NTcy"
        },
        "environment": {
            "TxId": ["9dae2c80-fe7a-4a36-b57b-4fb1271b0687"]
        }
    }' \
    "https://openam.example.com:8443/openam/json/policies/?_action=evaluate"
    {
        "resource":"https://bank.example.com:443/withdraw?amount=100.00",
        "actions":{
            "POST":true,
            "GET":true
        },
        "attributes":{
    
        },
        "advices":{
    
        },
        "ttl":0
    }

    Because the authentication required by the transaction succeeded, the second policy evaluation returns the POST and GET actions as defined in the policy.

    Notice that the time-to-live (ttl) value of the policy evaluation result is set to 0. This means the policy must not be cached, as the policy grants access to the resource only once. The policy enforcement point must manage this.

    Performing the policy evaluation with the same subject and resource starts a new transactional authorization flow, requiring a repeat of all the steps to access the protected resource each time.

Dynamic OAuth 2.0 authorization

AM can grant OAuth 2.0 scopes statically or dynamically:

Static scopes (default)

OAuth 2.0 client configurations specify the allowed and, optionally, default scopes.

When the client requests allowed scopes and the resource owner consents to grant the client access, AM issues the token with the scopes requested.

When different users use the same client that requests scopes A and B, the access token always includes scopes A and B.

Dynamic scopes

OAuth 2.0 client configurations specify the allowed and, optionally, default scopes.

You configure AM policies for OAuth 2.0 scope decisions. You configure the client or the OAuth 2.0 provider service to use the AM policy engine for scope decisions.

AM checks each scope against the applicable OAuth 2.0 scope policies. AM grants or denies access to scopes dynamically at runtime.

When different users use the same client that requests scopes A and B, the access token scopes can differ.

Example use case

A company supports custom OAuth 2.0 clients for internal applications. The use of the internal applications is bound by the terms and conditions in the contracts of those who work for the company. The terms and conditions grant the internal applications access to profile information the company maintains. It would be redundant to prompt employees and contractors for consent to access their profile information.

The AM administrator creates policies to grant the profile scope for all internal client tokens.

How it works

How policies determine whether to grant or deny an OAuth 2.0 scope
Figure 4. Policies for dynamic scopes

AM processes consent based on the policy decision:

  • If a policy grants access to a scope (GRANT=true), consent is automatic.

    AM does not prompt the user to grant access.

  • If a policy denies access to a scope (GRANT=false), AM omits the scope from any resulting token.

    AM does not prompt the user to grant access.

  • If no policy grants or denies access, then the result depends on the flow.

    When the flow is interactive as in authorization or device code flows, AM prompts the user to grant access or uses the saved consent state if available.

    If the flow is not interactive as in resource owner password or client credentials flows, AM omits the scope from any resulting token.

    For details about which flows are interactive, refer to the examples in OAuth 2.0 grant flows and OpenID Connect grant flows.

The default scopes behavior does not change for dynamic authorization. AM only evaluates default scopes from the OAuth 2.0 client profile when the client does not request a scope. AM follows the same rules to deduce consent for both default and requested scopes.

When issuing refresh tokens, AM issues the same scopes as for the access token, unless a policy explicitly denies one of the scopes.

Validate OAuth 2.0 scope policies

Writing policies for OAuth 2.0 may not be straightforward if your environment requires complex conditions. The easiest way to validate OAuth 2.0 policies is to configure a client to use the policies and request some tokens.

Prepare a demonstration

Start by preparing the demonstration:

OAuth 2.0 scope policy

The sample scope policy denies access to the email scope.

  1. In the AM admin UI, go to Realms > alpha > Authorization > Policy Sets and select Default OAuth2 Scopes Policy Set to edit the policy set.

    This is the oauth2Scopes policy.

  2. Click + Add a Policy, use the following settings, and create the policy:

    Name

    Dynamic OAuth 2.0 Scopes

    Resource Type

    OAuth2 Scope

    Resources

    Select * as the pattern and add email as the scope.

  3. Click the Actions tab, set GRANT to Deny, and save your changes.

  4. Click the Subjects tab, set the subject type to Authenticated Users, and save your changes.

The resulting policy reflects your work:

OAuth 2.0 policy denying the email scope for all authenticated users
Figure 5. OAuth 2.0 scopes policy

OAuth 2.0 client

The OAuth 2.0 client profile in this example overrides the AM OAuth 2.0 provider settings. This lets you test the scope policy without affecting other clients.

  1. Create a confidential OAuth 2.0 client account.

    In the AM admin UI, select Realm > Realm Name > Applications > OAuth 2.0 > Clients > + Add Client, and create a new confidential client with the following settings:

    Client ID

    myClient

    Client Secret

    forgerock

    Redirection URIs

    https://www.example.com:443/callback

    Scopes

    openid
    profile
    email

  2. Add the following settings in the client profile and save your work:

    Core tab > Name

    Dynamic scopes client

    Advanced tab > Grant Types

    Authorization Code
    Client Credentials
    Implicit
    Refresh Token
    Resource Owner Password Credentials

  3. Override OAuth 2.0 provider settings for this client.

    Switch to the OAuth2 Provider Overrides tab, update the following settings and save your work:

    Enable OAuth2 Provider Overrides

    Enabled

    Use Policy Engine for Scope decisions

    Enabled

    Scopes Policy Set

    oauth2Scopes

Resource owner

Create the OAuth 2.0 resource owner account:

  1. In the AM admin UI, select Identities > + Add Identity and fill the required fields.

  2. Record the username and password.

Test the demonstration

Test the feature with non-interactive and interactive flows.

Non-interactive

This test uses the resource owner password credentials flow:

  • The OAuth 2.0 client credentials are myClient:forgerock.

  • The resource owner credentials are the username and password you recorded; here, test:Secret12!.

  • The requested scopes are openid and email.

$ curl \
--request POST \
--user 'myClient:forgerock' \
--data 'scope=openid email' \
--data 'grant_type=password' \
--data 'username=test' \
--data 'password=Secret12!' \
'https://openam.example.com:8443/openam/access_token'
{
  "access_token": "…​",
  "refresh_token": "…​",
  "scope": "openid",
  "id_token": "…​",
  "token_type": "Bearer",
  "expires_in": 3599
}

Notice the access token has "scope": "openid". AM removed email from the scopes.

Interactive

This test uses the implicit flow. It stops after demonstrating the user consent phase of the process.

  1. Update the client configuration to require resource owner consent.

    In the AM admin UI, go to Realm > Realm Name > Applications > OAuth 2.0 > Clients > myClient, switch to the Advanced tab.

    Clear Implied consent and save your change.

  2. In a web browser, go to the /authorize endpoint to initiate the implicit flow.

    https://openam.example.com:8443/openam/authorize?scope=openid+profile+email&response_type=id_token&client_id=myClient&nonce=123&state=456&redirect_uri=https://www.example.com:443/callback
  3. Sign in with the resource owner’s credentials.

  4. Observe the prompt for consent that does not include the email scope:

    AM prompts for consent to access the profile scope.
    Figure 6. Consent for the profile scope

OAuth 2.0 scopes policy script API

To customize OAuth 2.0 scope decisions, configure the oauth2Scopes policy with an environment script condition that references an OAuth 2.0 policy condition script.

The following JavaScript writes the ID of the OAuth 2.0 client to the debug log and then authorizes the request:

logger.message("Client ID: " + environment.get("clientId"));
authorized=true;

OAuth 2.0 policy condition scripts can access the bindings available to the policy condition script API, except for the environment object. Instead of an IP property, this object returns the ID for the client making the authorization request.

For example, the following shows an environment map with a single entry:

"environment": {
    "clientId": [
        "MyOAuth2Client"
    ]
}

Customize policy evaluation with a plug-in

AM policies let you restrict access to resources based both on identity and group membership, and also on a range of conditions including session age, authentication chain or module used, authentication level, realm, session properties, IP address and DNS name, user profile content, resource environment, date, day, time of day, and time zone. Yet, some deployments require further distinctions for policy evaluation. This section explains how to customize policy evaluation for deployments with particular requirements not met by built-in AM functionality.

This page shows how to build and use a custom policy plugin that implements a custom subject condition, a custom environment condition, and a custom resource attribute.

Sample plugin

The AM policy framework lets you build plugins that extend subject conditions, environment conditions, and resource attributes.

Learn about downloading and building PingAM sample source code in the following Knowledge Base article: How do I access and build the sample code provided for PingAM?.

Get a local clone so that you can try the sample on your system. You will find the relevant files under the /path/to/openam-samples-external/policy-evaluation-plugin directory.

Files in the sample
pom.xml

Apache Maven project file for the module

This file specifies how to build the sample policy evaluation plugin, and also specifies its dependencies on AM components.

src/main/java/org/forgerock/openam/examples/SampleAttributeType.java

Extends the com.sun.identity.entitlement.ResourceAttribute interface, and shows an implementation of a resource attribute provider to send an attribute with the response.

src/main/java/org/forgerock/openam/examples/SampleConditionType.java

Extends the com.sun.identity.entitlement.EntitlementCondition interface, and shows an implementation of a condition that is the length of the user name.

A condition influences whether the policy applies for a given access request. If the condition is fulfilled, then AM includes the policy in the set of policies to evaluate in order to respond to a policy decision request.

src/main/java/org/forgerock/openam/examples/SampleSubjectType.java

Extends the com.sun.identity.entitlement.EntitlementSubject interface, and shows an implementation that defines a user to whom the policy applies.

A subject, like a condition, influences whether the policy applies. If the subject matches in the context of a given access request, then the policy applies.

src/main/java/org/forgerock/openam/examples/SampleEntitlementModule.java

These files serve to register the plugin with AM.

The Java class, SampleEntitlementModule, implements the org.forgerock.openam.entitlement.EntitlementModule interface. In the sample, this class registers SampleAttribute, SampleCondition, and SampleSubject.

The services file, org.forgerock.openam.entitlement.EntitlementModule , holds the fully qualified class name of the EntitlementModule that registers the custom implementations. In this case, org.forgerock.openam.entitlement.EntitlementModule.

For an explanation of service loading, see the ServiceLoader API specification.

Build the sample plugin

  1. If you haven’t already done so, download and build the samples.

    Learn about downloading and building PingAM sample source code in the following Knowledge Base article: How do I access and build the sample code provided for PingAM?.

  2. When the build is complete, copy the policy-evaluation-plugin-7.5.jar file to the WEB-INF/lib directory where you deployed AM:

    $ cp target/*.jar /path/to/tomcat/webapps/openam/WEB-INF/lib/
  3. Update the user UI to include the custom subject and environment conditions.

    For details, refer to UI customization:

    • Locate the line that contains the following text:

      "subjectTypes": {
    • Insert the following text after the line you located in the previous step:

      "SampleSubject": {
          "title": "Sample Subject",
          "props": {
              "name": "Name"
          }
      },
    • Locate the line that contains the following text:

      "conditionTypes": {
    • Insert the following text after the line you located in the previous step:

      "SampleCondition": {
          "title": "Sample Condition",
          "props": {
              "nameLength": "Minimum username length"
          }
      },
  4. If your UI supports multiple locales, change the translation.json files for those locales, as needed.

  5. Restart AM or the container in which it runs.

Add a custom policy to an existing policy set

To use your custom policy in an existing policy set, you must update the policy set.

You can’t update a policy set that already has policies configured. If policies are configured for a policy set, you must first delete the policies, then update the policy set.

Update the iPlanetAMWebAgentService policy set in the top level realm of a fresh installation.

  1. Authenticate to AM as the amAdmin user:

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: amadmin" \
    --header "X-OpenAM-Password: password" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM2…​",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  2. Update the iPlanetAMWebAgentService policy set by adding the SampleSubject subject condition and the SampleCondition environment condition:

    $ curl \
    --request PUT \
    --header "iPlanetDirectoryPro: AQIC5wM2…​" \
    --header "Content-Type: application/json" \
    --header "Accept-API-Version: resource=1.0" \
    --data '{
    "name": "iPlanetAMWebAgentService",
    "conditions": [
        "LEAuthLevel",
        "Script",
        "AuthenticateToService",
        "SimpleTime",
        "AMIdentityMembership",
        "OR",
        "IPv6",
        "IPv4",
        "SessionProperty",
        "AuthScheme",
        "AuthLevel",
        "NOT",
        "AuthenticateToRealm",
        "AND",
        "ResourceEnvIP",
        "LDAPFilter",
        "OAuth2Scope",
        "Session",
        "SampleCondition"
    ],
    "subjects": [
        "NOT",
        "OR",
        "JwtClaim",
        "AuthenticatedUsers",
        "AND",
        "Identity",
        "NONE",
        "SampleSubject"
    ],
    "applicationType": "iPlanetAMWebAgentService",
    "entitlementCombiner": "DenyOverride"
    }' "https://openam.example.com:8443/openam/json/realms/root/realms/alpha/applications/iPlanetAMWebAgentService"

Try the sample subject and environment conditions

In the AM admin UI, add a policy to the iPlanetAMWebAgentService policy set in the top level realm that allows HTTP GET access for URLs based on the template http://www.example.com:80/*, and uses the custom subject and environment conditions.

  1. Create the policy with the following properties:

    Sample Policy Properties
    Property Value

    Name

    Sample Policy

    Resource Type

    URL

    Resources

    Use the *://*:*/* resource template to specify the resource http://www.example.com:80/*.

    Actions

    Allow GET

    Subject Conditions

    Add a subject condition of type Sample Subject and a name of demo so that the demo user is the only user who can access the resource.

    Environment Conditions

    Add an environment condition of type Sample Condition and a minimum username length of 4 so that only users with a username length of 4 characters or greater can access the resource.

  2. With the policy in place, authenticate both as a user who can request policy decisions and also as a user trying to access a resource.

    Both of these calls return tokenId values for use in the policy decision request.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: amadmin" \
    --header "X-OpenAM-Password: password" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM2…​",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "X-OpenAM-Username: demo" \
    --header "X-OpenAM-Password: Ch4ng31t" \
    --header "Accept-API-Version: resource=2.0, protocol=1.0" \
    'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
    {
        "tokenId":"AQIC5wM…​TU3OQ*",
        "successUrl":"/openam/console",
        "realm":"/alpha"
    }
  3. Use the administrator tokenId as the header of the policy decision request, and the user tokenId as the subject ssoToken value.

    $ curl \
    --request POST \
    --header "Content-Type: application/json" \
    --header "Accept-API-Version: resource=2.1" \
    --header "iPlanetDirectoryPro: AQIC5wM2LY4Sfcw…​" \
    --data '{
        "subject":{
            "ssoToken":"AQIC5wM2LY4Sfcy…​"
        },
        "resources":[
            "http://www.example.com:80/index.html"
        ],
        "application":"iPlanetAMWebAgentService"
    }' \
    "https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_action=evaluate"
    {
       "resource": "http://www.example.com:80/index.html",
       "actions": {
           "GET": true
       },
       "attributes": {},
       "advices": {}
    }

    Notice that the actions returned from the policy evaluation call are set in accordance with the policy.

Try the sample resource attributes

The sample custom policy plugin can have AM return an attribute with the policy decision. In order to make this work, list the resource type for the URL resource type to obtain its UUID, and then update your policy to return a test attribute:

$ curl \
--request GET \
--header "iPlanetDirectoryPro: AQIC5wM2…​" \
--header "Accept-API-Version: resource=1.0" \
"https://openam.example.com:8443/openam/json/realms/root/resourcetypes?_queryFilter=name%20eq%20%22URL%22"
{
    "result":[
        {
            "uuid":"URL-resource-type-UUID",
            "name":"URL",
            "description":"The built-in URL Resource Type available policies.",
            "patterns":["://:*/","://:/?"],
            …​
        }
    ],
    "resultCount":1,
    "pagedResultsCookie":null,
    "totalPagedResultsPolicy":"NONE",
    "totalPagedResults":-1,f
    "remainingPagedResults":0
}

When you now request the same policy decision as before, AM returns the test attribute that you configured in the policy.

$ curl \
--request POST \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=2.1" \
--header "iPlanetDirectoryPro: AQIC5wM2LY4Sfcw…​" \
--data '{
    "subject":{
        "ssoToken":"AQIC5wM2LY4Sfcy…​"
    },
    "resources":[
        "http://www.example.com:80/index.html"
    ],
    "application":"iPlanetAMWebAgentService"
}' \
"https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_action=evaluate"
{
    "resource": "http://www.example.com/profile",
    "actions": {
        "GET": true
    },
    "attributes": {
    "test": [
        "sample"
     ]
},
"advices": {}
}

Extend the ssoadm classpath

After customizing your AM deployment to use policy evaluation plugins, inform ssoadm users to add the jar file containing the plugins to the classpath before running policy management subcommands.

To add a jar file to the ssoadm classpath, set the CLASSPATH environment variable before running the ssoadm command:

$ export CLASSPATH=/path/to/jarfile:$CLASSPATH
$ ssoadm …​

Scripted policy conditions

You can use scripts to tailor the actions AM takes as part of policy evaluation.

AM includes a sample policy condition script^ that lets users in their country of residence access resources there.

You can view the script in the AM admin UI. Go to Realms > Realm Name > Scripts, and select Scripted Policy Condition.

Prepare a demonstration

To demonstrate the sample policy condition script:

Policy administrator account

This account represents the policy enforcement point (PEP) account. It has the Entitlement Rest Access privilege required to request AM policy decisions over HTTP using the REST API. In a production deployment, use a PEP like PingGateway or an AM agent in this role.

  1. Create a policy administrator.

    In the AM admin UI, select Realms > Realm Name > Identities > + Add Identity and fill the required fields.

    Record the username and password.

  2. Create a group that grants the Entitlement Rest Access privilege to the policy administrator.

    Select Realms > alpha > Identities > Groups > + Add Group to create a group with the following settings:

    Group ID

    am-policy-evaluation

    Members

    The policy administrator whose username you recorded

    Privileges

    Entitlement Rest Access

End user account

This account represents the end user who tries to access online resources.

  1. Create a user.

    In the AM admin UI, select Realms > Realm Name > Identities > + Add Identity and fill the required fields.

    Record the username and password.

  2. In the Home Address field of the user profile, enter an address in the US such as the following and save the change:

    201 Mission St, Suite 2900, San Francisco, CA 94105

Sample policy

The policy references the script through environmental conditions.

  1. Create a policy set for policies regarding URLs.

    In the AM admin UI, select Realms > Realm Name > Authorization > Policy Sets > + New Policy Set to create a policy set with the following settings:

    Id

    am-policy-set

    Resource Types

    URL

  2. Create a policy in the policy set.

    Select Realms > Realm Name > Authorization > Policy Sets > am-policy-set > + Add a Policy to create a policy with the following settings:

    Name

    Scripted policy example

    Resource Types

    URL

    Resources

    *://*:*/*, *://*:*/*?*

  3. In the new policy, update the settings.

    Allow HTTP GET access by all authenticated users when permitted by the script:

    Actions

    GET: Allow

    Subjects

    Type: Authenticated Users

    Environments

    Type: Script, Script Name: Scripted Policy Condition

    When modifying settings in the policy editor, select the edit icon to begin changing the setting, the check icon to confirm the change, then Save Changes to commit the change.

  4. Verify the policy settings.

    Policy settings for the Scripted policy example

Try the demonstration

The AM policies?_action=evaluate endpoint lets a policy administrator make a REST call over HTTP to get a policy decision from AM. AM policy decisions for URL policies show at least the HTTP actions the user can perform. For details, refer to Request policy decisions over REST.

Here, when AM grants the user access to complete an HTTP GET request to the resource, the decision includes "actions":{"GET":true}. When AM denies access, the decision includes "actions":{}.

The REST call to the policies?_action=evaluate endpoint requires:

  • An SSO token ID for the policy administrator making the request.

  • An SSO token ID for the end user attempting to access the resource.

  • A request body that specifies who is attempting to access what in what way under what conditions.

    1. Obtain an SSO token for the policy administrator:

      $ curl \
      --request POST \
      --header 'Content-Type: application/json' \
      --header 'X-OpenAM-Username: <policy-admin-username>' \
      --header 'X-OpenAM-Password: <policy-admin-password>' \
      --header 'Accept-API-Version: resource=2.0, protocol=1.0' \
      'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
      {"tokenId":"<policy-admin-tokenId>","successUrl":"/am/console","realm":"/alpha"}
    2. Obtain an SSO token for the end user:

      $ curl \
      --request POST \
      --header 'Content-Type: application/json' \
      --header 'X-OpenAM-Username: <end-user-username>' \
      --header 'X-OpenAM-Password: <end-user-password>' \
      --header 'Accept-API-Version: resource=2.0, protocol=1.0' \
      'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/authenticate'
      {"tokenId":"<end-user-tokenId>","successUrl":"/am/console","realm":"/alpha"}
    3. Request evaluation for a request by a US end user in the US to access a resource located in the United States.

      The script lets users in their country of residence access resources there. The user’s home country and IP address match the resource location; AM grants access.

      $ curl \
      --header 'iPlanetDirectoryPro: <policy-admin-tokenId>' \
      --request POST \
      --header 'Content-Type: application/json' \
      --header "Accept-API-Version: resource=2.1" \
      --data '{
        "resources": ["https://www.whitehouse.gov:443/about-the-white-house/"],
        "actions": {"GET": true},
        "application": "iPlanetAMWebAgentService",
        "subject": {
          "ssoToken": "<end-user-tokenId>"
        },
        "environment": {
          "IP": ["8.8.8.8"]
        }
      }' \
      'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_action=evaluate'
      [{
        "resource": "https://www.whitehouse.gov:443/about-the-white-house/",
        "actions": {
          "GET": true
        },
        "attributes": {
          "countryOfOrigin": ["US"]
        },
        "advices": {},
        "ttl": <ttl>
      }]

      The script adds "attributes":{"countryOfOrigin":["US"]} to the result when AM grants access.

    4. Request evaluation for a request by a US end user outside the US to access a resource located in the United States.

      The user’s IP address does not match the home country or the resource location; no actions are returned:

      $ curl \
      --header 'iPlanetDirectoryPro: <policy-admin-tokenId>' \
      --request POST \
      --header 'Content-Type: application/json' \
      --header "Accept-API-Version: resource=2.1" \
      --data '{
        "resources": ["https://www.whitehouse.gov:443/about-the-white-house/"],
        "actions": {"GET": true},
        "application": "iPlanetAMWebAgentService",
        "subject": {
          "ssoToken": "<end-user-tokenId>"
        },
        "environment": {
          "IP": ["88.174.153.24"]
        }
      }' \
      'https://openam.example.com:8443/openam/json/realms/root/realms/alpha/policies?_action=evaluate'
      [{
        "resource": "https://www.whitehouse.gov:443/about-the-white-house/",
        "actions": {},
        "attributes": {},
        "advices": {},
        "ttl": <ttl>
      }]

      Notice "actions":{} in the response.

Enable debug logging for scripted policy conditions

These steps show how to enable trace-level debug logging for scripted policy conditions, so that logger output from the default policy condition script is recorded.

The script containing the debug output to capture must execute at least once to create the logger.

The name of the scripted policy decision logger has the format: scripts.POLICY_CONDITION.script-UUID.

  1. Log in as the AM administrator, amAdmin.

  2. Go to the Logback.jsp page; for example, https://openam.example.com:8443/openam/Logback.jsp.

  3. In the Logger list, scroll to select the scripted policy decision logger; for example, scripts.POLICY_CONDITION.9de3eb62-f131-4fac-a294-7bd170fd4acb.

  4. From the Level list, choose the debug level required.

    In this example, select Trace.

  5. Click Apply.

    Enable debug logging for a scripted conditions.

    Trace-level debug logging is now enabled for scripted policy conditions, with script output appearing in the /path/to/openam/var/debug/Policy debug log file.

    Changes to the Logback.jsp page do not persist when AM restarts.

    For additional details, refer to Debug logging.

Policy condition script API

A policy condition script has access to the following specific bindings, predefined objects that AM injects into the script execution context.

Use these objects in a script to get information such as the authorization state of a request, session properties, and user profile data.

AM can return the information in the response to an authorization request.

If you use static methods within policy scripts, you must allowlist those scripts. Otherwise, policy evaluation fails with an exception—​logged in the Entitlement debug file—​similar to the following:

java.lang.SecurityException: Access to Java class script-name is prohibited.

Binding Description Further information

advice

Return the condition advice from the script.

authorized

Return true if the authorization is currently successful, or false if authorization has failed.

Server-side scripts must set a value for authorized before completing.

environment

The environment values passed from the client making the authorization request.

httpClient

Make outbound HTTP calls.

identity

Access the data stored in the user’s profile.

logger

Write a message to the AM debug log.

resourceAttributes

Add an attribute to the response to the authorization request.

scriptName

Return the name of the running script.

session

Access the properties for the current session.

ttl

The time-to-live value for the response to a successful authorization.

username

String identifying the user ID of the subject requesting authorization.

-

Access environment data

The environment binding holds data from the client making the authorization request as a Map of <String, Set<String>.

For example, the following shows a simple environment map with a single entry:

  • Policy condition script

  • OAuth 2.0 scopes policy script

"environment": {
    "IP": [
        "127.0.0.1"
    ]
}
"environment": {
    "clientId": [
        "MyOAuth2Client"
    ]
}
For information about scripting OAuth 2.0 policy conditions, refer to OAuth 2.0 scopes policy script API.

Access profile data

Server-side authorization scripts can access the profile data of the subject of the authorization request through the methods of the identity object.

To access a subject’s profile data, they must be logged in and their SSO token must be available.

Set identity.getAttribute(String attributeName)

Return the values of the named attribute for the subject of the authorization request.

For example:

var attribute = identity.getAttribute("attrName").iterator().next();
void identity.setAttribute(String attributeName, Array attributeValues)

Set the named attribute to the values specified by the attribute value for the subject of the authorization request.

For example:

identity.setAttribute("attrName", ["newValue"]);

// Explicitly persist data
identity.store();
void identity.addAttribute(String attributeName, String attributeValue)

Add an attribute value to the list of attribute values associated with the attribute name for the subject of the authorization request.

For example:

identity.addAttribute("attrName", ["newValue"]);

// Explicitly persist data
identity.store();

You must call identity.store() to persist changes or they will be lost when the script completes.

Access session data

Server-side authorization scripts can access session data for the subject of the authorization request through the methods of the session object.

To access the session data of the subject, they must be logged in and their SSO token must be available.

String session.getProperty(String propertyName)

Retrieve properties from the session associated with the subject of the authorization request. Refer to the following table for example properties and their values.

Session properties and example values
Key Sample value

AMCtxId

e370cca2-02d6-41f9-a244-2b107206bd2a-122934

amlbcookie

01

authInstant

2018-04-04T09:19:05Z

AuthLevel

0

CharSet

UTF-8

clientType

genericHTML

FullLoginURL

/openam/XUI/?realm=alpha#login/

Host

198.51.100.1

HostName

openam.example.com

Locale

en_US

Organization

dc=openam,dc=forgerock,dc=org

Principal

uid=amAdmin,ou=People,dc=openam,dc=forgerock,dc=org

Principals

amAdmin

Service

ldapService

successURL

/openam/console

sun.am.UniversalIdentifier

uid=amAdmin,ou=People,dc=openam,dc=forgerock,dc=org

UserId

amAdmin

UserProfile

Required

UserToken

amAdmin

webhooks

myWebHook

Set authorization responses

Server-side authorization scripts can return information in the response to an authorization request with the following methods:

void responseAttributes.put(String attributeName, Array attributeValue)

Add an attribute to the response to the authorization request.

void advice.put(String adviceKey, Array adviceValues

Add advice key-value pairs to the response to a failing authorization request.

void ttl(Integer ttlValue)

Add a time-to-live value, which is a timestamp in milliseconds to the response to a successful authorization. After the time-to-live value the decision is no longer valid.

If no value is set, ttlValue defaults to Long.MAX_VALUE (9223372036854775807), which means the decision has no timeout, and can live for as long as the calling client holds on to it. In the case of policy enforcement points, they hold onto the decision for their configured cache timeout.