See api-docs Menu

Overview

Early Preview

This API is in early preview and may be subject to change. Please contact your account manager if you are interested in trying Smart Hooks.

Smart Hooks offers a new way to extend OneLogin in ways never possible before. From creating conditional access login flows to augmenting user lifecycle events we can’t wait to see what you build.

We have several types of hooks planned primarily around authentication flows and user lifecyle events. The initial release of Hooks includes our first authentication level hook, called the Pre Authentication Hook.

Use this set of APIs to manage your Hooks. You will find endpoints to create, update, delete Smart Hooks as well as defining environment variables and accessing execution logs.

What is a Hook?

A Hook is an extension point in OneLogin that lets you define customized actions using Javascript code. You will use the Smart Hooks API to configure a javascript function that gets executed every time a specific hook fires.

Smart Hooks are serverless which means that OneLogin will host and execute the javascript functions for you. There is no need to catch and consume these hooks like you may have done in the past using our Event Webhooks.

Within a Hook you can import external helper modules, make requests to 3rd party or home grown APIs and in some cases return data that will alter a workflow in OneLogin.

For example, you may want to use a pre-authentication hook to dynamically change the a Users Policy during a login flow.

Pre Authentication Hook

The pre-authentication hook runs synchronously as part of a UI based login flow. The hook fires immediately after the user enters a username/email but before they enter their password or are prompted for multi-factor authentication.

Traditionally in OneLogin, what happens during the login flow is dictated by the User Policy that is assigned to a user. The primary benefit of this hook is that is gives you an opportunity to change the User Policy in real time based on a set of conditions.

For example, You may want to supress MFA registration unless a user is on a trusted network or prompt for stronger MFA factors when a user has a higher risk score or is travelling to a different country.

All of this is possible by creating the policies that represent the desired login behavior and then using the hook function to assign the appropriate policy at login time.

Once a pre-authentication has been defined it will be executed for every user that initiates a UI based login. It is not possible to test this hook on a subset of users so consider using a developer or sandbox account while developing your function.

Minimum Viable Function

At a minimum the pre-authentication hook should return the user object. The function below is effectively like not having a pre-authentication hook defined at all. It simply takes the user object from context and immediately returns it back to continue a login flow.

exports.handler = async (context) => {
    return {
        user: context.user
    }
}

Where hooks get exciting is when you consider what you might be able to do before returning the user and their associated user policy.

Hook Context

A context object is passed into every hook function. The context contains information about the user and device as well as optional information about their current risk score and location.

{
  "user": {
    "user_identifier": "jim-hendrix",
    "policy_id": 187345
  },
  "device": {
    "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",
    "is_mobile": false
  },
  "location": {
    "ip": "120.118.218.225",
    "country_code": "TW"
  },
  "risk": {
    "score": 30,
    "reasons": [
      "Infrequent access from 120.118.218.225",
      "Infrequent access from Kaohsiung City, Kaohsiung, Taiwan",
      "Infrequent access from Taiwan",
      "Infrequent access using Chrome on Windows",
      "Low trust for session"
    ]
  },
  "correlation_id": "13a97251-215d-4fa5-baaf-6fc15700a2db",
  "request_id": "7d436b7e-b4a3-4b48-83fd-f4a12c22bb62"
}
user An object that represents the user attempting to authenticate.
  • user_identifier - The username or email address entered by the user.
  • policy_id - The User Policy that will be applied for the rest of the login flow.
device An object decribing the device used during the authentication.
  • user_agent - The authenticating users browser or user agent.
  • is_mobile - A boolean flag that indicates if the login is taking place on a mobile device
location An object decribing the location of the authenticating user. This is only populated if the location_enabled property is set to true when creating/updating the Hook function.
  • ip - The authenticating users ip address.
  • country_code - An ISO 3166 Aplha 2 character country code based on a geo ip address lookup.
risk An object representing the current risk score for the authenticating user. This is only populated if the risk_enabled property is set to true when creating/updating the Hook function.
  • score - An integer between 0 (low) - 100 (high) risk level.
  • reasons - An array of strings that indicate the primary drivers behind the risk score.
correlation_id A unique identifier that can be used to trace a transaction end to end. This is useful if you need help from OneLogin support in debugging any issues.
request_id A unique identifier that can be used to trace a single incoming request.

