Skip to content

Authentication

Chris Shingler edited this page Aug 7, 2024 · 47 revisions

Getting started

Before you can get started with any of Unity's APIs, we need to register your Application within our Authentication service but, before we can do that, you need to tell us which "auth flow" is suitable for you.

This document describes how Unity's authentication works and the auth flows we provide. Once you have decided which is appropriate for your needs, please register your App

Introduction

Requests to all Unity APIs are made via HTTPS and each request must be authenticated with a User's Bearer token, which must be included inside the Authorization header.

Here’s a curl example that returns a list of "Fee Earners" from our CRM API, where {token} must be replaced with a valid bearer token, and {tenantId} must be replaced with a valid Tenant Identifier (which is unique to each Law Firm):

curl --location --request GET 'https://api.{quill-domain}/quillapi5/feeearners' \
 --header 'clientId: {tenantId}' \
 --header 'Accept: application/Json' \
 --header 'Authorization: Bearer {token}'

Terminology & Quirks

As alluded to above, at Unity, we use the term "Tenant" to refer to our clients. We generate unique TenantId’s for each Law Firm. We will provide you with our mutual client’s TenantId, which you must include in CRM API requests as per the example above.

PLEASE NOTE: For legacy reasons, the TenantId is sent in a header called "ClientId" which should not be confused with your Application’s “client_id” which identifies your app and is required to get a bearer token.

Getting a bearer token

Unity's authentication model is an implementation of OpenID Connect (based on OAuth 2.0) & there are many third party frameworks/libraries available for popular programming environments. We strongly recommend you use a mature and well tested library for your platform rather than hand crafting your own "OAUTH client".

We offer two "flow" options for obtaining bearer tokens: Authorization Code Flow or Implicit Flow. Only you can decide which one is appropriate based on the architecture of your Application. Once you have decided which flow meets your needs, please complete our form so we can register your App

User Interaction

A common question we are asked is: "can I get a token without user interaction". The answer is simply "NO" you can't! User interaction is required to get a token. Our Auth service will pop up a login form requesting a valid username & password before it will issue a token. However, if you are using Authorization Code Flow, you can limit the number of user interactions (to say once per quarter) if your oauth library supports "refresh tokens".

Authorization Code Flow (for server side Web Apps)

If your App is Web Server Based e.g. a PHP, ASP.NET API/Web App or equivalent, this is the flow for you. It allows for longer lived sessions through the use of a client secret and refresh tokens.

With this flow you must provide us with your own "redirect uri". Once we have that we can register your App and provide you with your unique “client_id” and “client_secret”.

You are responsible for securing your "client_secret". Keep it server-side only and never shared, distributed or included in any source code, client side JavaScript, or compiled distributed binaries

Once we register your App for this flow, we will provide you with:

var Description
client_id A unique key that identifies your App to Unity
client_secret Keep this secure. It must be kept server-side and never leaked to the client app or made public
scope To tell our systems which Unity APIs your token is authorized to access

Given those values & your own redirect uri, you can use an OAuth library to make the necessary series of requests to: a) get a code (with user interaction); and b) exchange the code for an access & refresh token. Appendix 1 provides an example using Postman.

Access tokens have a short life but refresh tokens live for 90 days after which the user will need to grant access again, so refresh tokens make for a better user experience.

Authorization Code Flow is not suitable for native applications, i.e. windows apps, mobile apps, or single page apps (SPAs). Hence we also provide Implicit Flow …

Implicit Flow (for native Apps)

This flow is simpler to implement than the one above but is suited to native apps only e.g. a Desktop or Native Mobile Application because a client_secret does not need to be stored.

The payback is that the token lifetime is shorter (approx 18 hours) after which it must be renewed. In real life, this simply equates the user logging in once per day, which in our experience is totally acceptable.

Once you have decided you require Implicit Flow and completed our register your App form, we will provide you with the following values:

var Description
client_id A unique key that identifies your App to Unity
scope To tell our systems which Unity APIs your token is authorized to access
redirect_uri Although not required for implicit flow, you must send this value (where "oob" means "out of bounds") oob://localhost/data

