Skip to content

Random scripting examples for use in the ForgeRock Platform products.

License

Notifications You must be signed in to change notification settings

lapinek/platform-scripting-examples

Repository files navigation

ForgeRock Platform Scripting Examples

Supplemental examples to publicly available scripting resources, including:

Contents


ForgeRock Access Management (AM)

Back to Contents

General

Back to Contents

Back to Contents

  • Set a Theme with a Method of the Action Interface

    Back to Contents

    Example Script

    In Platform UI, you can apply a theme dynamically from a scripted decision node by sending callbacks and using withStage method of the Action Interface:

    action = javaImports.Action.send(
        javaImports.ScriptTextOutputCallback(script)
    ).withStage('themeId=' + themeNameOrId).build();

    Note, however, that setting a theme this way will be overridden by specifying a theme for journey, as described in Apply a custom theme to a Journey.

    You can find, update, or create a theme in the Platform Administrator under Hosted Pages. The theme name can serve as the theme ID in your scripted decision.

    Hosted Pages Screen in the ForgeRock Platform Administration UI Authentication Journey Configuration Screen in the ForgeRock Platform Administration UI with a Scripted Decision Node Setting the Custom Theme Sign In Screen with Custom Theme Applied
  • Get User Location from Their Postal or Physical Address and Save the Location Information in sharedState

    Back to Contents

    Example Script

  • Get User Location from Their IP Address and Save the Location Information in sharedState

    Back to Contents

    Example Script

    You can get the client IP address from the X-Forwarded-For request header in deployments with AM behind a balance loader or a reverse proxy.

    Otherwise, in an "on premise" installation, you'll need to obtain the client IP address with a script running in the browser. Accessing the request object in the scripted decision context is currently not an option.

  • Set a Session Property Based on a Value Saved in sharedState

    Back to Contents

    Example Script

  • Set Dynamically (Multiple) Session Properties

    Back to Contents

    Example Script

    You can set the future session properties in a scripted decision dynamically by using methods of an ActionBuilder instance returned by static methods of the Action interface.

  • Enable 2-Step Verification in Identity Cloud with Pre-existing Oath Devices Data Saved in a Custom Attribute

    Back to Contents

    Example Script

  • Resend HTTP Request

    Back to Contents

    In a scripted decision, you can use the httpClient binding for making an outbound HTTP request. The binding's .send(Request request) method returns a Promise. You can make the script wait for the promise to be resolved by using one of its .get methods. Alternatively, you can leave the promise to be resolved independently of the script execution with a .then method.

    If you use the .get() method, the scripted decision will wait for the promise to be resolved with the default timeout of 10 seconds and then continue to execute.

    Using the .get(long timeout, TimeUnit unit) allows to specify a custom timeout. This will require the java.util.concurrent.TimeUnit class to be added to the allowed Java in AM, as described in this KB article. Doing so is an option in self-managed environments, such as "on-premises" one or ForgeOps, but the class is not currently a part of the allowed Java in ForgeRock Identity Cloud.

    Whether the default or a custom timeout is used in the promise, it is possible that the request will intermittently fail. The example scripts referenced below allow for making a specified number of subsequent requests in case the previous request times out.

    Example Script - Default Timeout

    Example Script - Custom Timeout

