OpenAM: REST APIs for policy evaluation

OpenAM logo

One of the significant new features added to OpenAM and coming in the pending release is the new REST API for policy evaluation. To try the API, get a nightly build of OpenAM, or build the code yourself from the trunk.

Some background: Your application should not be in the business of making policy decisions. Not because you are not smart enough to do it, but instead because you do not want to maintain potentially intricate and changing policies across all your applications. Instead your application should ask a service like OpenAM to make policy decisions, and then focus only on enforcing those policy decisions. (In fact, if your application runs in a web server or application server, you could do even better by getting a policy agent to do the work on your application’s behalf.) You can therefore administer policies within the service like OpenAM, and have them uniformly enforced across many applications. Policy evaluation is what your application asks a policy decision point like OpenAM to carry out.

OpenAM has had REST APIs for policy evaluation for a long time. The older APIs required, however, that you re-encode the SSO token in a particular way. They also did not necessarily return JSON, making them a bit more difficult to work with.

The newer API returns JSON, and does not require tokens to be re-encoded. The newer API makes use of two endpoints:

  1. /json/policies?_action=evaluate (for myRealm/subRealm, /json/myRealm/subRealm/policies?_action=evaluate)
    This endpoint takes an HTTP POST, where the POST data is a JSON object defining the “resources”, “application”, “subject”, and “environment” for which OpenAM makes the policy decision.

    • The “resources” in this case is an array of strings specifying the resource(s), such as "http://www.example.com/profile", that the user is trying to access. This is the only required field.
    • The “application” is the policy application name. You see the application names in the new policy editor. Policies belong to applications, so the application name narrows down the set of policies that can apply.
    • The “subject” can take an SSO token ID string to represent the subject, but it can also take a JWT or a map of JWT claims, depending on how the policies are configured in OpenAM.
    • The optional “environment” can provide additional information about the environment of the user who is trying to access the resource.
  2. /json/policies?_action=evaluateTree (for myRealm/subRealm, /json/myRealm/subRealm/policies?_action=evaluateTree)
    This endpoint takes an HTTP POST with POST data similar to the first. Instead of “resources”, it takes a “resource” string. OpenAM returns policy decisions about all the resources under the specified “resource”.

Suppose you have a policy in OpenAM that belongs to the default application and that allows authenticated users GET access to "http://www.example.com/profile", returning the user’s common name as a response attribute.

In addition, you have a web page that allows you to get a policy decision when logged in as a user authorized to request policy decisions, such as OpenAM administrator. (This example is overly simplistic and mixes up content with policy enforcement. In real life, your client-side JavaScript would end up requesting a resource; your server-side policy enforcement code would check with OpenAM before responding.)

<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
</head>
<body>

<h3>Fake Profile Page</h3>

<div id="common-name"></div>
<div id="policy-decision"></div>
<div id="error"></div>

<script type="text/javascript">

var endpoint  =
  "http://openam.example.com:8080/openam/json/policies?_action=evaluate";
var resources =
  '{ "resources": [ "http://www.example.com/profile" ] }';

$(document).ready(function () {

  // Request decision from OpenAM.
  $.ajax({

    url: endpoint,
    type: "POST",
    contentType: "application/json",
    dataType: "json",
    data: resources

  }).done(function (data) {

    // Display the name.
    $("#common-name").html(
      "<h4>Common Name</h4>"
      + "<pre>"
      + data[0].attributes.cn
      + "</pre>"
    );

    // Display the full response.
    $("#policy-decision").html(
      "<h4>Policy Decision</h4>"
      + "<pre>"
      + JSON.stringify(data, undefined, 2)
      + "</pre>"
    );

  }).fail(function (data) {

    // Display the error response.
    $("#error").html(
      "<h4>Error:</h4>"
      + "<pre>"
      + JSON.stringify(data, undefined, 2)
      + "</pre>"
      );
    });
});

</script>

</body>
</html>

If you first login to OpenAM as amadmin in order to get a session cookie and then visit the web page, you can get a policy decision for the specified resource.

policy

For details on the API, see the draft documentation on Requesting Policy Decisions.