How long lived is ctx.currentUserAccessToken in plugin hooks?

Greetings and salutations! I’m interested in securely authenticating a request from my plugin frontend to my backend, and I think currentUserAccessToken may be a way to get there.

Before I go off sending it in plaintext in a request, I’m wondering how long lived that token is? If it were intercepted, would an attacker be able to use it forever?

Hi @frodi.karlsson, and welcome to the forum!

I’ll check with the devs about how long that token is valid for and let you know as soon as I have an answer.

Some thoughts on that:

  • Everything should be sent over HTTPS anyway, so hopefully there would not be MITM attacks to intercept it in the first place…?

  • The currentuserAccessToken is mainly useful for your plugin itself to make calls to our APIs, i.e. when you want the plugin to be able to use the CMA to retrieve or edit records that the plugin SDK doesn’t already give it access to. But if you’re using your plugin just to send a message to another external backend of your own, you don’t need to pass our token at all.

    Your backend can use any API token you like (that you can generate or rotate both in the DatoCMS UI or via API call). Then you can use any sort of auth system you like between your plugin and your backend, such as a JWT or a simple shared secret string.

    That way, you can help ensure that even if the message between your plugin and your backend is intercepted, the attacker couldn’t do anything useful with that unless they also have your Dato API keys (which would be separately and securely stored in your backend itself, and not sent over the wire between the plugin and your backend). Your actual API key would still need to be sent to us over the wire from your backend, of course, but again, that should also be HTTPS-protected.

  • You can further use our roles & permissions system to define fine-grained access permissions for each API key: Project collaborators, roles and permissions | Documentation


Is there a particular threat scenario or use case you’re concerned about? If your network messages are routinely subject to eavesdropping and decryption by third parties, I’d be very concerned about sending any sort of secret, even if they were extremely short-lived…

Most of our auth (not just the currentUserAccessToken, but also things like HTTP Authentication bearer tokens, cookies, or your username & password upon dashboard login) are sent ā€œas plaintextā€, but encrypted by HTTPS. That’s a pretty standard practice, as far as I understand? Are you unable to use HTTPS for some reason? Or is there some other auth system you’re looking for?


Regardless, I’ll let you know once I find out how long that token is valid for!

:smile: Yes, while that’s true, it’s nice to know the scope of potential vulnerability should the worst come to pass.

My problem there is that we’d have to expose our secret as client-facing code wherever we host the plugin frontend. Values passed in the ctx object are unique in that they don’t come from client code but from DatoCMS’s plugin frontend consumer, which is only accessible in authenticated contexts. From the values in ctx, currentUserAccessToken seems most reasonable to use, especially if it’s short-lived.

Am I missing something obvious perhaps? OAuth in the plugin interface might be a more conventional solution…

Yep, I’ll try to get you a solid answer on the validity period as soon as I find out!

Gotcha. That makes sense!

Nope, probably not! It’s always a tradeoff between ease of use and security, and in this instance we opted to keep things on the simpler side.

1 Like

@frodi.karlsson,

We dug around the code and it seems like the maximum period currentUserAccessToken can be valid for is 1 month from the time of issuance (which you can see by decoding the JWT; it’s the only timestamp in there). Certain events (user deletions, etc.) may invalidate it sooner than that, but left untouched, that’s how long it would normally be valid for.

Seems long, doesn’t it?

If you’re worried, another workaround might be to use a serverless function (a CF worker or Vercel Function or AWS Lambda, etc.) to act as a intermediary between the plugin and your backend. The API key would be in the serverless, as an env var or similar, and never exposed to the plugin or the user’s browser.

You’d need to implement some other way of authenticating the plugin, though, like implementing your own oauth flow between the serverless and your plugin, or whitelisting by IP/domain/referrer (less secure).

Or it might be safer to fetch another secret value saved in your project somewhere (like in the private plugin URL as a hashtag anchor value, or in a record somewhere). That can act as the ā€œencryption keyā€ of sorts… the plugin would receive that directly from the browser in-memory, use it as the secret to encrypt the currentUserAccessToken itself, and then send that to the backend (which would already know the shared secret from the project). That way the plugin code doesn’t know the secret, so an impersonator shouldn’t be be able to validate as you when trying to communicate with the backend.


But IMHO all of this might be over-designing things a bit? If you can’t trust the HTTPS connection between the user’s browser and your backend, presumably you’d have similar problems with the HTTPS connection between Dato and your user, or between the plugin and your user, anyway. Any of those could be MITMed and either trojaned with a malicious script or else simply have their credentials harvested in transit.

Doesn’t seem that helpful to me to over-protect the connection between the plugin and the backend to a greater extent to everything else in the flow… it’s a lot of work only to move the weakest link to elsewhere in the stack.

Alright, thanks a lot for checking. That definitely answers my question, and I appreciate the input.

I agree, it seems like over-engineering to not trust HTTPS and the access token should be fine to use as is.

1 Like