Use cases for Action Tokens vs Authenticator's actionURL

Looking for some help understanding best practices. I’m familiar with custom authenticators and somewhat familiar with action tokens. I have multiple scenarios where having a link that will allow continuing an auth flow is quite useful. The scenarios work and the code is functional, but I could use some help on which approach is “more correct” and why

When is it more appropriate to send a link containing an action token (and handle it using an action token handler) instead of using an authenticator’s AuthenticationFlowContext.getActionUrl?

For example, here is the link with an ActionToken:

base-url/realms/my-realm/login-actions/action-token?key=action-token-jwt-value&client_id=postman&tab_id=zNsbjDojVWg

The JWT decoding is pretty well explained in this documentation. Of interest to me, you can embed the ID of the authentication session into the token, although I’ve yet to determine if Keycloak does anything with this claim before calling the token handler.

Here is a link using an Authenticator’s getActionUrl method

base-url/realms/my-realm/login-actions/authenticate?session_code=my-code&execution=e9879abf-22f3-4ed2-8f27-7e8275ffdd20&client_id=postman&tab_id=zNsbjDojVWg

What I know so far:

  • The ActionToken is a JWT, so you get a crypto guarantee that it was generated by the server (and all the claims - you know when it was generated, you know it’s not expired, etc). It has some non-claim query params, so it’s a little bit susceptible to modification, but it’s much less modifiable than the actionUrl. You also get far more data in an ActionToken, and you can embed your own claims when then become tamper-proof. While you can embed claims into the actionUrl via your own query params, they are not tamper-proof.
  • Building an Authenticator that uses only the actionURL is slightly simpler, as it only uses one SPI instead of needing to learn/use two SPIs. Not a huge deal, but good to know.
  • Both URLs have modifiable params for tab id and client id.
  • It seems like both approaches can be used for ‘continuing’ an authentication

What I don’t know

  • How does an authenticator interact with a session? What’s the expiry time of an actionURL?
  • What are the other pro/cons of these two approaches?

Can anyone offer some guidance or experience here?