API keys, application passwords and OAuth: how each CMS lets something else in
There are three ways a content system lets outside software in, and they are not equally good. An API key or token is a secret that stands for an account. An application password is a secret made for one application, listed separately and revocable on its own. OAuth sends you to your own site to approve the thing, and binds what it may do to what you may do. The third is clearly the best and almost nobody offers it: of 11 platforms we have built for, one does.
·
This matters more than it sounds, because whatever you paste into a product is the whole of your protection. A credential you cannot see, cannot scope and cannot revoke on its own is a credential you have to trust somebody about.
The three mechanisms, and what each one proves
The useful question about any credential is not how long it is. It is: what does holding it prove, and what happens when you want it back?
- A token or API key. A string that stands for an account or a project. Usually shown once. Usually revocable, though sometimes only by deleting and replacing it. Often scoped — Strapi's tokens can be limited to certain collections, Craft's are issued against a schema that decides exactly what they may read and change, Sanity's have levels and the lowest that can write is Editor. A scoped token is a genuinely good answer. An unscoped one that stands for an administrator is the weakest thing on this list.
- An application password. WordPress's answer, and the best of the secret-based ones. It is a separate credential made for one application, it appears in your own profile with the name you gave it, it works only for the REST API, and deleting it changes nothing about how you log in. Everything you would want from a key, with the two parts keys usually miss: you can see it in a list, and you can take back one without touching the others.
- OAuth, done properly. You are sent to your own site, you sign in there, you see what is being asked for, and you press approve. The software never sees a password of yours, and the access it gets is bound to you — your permissions are its permissions, and you can withdraw it from your own dashboard. This is the arrangement our own connector uses on the other side, for exactly the same reasons, which is a reasonable argument that we believe it.
What each platform asks you for
This table is read from each adapter's own connection form, so it is what you will actually be asked to paste. The second column is the one that tells you something: a platform that needs to know *who you are* as well as what the secret is usually has the better arrangement behind it.
| Platform | What it asks you to paste | And who you are |
|---|---|---|
| WordPress | Application password | Your WordPress username |
| Joomla | Joomla API token | No |
| Drupal | That account's password | The Drupal username |
| Craft CMS | Craft GraphQL token | No |
| Concrete CMS | Client Secret | Client ID |
| Ghost | Admin API key | No |
| Webflow | Webflow API token | No |
| Wix | Wix API key | Your Wix site ID |
| Contentful | Content management token | No |
| Strapi | Strapi API token | No |
| Sanity | Sanity API token | No |
Read from each adapter's own connection form, so this table and the form you actually fill in cannot disagree.
The best of them, and why
Concrete CMS, and it is not close — which is a surprising sentence to write about the platform that allows the fewest jobs on our whole list. Concrete connects by sending you to your own site to approve an integration, and the resulting access is bound to your account. No password leaves your hands, and you revoke it from your own dashboard rather than asking us to.
There is a lesson in how we found that out. Concrete also offers the credential-style connection that every other platform here uses, and it works — the token is issued, signed and reads the site perfectly. Every write then fails, because Concrete attaches permissions to a person and that kind of token has no person on it. The arrangement we would have chosen for convenience was the one that could not work, and the arrangement that works is the one we would have chosen on principle. WordPress is second with its application passwords, and after that it is a field of keys that differ mainly in whether they can be scoped.
Three arrangements to be careful with
Not criticism of the platforms — each of these is a reasonable decision by somebody with different constraints. But each one asks something of you that the others do not.
- Drupal's basic authentication uses a real account password. There is no application-password equivalent in core, so the credential is an account's actual login. The only safe way to use it is to make an account for the job, with a role that may edit content and nothing more, which is what our setup page says in the step before you are asked for it.
- A Wix key reaches every site on the account. It is made at account level, and which site a request lands on is decided by the request rather than by the key. That has a direct consequence we built around: a Wix key proves nothing about owning any particular site, so a Wix site is verified like any other website, with a file or a meta tag. Webflow's token reaches exactly one site, which is why that one needs no separate proof. Two hosted platforms, opposite answers, and the difference is in what the credential proves.
- A Wix key's permissions cannot be changed after it is made, and a Contentful token can be made in a state that works nowhere useful. Wix: tick the wrong boxes and the remedy is a new key. Contentful: a personal management token has to be authorised against your organisation afterwards, and until it is, it can see your account and none of your spaces — which looks exactly like a wrong token.
What happens to it after you paste it
Worth saying plainly, since the whole post is about not having to trust anybody. Every credential is encrypted, and each one is tied to the website it belongs to — so a stored secret copied from one website's record to another's fails to decrypt rather than quietly authorising the wrong site. The key that does the encrypting lives outside the web root and is never in the code. Nothing is ever written to a log: not a credential, not an authorisation header, not the body of a token request. And when you disconnect a site, the stored secret goes with it, which is the easy half — the important half is that you can also revoke it at the other end, in your own platform, without asking us anything.
Honest limit: a credential we hold is still a credential somebody else holds, however it is encrypted, and the only arrangement that avoids that entirely is the Concrete-style one where you approve access on your own site. Of 11 platforms, one offers it. We would rather name that as the gap it is than describe encryption as though it were the same thing.
Questions we get asked about this
- Which is safer, an API key or OAuth?
- OAuth, clearly: no password leaves your hands, the access is bound to your own permissions, and you withdraw it from your own dashboard. A scoped API key is a reasonable second. An unscoped administrator key is the one to avoid.
- Is an application password the same as my WordPress password?
- No, and that is the point of it. It is a separate credential, made for one application, that works only for the REST API. Deleting it changes nothing about how you log in, and it never reveals your actual password.
- What if I want to take access away right now?
- Do it at your end, in your own platform: delete the application password, revoke the token, or remove the integration. That works whatever we do, which is exactly why it is the better answer than asking us.