User Management API Documentation

Overview

This section describes the API endpoints and features that are provided for the purposes of identity and access management, including examples of hosted automation in python. There are features intended for DABL application authors for the purposes of authenticating their end users and writing applications that respond to the presence of new users. In addition, there are features for application authors to externalize a part of their application automation and host it themselves, while still being able to use DABL's APIs to run DAML transactions.

Onboarding authenticated users

Almost every app that is deployed in DABL is meant to be used by multiple users and not just you, its creator.

Each of those users must sign up with their own account in order to be able to act as a DAML party on a ledger. This provisioning happens automatically and in an ad-hoc fashion when the user signs up for the first time. What is more, each new party that enters the system needs to get properly onboarded in your DAML app so that it gets the appropriate disclosures and permissions to perform actions.

The following section outlines the hosted login functionality that DABL provides, by examining a particular example application that makes use of it, called DABL Chat. You can find the source code for DABL Chat here, for an up to date and working example that incorporates these ideas. Relevant snippets of that application are also expanded inline within this documentation for additional context.

The Login In with DABL button

This is a button that redirects the new user to sign up with their email and password, or other supported identity provider, and then back to your app, while also allocating a ledger identity for them. The login button is an html <a> tag with a hypertext reference to a login url.

<a href={`https://login.projectdabl.com/auth/login?ledgerId=${ledgerId}`}>Log In with DABL</a>

NOTE: ledgerId is the ledger identifier of the deployed ledger.

This ledger id can be found in the Ledger Settings page. Since this id is not known until the ledger is created, but the ledger id is present in the URL where your application is served, you can construct the login URL appropriate to your ledger using this handy JavaScript:

const makeLoginUrl = () => {
   let host = window.location.host.split('.');
   const ledgerId = host[0];
   let loginUrl = host.slice(1);
   loginUrl.unshift('login');

   return loginUrl.join('.')
     + (window.location.port ? ':' + window.location.port : '')
     + '/auth/login?ledgerId=' + ledgerId;
 }

NOTE: this code makes assumptions about the domain layout of the deployed application, namely that the ledger id is the prefix of the hosted application url when splitting with a period.

A successful user authentication will redirect the user to the app url, while setting a cookie containing an access token for the logged in user, as well as a query parameter containing the party identifier. Your frontend can then extract those parameters and later use them to make authenticated calls:

const urlParams = new URLSearchParams(url.search);
 const partyId = urlParams.get('party')
 const tokenCookiePair = document.cookie.split('; ').find(row => row.startsWith('DABL_LEDGER_ACCESS_TOKEN')) || '';
 const token = tokenCookiePair.slice(tokenCookiePair.indexOf('=') + 1);

NOTE: previous versions of DABL would supply the initial access token as a URL parameter, but this delivery mechanism is being phased out in favor of a cookie based one. The above code can be used to retrieve the initial access token in a manner that will continue to function now and in the future.

Listening for new users

After authenticating, your frontend can then create a contract describing a request for a user account on the ledger, as the user that has just authenticated:

template UserAccountRequest
  with
    operator : Party
    user : Party
    userName : Text
  where
    signatory user

    controller operator can
      UserAccountRequest_Accept : Either (ContractId UserInvitation) (ContractId User)
        do
          -- ...

This template requires three pieces of information:

  1. The operator party, which represents the application itself.
  2. The user party, which represents the requester.
  3. The party's userName, a human readable string for the requesting user.

After a user logs in to a ledger and creates this contract, the contract gets disclosed to your operator party. All you have to do from there is to run automation as operator and listen to creations of your contract (Chat.UserAccountRequest in this example). When such a contract gets created, your bot will read the user from the contract and kick off an onboarding workflow for it. Your automation callback could look something like this:

@client.ledger_created('Chat.UserAccountRequest')
 def accept_user_account_requests(event):
     return exercise(event.cid, 'UserAccountRequest_Accept')

NOTE: this example uses decorators defined in the DAZL client, a python client for DAML ledger actions. For documentation on DAZL, see this page.

On the other side of this request, you would need a bot to listen and automatically accept the request, according to some workflow definition. For more details on how DABL Chat accomplishes this, check the source code.

Summary

This is an instance of a typical “Initiate - Accept” pattern that is further discussed in the official DAML docs. The workflow described above is the supported one for writing DABL applications that make use of DABL's hosted authentication features. To see DABL Chat in action, consider deploying it on your own ledger and poking around!

Service Accounts

Authenticating programmatic requesters

For those instances where you'd like to authenticate requests to programs, instead of people, DABL supports service accounts. These might be used when building an application that is composed of self hosted autonomous ledger accessing components. In these cases, if you simply copy your console access tokens into your application configuration, they will expire after 24 hours, quickly leading to failures authenticating your requests. For this reason, DABL also supports service accounts, which take the form of a long-lived credential which can be exchanged for an access token, which is itself valid for a longer period of time.

Service Account Allocation

To allocate yourself a service account, navigate to the ledger settings page. On that page, you can click the button labeled "add service account", which will issue you a service account and service account credential for that ledger, which can then be used to request access tokens. Be sure to copy the credential and store it in a secure location, as it will only be revealed exactly one time, and subsequent attempts to retrieve it will not succeed.

POST https://login.projectdabl.com/sa/login

curl -v -X POST https://login.projectdabl.com/sa/login -u $CRED_ID:$CRED_SECRET

This endpoint accepts a service account credential and supplies an access token. Credentials can be generated using the procedure described here. You can POST to it using a credential id, and a generated credential. This will return you a JWT which is otherwise indistinguishable from a console access token. Now, you can store your generated credential pair within your application configuration, and deploy your very own authenticated ledger automaton!

Parties With Special Significance

In DABL, there are exactly two parties with special significance. The first enables application owners to discover application users, and the second enables application owners to publish ledger data to the public.

GET [:ledgerId].projectdabl.com/.well-known/dabl.json

Returns a json object of the form:

{
   "userAdminParty": "ledger-party-[:uuid]",
   "publicParty": "public-[:ledgerId]"
 }

This can be used to discover two party identifiers, described below.

UserAdmin

The user admin is a party to administer users. It is created by the application operator, on each ledger, and is specific to that ledger. The only administrative function that it has is being made an observer of ledger party contracts corresponding to people that log into a ledger.

Public

The public party is a per ledger party which public data is disclosed to.

These are the API endpoints that can be used to support ledger access before any user has logged in. Even though DABL provides a mechanism for automatically allocating a ledger identity for an authenticated requester, there are also cases where it's important to be able to read ledger data before this, for instance to read public catalog data. In order to support this, DABL designates a party with a reserved name, which requesters can obtain a JWT to make requests with, but without supplying authentication credentials.

POST api.projectdabl.com/api/ledger/[:ledgerId]/public/token

This can be used by any requester, in order to obtain a token with which to perform read-only authenticated ledger activities. Application authors should take care to not disclose data to the public party which is not actually public. In order to undertand how this party could be automatically discovered by an application, see this section.

Summary

These interfaces together form DABL's published external API surface for IAM related services.