The rule that decides most of it
If the action returns per-user data or changes anything, the user must be authenticated individually. A shared API key gives every user of the GPT the access of whoever holds that key — which is rarely what anyone intended.
Authentication is where GPT Actions projects either become defensible or become an audit finding. This covers the options, when each is appropriate, and the mistakes worth avoiding.
The options
| Method | Appropriate for | Not appropriate for |
|---|---|---|
| None | Genuinely public data | Anything internal |
| API key | Read-only, non-personal, low sensitivity | Per-user data; any write |
| OAuth | Per-user data, writes, anything sensitive | Nothing — it is the default answer |
The shared-key failure mode is worth stating plainly. If your action authenticates with one key that has broad access, then any user of the GPT can retrieve anything that key can reach — regardless of what their own role permits. The assistant becomes a way around your access control rather than a client of it.
What OAuth gives you that a key does not
- Per-user identity, so your existing permissions apply unchanged.
- Scoped consent — the user sees and approves what is being granted.
- Individual revocation without affecting anyone else.
- Expiry, limiting the value of a leaked token.
- Attribution in logs — a real person, not a service account.
Attribution alone justifies the extra effort. An audit log full of entries from "integration-user" answers no question anyone will actually ask.
Designing the API behind the action
Authentication proves who is asking. The API design determines what they can reach:
- Expose narrow operations — "get order status by ID", not "query orders".
- Validate every parameter. Assume inputs may be malformed or adversarial.
- Apply the user's permissions server-side, never relying on the caller to filter.
- Return only needed fields. Whole-record responses leak data nobody asked for.
- Rate limit per user to contain loops and bulk extraction.
- Log the request, the identity and what was returned.
- Fail closed — if authorisation is unclear, refuse.
Write the operation list before writing any code. If you can enumerate every operation on one page and justify each, the security conversation is short. If the list says "flexible query endpoint", it will not be.
Mistakes that recur
| Mistake | Consequence |
|---|---|
| Shared key for per-user data | Access control bypass |
| Permissions enforced only in the schema description | No enforcement at all |
| Returning full records | Data disclosure beyond the use case |
| No rate limiting | Runaway loops; bulk extraction unnoticed |
| Secrets in the action schema | Exposure |
| No logging | Cannot answer "what was accessed" |
| Write operations without confirmation | Irreversible actions from an ambiguous request |
Writes need more than authentication
- Explicit confirmation before anything consequential happens.
- Idempotency so a retry does not create a second record.
- An audit entry recording who approved what.
- Reversibility where possible, or a clear reason it is not.
- Value limits where amounts are involved, with escalation above them.
Content returned by an action must never authorise a further action. If a retrieved record contains text instructing the assistant to do something, following it would mean an attacker who can write into your data can drive your API. Authority comes from the authenticated user's request, never from returned data.
A rollout that survives review
- OAuth from the start — retrofitting it is worse than building it.
- Read-only first, with full logging.
- A small user group until usage patterns are understood.
- Review the logs, particularly denied requests.
- Add writes individually, each with confirmation and audit.
Building GPT Actions against internal systems? Tell us what needs connecting. See our ChatGPT plugin service, the custom GPT guide, and MCP security practices.