Hook Response

The Pre Authentication hook gives you the opportunity to change the User Policy that will be used for the rest of the login flow (it does not permanently change their assigned User Policy). Therefore the minimum required response for this hook is a user object containing the policy id.

For example, This function will do nothing and keep the User Policy set to the users currently allocated policy.

exports.handler = async (context) => {
  return {
    user: context.user
  }
}

Where as this hook function would change the User Policy for mobile device users

exports.handler = async (context) => {
  
  let user = context.user;

  if (context.device.is_mobile) {
    user.policy_id = 1234;
  }

  return {
    user
  }
}

You can also halt the login flow and therefore deny the user the ability to complete the login by returning null from the function.

For example, Deny access based on high risk

exports.handler = async (context) => {
  
  // Deny on high risk
  if (context.risk.score > 90) return null

  // Otherwise let them login as normal
  return {
    user: context.user
  }
}

Environment Variables

In some cases you may want to make an external API request from a Hook and therefore need to include an API key in your hook function. Instead of hard coding secrets like API keys into your functions you should consider using an Environment Variable.

Environment Variables are not just useful for injecting secrets into your hooks. You can also use them inject common settings that may be useful across multiple different hooks.

It’s worth noting that if you update an environment variable, all of the hooks that have been linked to that variable will also be updated with the latest value.

How to use an environment variable in a hook

First create a environment variable using the API.

curl --location --request POST 'https://api.us.onelogin.com/api/2/hooks/envs' \
--header 'Authorization: Bearer xxx' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "SECRET_API_KEY",
    "value": "helloworld"
}'

Then access the variable by name from the standard Node.js environment object in your function code.

exports.handler = async (context) => {
  
  const apiKey = process.env.SECRET_API_KEY;

  // Do something with API key...

  return {
    user: context.user
  }
}

Runtime Environment

Smart Hooks must be written in Javascript and are executed using the latest LTS (Long Term Support) version of Node.js.

Current version is nodejs12.x

You must set the runtime attribute of each hook to one of the supported versions.

NPM Modules

You can give your hooks super powers by pulling in useful packages from NPM. You will be responsible for managing package versions and upgrading when required.

When creating or updating a hook use the packages attribute to make them available in your hook function code. You can then use the require method to make use of the package.

Included packages require that an explicit semantic version is set.

For example, Create a hook with MySQL package to enable access to an external database.

{
    "type": "pre-authentication",
    "function": "CmV4cG9ydHMuaGFuZGxlciA9IGFzeW5jIChjb250Z....",
    "disabled": false,
    "retries": 0,
    "timeout": 1,
    "risk_enabled": false,
    "location_enabled": false,
    "env_vars": [
    ],
    "packages": {
      "mysql": "2.18.1"
    }
}

Then require it in your function.

const mysql = require("mysql");

exports.handler = async (context) => {

  // Do something with mysql

  return {
    user: context.user
  }
}

Execution Timeouts

To ensure a good end user experience, Smart Hooks have execution timeouts in place.

The minimum timeout required for all hook types is 1 second.

The maximum timeout value varies for each type of hook.

Hook Type Maximum Timeout
pre-authentication 1

Logs & Debugging

When you’re getting started and in the development or experimentation phase we recommend using a developer or sandbox account for testing your Hook functions.

We also provide a convenient logs endpoint for each hook which will provide the last 7 days of execution history. These logs are great for inspecting values in your hooks or catching and reporting errors.

Anything that is logged using console.log() or console.error() will be included in the logs.

For example, log the context object so you can inspect its values.

exports.handler = async (context) => {

  console.log("Context: ", context);

  return {
    user: context.user
  }
}

or catch and report errors

exports.handler = async (context) => {
  try {

    // Do something that causes an error... 

    return {
      user: context.user
    }
  }
  catch (error) {
    console.error("Error", error);
    return null;
  }
}

Postman Collection

We’ve created a library of sample Hook functions in the Postman collection. We will keep it updated with functions that solve common requested workflows.

Postman Pre Request Script

To view & modify the function click on the Pre Request Script tab within Postman. Also note that this script will Base64 encode the function before it sends it to the Smart Hooks API.

Download for the Smart Hooks API