Repository navigation
Authentication
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
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}'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.
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
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".
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 …
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.
| 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/ |
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/
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
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: