Designing OAuth2 scopes

Esta publicación aún no está disponible en tu idioma. Mostrando la versión en inglés.

security

Designing OAuth2 scopes

Why `user:read` isn't enough, and how to scope tokens without painting yourself into a corner.

Alexandre Awadallak2 min read

Scopes are the access-control language of your API. Get them right and third-party integrations feel natural. Get them wrong and you're forever explaining to customers why the Slack bot can also delete their billing history.

The read/write split is the minimum#

At minimum, split every resource into read:* and write:*. read:cases lets an integration list cases; write:cases lets it mutate them. This covers 80% of real-world needs without over-engineering.

Resource-first naming#

{verb}:{resource} scales better than flat names. read:billing is clear; billing_read_only is not. Clients see a list of scopes on the consent screen and need to understand what they're granting at a glance.

Granular scopes are a trap#

It's tempting to ship read:cases.priority, write:cases.status, write:cases.comments. Developers building against your API hate this. They'll request everything, always. Offer coarse scopes by default, introduce fine-grained ones only when a customer has a real reason.

Admin-style scopes#

Some operations — transferring org ownership, deleting accounts — should require explicit admin scopes (admin:org). Never bundle admin actions under a regular write:* scope; a compromised integration shouldn't be able to delete the account that installed it.

Scope inheritance#

admin:* should imply write:* which implies read:*. Keep the hierarchy simple. Resist the urge to invent a DAG.

Document the minimum#

For each API endpoint, document the exact scopes required. An SDK that surfaces this to the developer ("this call requires write:billing") saves hours of consent-screen iteration.