Back to Contents

  • Saving AM User Session Information in a Custom Claim, and Resetting the Session Idle Timeout by Using the SSO Token

    Back to Contents

    Example Script

    • The Premise

      Back to Contents

      A third-party Relying Party (RP) might not be able to include the OpenID Provider (OP) cookies in requests made via the back channel. For example, including cookies in XHR requests from a different domain might be affected by the third-party cookies restrictions implemented in the browser; and for requests made from the server side, a third-party application won't have access to the cookies set by the authorization server.

      Therefore, maintaining a user session at the OP via the back channel, silently, may need to be implemented without reliance on the OP's session cookies.

      In AM, the session information could be accessible in the context of the OIDC Claims script, which runs when ID token claims are being processed. Thus, the session information could be included in a custom ID token claim.

      The session context in the script is provided via the session binding, which represents an instance of the SSOToken class.

      The session binding is currently available in the OIDC Claims script only when the session cookie is included in the OIDC authentication request; for example, during an interactive authorization code grant initiated in the front channel.

    • Trusted Relying Party (RP)

      Back to Contents

      In these conditions, a trusted RP application running in a different domain could maintain a (CTS-Based) user session at AM by providing the SSO token in a REST call to the /json/sessions/ endpoint.

      To make this call silently from a browser, via an XHR request, you will need to add the session token header name (typically, iPlanetDirectoryPro) to the accepted headers in your CORS service configuration, in the AM console > CONFIGURE > Global Services > CORS Service > Secondary Configurations > CORS configuration name > Accepted Headers.

      The SSO token could be obtained from the session object with its getTokenID() method.

      For this to work, you will need the com.iplanet.sso.providers.dpro.SSOTokenIDImpl Java class to be allowed in the scripting engine configuration for the OIDC Claims Script type.

      Then, the session token could be included as a custom claim in the ID token sent to the RP.

      With an RP that is a Single Page Application (SPA), storing the almighty SSO token in a browser should be well considered.

    • Untrusted RP

      Back to Contents

      An untrusted third-party application, belonging to a business entity different from the one maintaining the authorization server, should not have access to the user's SSO token.

      If/when the session binding were defined every time the ID token is issued, and the user session is not terminated, presence of a claim based on the session information could serve for the RP as an indication of an active user session, and its absence could be used by the RP to effect the single sign out functionality.

      In addition, the user session could be renewed from the script by sending a request to the /json/sessions/ endpoint; thus, relieving a trusted RP from the responsibility to maintain the SSO token, and providing a safe option to renew the user session for an untrusted RP.

      To make an HTTP request from the OIDC Claims script, you will need the following Java classes to be allowed in the scripting engine configuration for this script type:

      • org.forgerock.http.protocol.*
      • org.forgerock.http.Client
      • org.forgerock.util.promise.PromiseImpl
    • Example of an ID Token With Session Information:

      Back to Contents

      {
          "at_hash": "7y7kdvI4P97EOrng0kn7jw",
          "sub": "85f8cdd0-59f5-4d4c-b6f9-5fe0857c0f8c",
          "auditTrackingId": "e6716ee2-32ee-4b32-ade6-19c7f3760c87-80295",
          "subname": "85f8cdd0-59f5-4d4c-b6f9-5fe0857c0f8c",
          "iss": "https://default.iam.example.com/am/oauth2",
          "tokenName": "id_token",
          "session": {
              "timeLeft": 7199,
              "tokenId": "VxYoSm207yxijytEXTW2HUkNCmM.*AAJTSQACMDIAAlNLABxsQTFuU3NtMW00L3QxWTFiZmUrU2l4aitDSEU9AAR0eXBlAANDVFMAAlMxAAIwMQ..*"
          },
          "given_name": "user",
          "nonce": "Y2u8L7AjPOknYx7ESDJwNaAi2-3xloI79UWiS4vp6BQ",
          "sid": "E90taYovhKEMRrTu0+mTc64/1KbrHnG0z1QLtlSqV9o=",
          "aud": "node-openid-client",
          "c_hash": "8kF3xWVmnEzh51oqDD2Vvw",
          "acr": "0",
          "org.forgerock.openidconnect.ops": "GQgVZAO0mKmrPBru9WYymF2nJwI",
          "s_hash": "EdwNOuHRohV2HCUbUYONbg",
          "azp": "node-openid-client",
          "auth_time": 1625071581,
          "name": "user 0",
          "realm": "/",
          "exp": 1625075181,
          "tokenType": "JWTToken",
          "iat": 1625071581,
          "family_name": "0"
      }

Scripts to Run in a Browser

Back to Contents

Run this script in any administrative browser console—AM, IDM, or Platform.


ForgeRock Identity Management (IDM)

Back to Contents

