Authentication And Authorization¶
Authentication and authorization answer different questions. Keeping them separate prevents a valid identity from being mistaken for unlimited access.
Authentication: Who Are You?¶
Authentication establishes a principal. A browser session authenticates a
user through an opaque cookie backed by server-side state. The resulting
principal records the browser_session authentication mechanism. An HTTP
Bearer credential can carry an OAuth2 access token; after token and persisted
session validation, the resulting user or client principal records the
oauth2_bearer mechanism. Bearer is the credential transport, while OAuth2 is
the protocol that issued and governs the access token. OAuth2 client
authentication establishes the client, not a browser user.
Both mechanisms resolve to explicit canonical principal contexts. Browser
sessions, OAuth2 users, and OAuth2 clients each keep their own immutable context
type behind small shared protocols. The shared protocol exposes identity and
the authentication mechanism, but no session credential. Only a browser
principal carries its opaque raw_session_id; only OAuth2 principals carry an
internal oauth2_session_id. Session and OAuth2 code produce these
authentication facts; authorization dependencies then evaluate them without
mixing browser-only, client-only, and user-only fields. The shared contexts and
mechanism-composing dependencies live in app/security/; each authentication
feature remains responsible for resolving its own session or token state.
Passwords, session cookies, authorization codes, access tokens, refresh tokens, ID tokens, and single-use email tokens are different artifacts. They must not be accepted interchangeably.
Authorization: What May You Do?¶
Authorization happens after authentication. It evaluates the authenticated principal against the requested action and resource.
- A role groups responsibilities such as administrator or operator.
- A permission names an application action such as
users:read. - An OAuth2 scope limits what a client may do with a token.
- Ownership asks whether the principal controls a specific resource.
- An organization boundary limits which organization's resources are visible.
An organization administrator operates inside one organization. An operator is
a global control-plane role and may act across organizations through the
dedicated /api/v1/server/* surface.
A scope is not automatically an application permission. A resource server must
map token scopes and principal context to an explicit access decision. In the
canonical Zero Auth Lite API, that mapping is intentionally direct and readable:
API permission names such as users:read are also exposed as OAuth2 scope
names. A bearer principal receives the intersection of its role-derived
permissions and granted scopes. Browser-session principals are authorized from
their current server-side roles and are not restricted by OAuth2 scopes.
The profile:write scope covers ordinary profile fields only. Changing a
password or deleting the current identity requires a browser session and its
CSRF proof, so a Bearer token cannot exercise those sensitive operations.
Current-organization administration intentionally uses the coarse
organization:read and organization:write scopes across organization
metadata, users, and OAuth2 sessions. Those scopes constrain an
organization-admin token; they do not confer the organization-admin role. The
server API for server operators keeps the resource-specific organizations:*,
users:*, sessions:write, and oauth2_clients:* scopes for server-wide
control-plane actions.
Where Decisions Live¶
Zero Auth Lite provides authenticated user and principal contexts. The application owns resource-specific authorization policy because only the application knows the meaning of its resources, roles, and organization relationships.
FastAPI dependencies enforce the complete HTTP authorization contract: roles, application permissions, OAuth2 scopes, and CSRF proof where applicable. Actor-bound services repeat the required role check and enforce target-specific rules such as organization membership, ownership, and lifecycle invariants. They intentionally do not reinterpret transport permissions or bearer scopes; those decisions belong to the route boundary. This split keeps direct service calls safe without maintaining two subtly different permission policies.
Common Mistakes¶
- Treating possession of an authorization code as user authentication.
- Treating an ID token as an API access token.
- Assuming a valid signature proves a token is still active.
- Using an internal database ID as an unreviewed public identifier.
- Checking a role but ignoring organization or resource ownership.
- Calling OAuth2 an authentication protocol without explaining the OIDC layer.
Continue with sessions and CSRF, OAuth2 flows, or OpenID Connect.