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?
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.
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!
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ā¦
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.