FR

Full Stack · 3 min read

Verified Experience Pattern

Designing Authentication with OAuth 2.0, OIDC and RBAC

How authentication, identity, and authorization fit together — and why conflating them is where most access-control bugs come from.

OAuth 2.0OIDCJWTRBAC
User
Identity ProviderOIDC
APIJWT verification
RBAC Policy Check

OAuth 2.0, OIDC, and RBAC solve three different problems that are easy to conflate: delegated authorization, identity, and access control. Treating them as one problem is where a lot of access-control bugs come from.

OAuth 2.0: delegated authorization

OAuth 2.0 answers "can this client act on behalf of this user for these specific permissions (scopes)?" It was designed for delegation — letting a third-party application access a user's resources without handing over their password — not for authenticating the user to your own application by itself.

OIDC: identity on top of OAuth

OpenID Connect adds an identity layer on top of OAuth 2.0: an ID token (a JWT) that asserts who the user is, issued by a trusted identity provider. This is what actually answers "who is this user," and it's the piece that's often missing when a system uses "OAuth" for login but has no real identity assertion — just an access token with no verified claim about who it belongs to.

JWTs: a transport format, not a security model by itself

A JWT is a signed (and optionally encrypted) container for claims. Using JWTs for session or access tokens is a reasonable implementation choice, but a JWT's signature only proves the token wasn't tampered with after issuance — it says nothing about whether the permissions inside it are still valid. Short expiry times and a real revocation strategy (e.g. a refresh-token rotation scheme) matter more than the token format itself.

RBAC: authorization, decided separately from identity

Once a request is authenticated and you know who the user is, role-based access control answers "what is this user allowed to do." Keeping this as an explicit, centrally enforced policy check — rather than scattering if (user.role === 'admin') checks through the codebase — is what makes access control auditable and consistent across REST and GraphQL surfaces alike.

A design that holds up

  1. Authenticate via OIDC against a trusted identity provider — don't roll your own password/session handling if you can avoid it.
  2. Issue short-lived JWTs for API access, with a refresh mechanism that can be revoked.
  3. Enforce RBAC centrally, at the API/service boundary, as policy — not as inline conditionals scattered across handlers.
  4. Log authorization decisions, not just authentication events, so an access-control incident can be reconstructed after the fact.

This layered approach — OIDC for identity, JWTs for transport, RBAC for policy — is the authentication and authorization model used across the Distributed SaaS Platform system.