Identity Resolution


Lookup Strategy

The core of Identity Resolution in Hull relies on the claims you pass along with the incoming messages you send to Hull through the Firehose. You pass the claims as the “Hull-Access-Token” parameter in the Headers of your HTTP Call:

headers: {
  "Hull-App-Id": CONNECTOR_ID,
  "Hull-Access-Token": JWT_ENCODED_CLAIMS | CONNECTOR_SECRET,
  "Hull-Organization": ORGANIZATION,
}

Building JWT Tokens

Integrate Hull with your existing user management and create/lookup users in Hull.

Users and accounts can be looked up and lazily created with the API by using secure JSON Web Tokens (JWT).

Anatomy of a JWT Auth token

A valid JWT for use with hull MUST contain the following claims :

Mandatory claims :

  • iss : Identifier of the issuer of the token (Most of the time, it will be your Hull App ID)
  • iat : Unix timestamp of the date the token has been issued at
  • sub : Subject of the Token, it’s your Hull User’s ID

Optional claims :

  • exp : Unix timestamp of the expiration date for the token. After this date, the token will not be considered valid.
  • nbf: Unix timestamp of a date. The token will not be considered valid of used before this date.
  • io.hull.user INSTEAD OF the sub claim, to use a unique ID that you generate and manage.
  • io.hull.asUser INSTEAD OF the sub claim, to look for the best matching user.
  • io.hull.asAccount: INSTEAD OF the sub claim, to look for the best matching account.
  • io.hull.subjectType (string): Whether user or account. Indicate which object type you want to perform action on. Allow to retrieve a user’s account when used with a user identifier.
  • io.hull.create (boolean): used with io.hull.asUser|asAccount. If true and no user is found, a new user will be created with the properties listed in io.hull.asUser|asAccount. Default: true
  • io.hull.active (boolean) : Marks the user as active for the specified number of seconds. Allows to fast track recompute and notifications for that specific user while he remains active. Default: false
  • io.hull.scope (array) : adds scopes claim to the JWT to impersonate a User with admin rights. Currently, only supported value is [“admin”]

All JWTs MUST be signed with the secret of the issuer. App issued token must be signed with the App Secret that you can find in the App’s configuration page in Hull admin.

Using Tokens to lookup users

If your develop a Hull connector and don’t have access to the user’s identifier, you can build a special token that will use a resolution strategy to find the best matching user.

Instead of using the io.hull.user claim, you should use the io.hull.asUser claim. Allowed properties include and will be resolved in that order :

  • external_id
  • email
  • anonymous_id

Example use with Ruby:

$ gem install hullio jwt


require 'jwt'
require 'hullio'

Hull.configure do |c|
  c.app_id     = "your-app-id"
  c.app_secret = "your-app-secret"
  c.org_url    = "https://ORG-NAMESPACE.hullapp.io"
end

user = User.find('1234') # Retrieve your user here.
userHash = {
  external_id: user.id,
  email      : user.email,
}
token = Hull.user_token(user_hash)

userHash = { external_id: user.id } # The second time around, you only need the external_id.
token = Hull.user_token(user_hash)

userHash = {external_id: user.id, email: 'changed@email.com'} # To update data for the user, pass the field again
token = Hull.user_token(user_hash) # Pass token to hull.js or use in Server-to-server api calls

It allows you to authenticate users with identifiers from your app without having to keep track of their Hull User ID. As a rule of thumb, you should never rely on the Hull ID because it might change at any time if/when the user is merged with another one.

Lazy Creation

  • If no User with a matching external_id, or email is found, it will be created automatically.
  • If a user matching the email is found, it will be used.
  • If more than one user matching the email are found, the oldest will be used.
  • If an external_id and an email are found, then the external_id takes precedence for finding the user, but the email will be added to that user, potentially merging another user with this email and no external_id

  • If the User is found, he will be authenticated and updated with the additional properties passed via the io.hull.user.

Using Tokens to lookup accounts

You can use the io.hull.asAccount claim to lookup an account using the following properties which will be resolved in that order :

  • external_id
  • domain

You can also lookup a user with any claim allowing to do that, and set the io.hull.subjectType claim to account to retrieve the matched user’s account.

Linking Users and Accounts

You can link a user to an account by providing both io.hull.asUser and io.hull.asAccount claims. The matched user and account will be linked. If no user and account match, they will be created.

When linking, you can choose if you want to retrieve the matched user or account by providing a io.hull.subjectType claim set to whether user or account.

Using Tokens with the REST API, server to server.

If you sign any API call with a JWT as described below, a User will be created on the fly if it can’t be found. For instance you could directly start creating comments on an entity with a User on your backend without any prior setup:

// npm install jwt-simple hull


import Hull from 'hull';

const client = new Hull({
  id: 'HULL_ID',
  secret: 'HULL_SECRET',
  organization: 'HULL_ORGANIZATION_DOMAIN'
});

client.asUser({ external_id: "1234", email:'xxx@example.com', name:'FooBar' }).token(optionalClaims);
// => JWT_TOKEN