Once again, we strongly recommend you use mature and trusted third party libraries to handle these OAUTH2 authentication flows.

Important URLs and initial discovery

Title Description Scope Root
Discovery An endpoint provided for discovering the URLs below programmatically N/A https://discovery.{quill-domain}/default.json
Auth API Retrieve a bearer token via one of our two optional "flows" openid https://auth.{quill-domain}/
CRM API Create & Edit Clients, Cases & Contacts + also create simple time sheet items crmwebservice https://api.{quill-domain}/quillapi5/
Money API Create bills, disbursements etc. interactivewebservice https://i3.{quill-domain}/api/

Targeting the right Tenant (our mutual client)

As shown in the example at the beginning of this doc, the "CRM API" requires that the TenantId is sent with each request in the “ClientId” header.

However, the "Money API" works differently and instead requires a unique “TenantURI” within the URI web address. For example, this request retrieves a list of tax rates (vat codes):

curl --location --request GET 'https://i3.{quill-domain}/api/{tenantUri}/Money/TaxRates/' \
--header 'Accept: application/Json' \
--header 'Authorization: Bearer {token}'

Note that the "TenantUri" can be discovered by pointing at the API root:

curl --location --request GET 'https://i3.{quill-domain}/api/' \
--header 'Accept: application/Json' \
--header 'Authorization: Bearer {token}'

This returns a json file containing the Tenant(s) - usually one - that the user has access to e.g.

{
    "TenantId": 123,
    "UriName": "abc-law-ltd",
    "Name": "ABC Law Limited",
    "_links": {
        "recentCases": {
            "href": "https://{domain}/api/{tenantUri}/cases/recent",
            "templated": false
        }
    }
}

So, given your TenantId, you can extract the "UriName" from that json document and use it to construct a valid URL e.g. https://i3.{quill-domain}/api/abc-law-ltd/Money/TaxRates/

Appendix 1: Quick Start with Postman

Postman (v9.1.3 or above) handles much of the complexity around getting auth tokens for you, so its a good way to get started quickly.

NOTE: Does NOT work with our Implicit flow. Works with our Authorization Code Flow ONLY

Edit your collection, head to the Authorization tab, select:

  • Type: OAuth 2.0
  • Add auth data to: Request headers

Then complete the "Configure New Token" form like this:

key value
Token Name Unity
Grant type Authorization Code
Callback URL https://app.getpostman.com/oauth2/callback
Check "Authorize using browser"
Auth URL https://auth.{quill-domain}/core/connect/authorize
Access Token URL https://auth.{quill-domain}/core/connect/token
Client Id {your-application-client-id}
Client Secret {your-application-client-secret}
Scope openid crmwebservice interactivewebservice
State Can be ignored for testing, but is recommended for Production
Client Authentication Send as Basic Auth header

Once you have completed the form, hit "Get New Access Token" & a Unity login form will pop up. Enter a valid Unity username/ password, & a bearer token will be returned, which you can then use in further API requests.

Further Postman Authorization guidance here

Appendix 2: Further reading

Authorisation Code v Implicit Flow https://www.scottbrady91.com/OpenID-Connect/OpenID-Connect-Flows

A c# Implicit Flow example can be found here & once you've cloned that Github project, open up the Clients solution and then the WPF WebView Sample project which is an "Implicit Flow" example.

PHP Client Libraries: https://oauth.net/code/php/

Further Authorization Code Flow info here: https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type

Regarding "State" & “N.Once” values:

https://stackoverflow.com/questions/46844285/difference-between-oauth-2-0-state-and-openid-nonce-parameter-why-state-cou/46859861#46859861 https://auth0.com/docs/protocols/state-parameters

Further reading on OAUTH2 can be found here: https://swagger.io/docs/specification/authentication/oauth2/

Refresh Tokens are supported with our Authorization Flow. Refreshing tokens is a fairly involved process and we don't provide specific examples. We strongly recommend you use a mature and well tested library for your platform which is likely to support refresh tokens out of the box. But these pages may help you get started with your research:

Okta get-refresh-token

Okta refreshing-an-access-token