Back to Contents

  • Custom Implementation of Knowledge Based Authentication (KBA)

    Back to Contents

    Example Script

    Continue reading for additional information and examples.

    Motivation

    Back to Contents

    • Allow for uploading existing hash into a custom field, and use it for validating users' answers to security questions.

      For example:

      "frIndexedMultivalued3": [
          "{\"questionId\":\"3\",\"answer\":\"$2a$10$QYZRykd.7Is1DQx96hfUeOunRACQKPKCR21jpPND60eCmC6WObhSK\"}",
          "{\"questionId\":\"1\",\"answer\":\"$2a$10$U6kH.1ghtrtzJhpNQXretuQR4psfO6zC5ANnwfjsGiLAdp0ob1xeG\"}",
          "{\"questionId\":\"2\",\"answer\":\"$2a$10$noDIZAkLxArssuDOw8PJhOseQ5QrwXSAckq/U2s1Gbj6G8hvlPLES\"}"
      ]
    • Allow for use of hashing algorithms that are currently unsupported in a control environment, such as ForgeRock Identity Cloud (Identity Cloud).

      For example:

      const javaImports = JavaImporter(
          java.security.SecureRandom,
          org.bouncycastle.crypto.generators.OpenBSDBCrypt,
          java.lang.String
      );
      
      // . . .
      
      /**
       * Create hash.
      */
      function hashAnswer(answer) {
          const secureRandom = new javaImports.SecureRandom();
          const salt = secureRandom.generateSeed(16);
          const answerJava = new javaImports.String(answer);
      
          return javaImports.OpenBSDBCrypt.generate('2a', answerJava.toCharArray(), salt, 10);
      }
      
      // . . .
      
      /**
       * Validate answers.
      */
      const hasIncorrectAnswer = requestQuestions.some(function (requestQuestion) {
          const requestAnswerJava = new javaImports.String(requestQuestion.answer);
          const correctAnswer = profileQuestions.find(function (profileQuestion) {
              return profileQuestion.questionId === requestQuestion.questionId;
          }).answer;
      
          return !javaImports.OpenBSDBCrypt.checkPassword(correctAnswer, requestAnswerJava.toCharArray());
      });

    Custom Endpoint for Saving and Validating Answers to Security Questions

    Back to Contents

    • Configure the Security Questions

      For example, in the browser console during an active IDM Administrator session, update the KBA configuration over REST:

      Update KBA Configuration - Example Script

    • Create a Custom Endpoint to Launch the Script

      Upload the following script at the custom endpoint:

      Custom Endpoint Script

      This ^^^ script is using OpenBSDBCrypt with the following defaults:

      const bcryptVersion = '2a';
      const bcryptCost = 10;

      For example, you can upload the script over REST using the following example as a template in the browser console during an active IDM Administrator session:

      Create or Update Custom Endpoint - Example Script

    • Optionally, load the existing hashed answers into the custom KBA field as an array of stringified JSON.

      For example:

      "frIndexedMultivalued3": [
          "{\"questionId\":\"3\",\"answer\":\"$2a$10$QYZRykd.7Is1DQx96hfUeOunRACQKPKCR21jpPND60eCmC6WObhSK\"}",
          "{\"questionId\":\"1\",\"answer\":\"$2a$10$U6kH.1ghtrtzJhpNQXretuQR4psfO6zC5ANnwfjsGiLAdp0ob1xeG\"}",
          "{\"questionId\":\"2\",\"answer\":\"$2a$10$noDIZAkLxArssuDOw8PJhOseQ5QrwXSAckq/U2s1Gbj6G8hvlPLES\"}"
      ]
    • During registration, use PATCH request to the custom endpoint to hash plain-text answers with the custom algorithm, save them in the custom KBA field, and update the standard KBA property accordingly.

      See an example of doing so in the browser console during an active IDM Administrator session:

      Hash and Save Answers in a Custom KBA Field - Example Script

    • During authentication, use POST request to the custom endpoint to verify plain-text answers against hashes saved in the custom KBA field, and to update the standard KBA property accordingly if the correct answers were provided.

      See an example of doing so in the browser console during an active IDM Administrator session:

      Verify Answers Against Hashes Saved in the Custom KBA Field - Example Script

    • During registration and authentication, optionally, pass in the custom KBA field name in the requests sent to the custom endpoint as the field parameter.

      For example (to be run in the browser authenticated as IDM Administrator):

      var customEndpointName = '{custom-endpoint-name}';
      var userId = '{user-id}';
      var data = JSON.stringify([
          {
              operation: 'replace',
              field: '{custom-kba-field-name}',
              value: [
                  {
                      questionId: '{question-id}',
                      answer: '{answer}'
                  }
              ]
          }
      ]);
      
      await $.ajax({
          method: 'PATCH',
          url: '/openidm/endpoint/' + customEndpointName + '/' + userId,
          data: data,
          headers: {
              'x-requested-with': 'XMLHttpRequest',
              'Content-Type': 'application/json'
          }
      });

      If the field parameter is not provided, the custom endpoint script will substitute it with a default:

      const defaultKbaCustomField = 'frIndexedMultivalued3';

      You can also change the default in the Custom Endpoint Script.

    • Optionally, when the standard KBA property has been populated for all users, use the out of the box KBA nodes to validate user's answers.

      KBA Verification Node with three questions
  • Update Mappings via REST

    Back to Contents

    Example Script

ForgeRock Identity Platform and Identity Cloud

Back to Contents

  • Backup Realm Configuration with FRODO CLI

    Back to Contents

    An example shell script that saves major realm configuration components:

    Example Script

    Example call:

    $ ENVIRONMENT=kl03; REALM=alpha; /path/to/frodo-backup-realm-configuration.sh $ENVIRONMENT $REALM;
    

About

Random scripting examples for use in the ForgeRock Platform products.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published