Skip to content

AT Protocol OAuth

OAuth is the account authorization system for AT Protocol clients. It lets an app obtain permission to call a user’s Personal Data Server (PDS) without asking for the user’s password.

The unusual part is not OAuth itself. The unusual part is where OAuth runs. AT Protocol has many PDS hosts and can use separate authorization servers, sometimes called entryways. A client therefore begins by discovering authority. It cannot hard-code one login domain and call the result authentication.

A client needs three facts before it can make authorized XRPC calls:

  1. which account it is acting for;
  2. which PDS currently hosts that account;
  3. which permissions the user granted.

In AT Protocol, the stable account identifier is the DID. Handles help humans find accounts, but handles can change. PDS hosts can also change. OAuth has to respect that portability rather than smuggle in a central account database.

The result is a profile of OAuth that does two jobs:

  • it authorizes access to PDS resources;
  • it authenticates the AT Protocol account DID for login-style use cases.

OAuth 2.0 by itself is mostly an authorization framework. AT Protocol adds DID verification to make it usable for account authentication.1

OAuth termAT Protocol termRole
Resource ownerUserControls the account.
ClientApp or serviceRequests permission to act for the user.
Resource serverPDSAccepts authorized XRPC requests.
Authorization serverPDS or entrywayAuthenticates the user and issues tokens.

A small PDS can be both resource server and authorization server. A larger service may put authorization in a separate entryway that serves many PDS instances.

AT Protocol does not use generic OAuth with optional pieces chosen at runtime. It specifies a profile:

  • Authorization Code flow only;
  • PKCE with S256;
  • Pushed Authorization Requests (PAR);
  • DPoP-bound access tokens;
  • server-issued DPoP nonces;
  • client metadata discovered from the client_id URL;
  • required atproto scope;
  • required sub verification against the account DID.

These choices follow the direction of OAuth 2.1 and OAuth security best current practice: avoid the implicit flow, avoid password-style grants, and do not pretend public clients can keep shared secrets.23

The flow is correct only if these statements hold at the end:

BindingQuestion
Account bindingDid the token response name the DID the client expected?
Server bindingIs the authorization-server issuer authoritative for that DID’s current PDS?
Token bindingAre the tokens bound to the DPoP key for this client instance?

This invariant explains most of the protocol’s ceremony. PAR protects the authorization request. PKCE protects the code exchange. DPoP protects token use. DID and issuer checks protect account authentication.

  1. Clients and Metadata
  2. Identity and Discovery
  3. Authorization Flow
  4. Tokens and Security
  1. Bluesky/AT Protocol. “OAuth”.

  2. IETF OAuth Working Group. “The OAuth 2.1 Authorization Framework”.

  3. Lodderstedt, Torsten, et al. RFC 9700: Best Current Practice for OAuth 2.0 Security.