Trigger-service and authentication

Hey :wave:

I’m trying to get Trigger Service to work with oauth authentication. I’m confused as to how logging in a user is supposed to work in such a flow though.

When I install a trigger I do notice that it’s calling /auth in the authentication middleware. However, from what I understand (which could certainly be wrong) calls to /auth are supposed to be preceded by a call to /login. But Trigger Service would never make a /login call on its own, would it?

The documentation on Trigger Authorization does provide instructions on how to handle logins. However, the idea there seems to be to create some kind of web portal that a trigger user can check every now and then to see if they’re still logged in on the Trigger Service. And if they’re not then I suppose at that point they would manually go through the log in process. (Technically: the web portal would connect to the middleware and call /login, which in turn would trigger a redirect to the log in page in the browser.)

I’m left wondering what the recommended way would be to solve this problem if we want to run Trigger Service without supervision. Is it left as an exercise for the reader? If so, can you give this reader more hints? :upside_down_face:

Edit: I’m aware that I may be asking for something that in a lot of ways is conceptually unsound. In that cas, however, it would be helpful to just have that confirmed and also to maybe get a sketch as to what the ‘vision’ is for the UX of running Trigger Service in production. :pray:

4 Likes

The default auth setup of the trigger service is built around an OAuth authorization code/three legged flow where users explicitly opt in to delegating their authorization to the trigger service and allowing to act on their behalf. This is a deliberate choice to avoid setups where triggers are spun up on behalf of users without their interaction.

If you’re looking for a different kind of setup where there is no user involvement, then you might have to implement your own auth middleware where you directly request tokens via something like an OAuth client credentials flow. I don’t think anyone has actually done that so far though. The API that you have to implement is specified in Auth Middleware — Daml SDK 2.3.2 documentation.

2 Likes

Thanks @cocreature. What you’re saying is congruent with new insights I have gathered since my original post.

Let me go in a bit more detail in case it’s useful for anyone else.

I basically had two realizations:

  1. In some environments server-side components are already authenticating with OAuth 2.0 using client certificates (mTLS) rather than passwords. Having a login page does not make sense in that case. Moreover, it may be that you already have the private key required to fetch the access token stored on your server.
  2. Some of the other Daml components take paths to access tokens as input. In some setups one might wish that the same was possible for trigger service.

So basically the whole flow of using refresh tokens, reverse proxies, cookies, and a login page may be overkill for some deployments, depending on application-specific concerns. I think that if you are comfortable storing the access token on disk or if you’re comfortable storing an mTLS private key on disk then you may want a different solution.

If you have the access token stored on disk, you can use this implementation of auth service:

#!/usr/bin/env bash
while true
do
  {
    tok="$(< /path/to/access_token)"
    printf 'HTTP/1.0 200 OK\r\n'
    printf 'Content-Type: application/json\r\n'
    printf 'Content-Length: %d\r\n' ${#tok}
    printf '\r\n{ "access_token": "%s", "refresh_token": "" }' "$tok"
  } | nc -l localhost 5000
done

Warning: I reckon this script cannot handle concurrent requests well. The script worked just fine for my modest use case but I present it mostly as a proof of concept.

Patch the script to use tok="$(curl --data ... --cacert ... --cert ... --key ... https://... | jq -r .access_token)" (or something to that effect) if you want to use mTLS rather than storing the file on disk.

I hope this helps. :slight_smile:

1 Like

I just learned something new.

As @cocreature mentioned the documentation does uses an ‘authorization_code / three legged approach’. An approach without refresh tokens is called a ‘client_credentials / two legged approach’.

You can find more details here.