OAuth 2.0 and RBAC: Building Secure Multi-Role Authentication for SaaS
Authentication is solved. Authorization is where teams get hurt.
Most SaaS products bolt on Auth0 or Firebase Auth and call it done. Then six months later they're debugging why a team member can delete billing data, why a viewer-role user can invite new members, or why a tenant's admin can see another tenant's records. These aren't edge cases — they're what happens when you treat authorization as an afterthought.
This guide covers OAuth 2.0 as your authentication layer, RBAC (role-based access control) as your authorization strategy, and where ABAC (attribute-based access control) makes sense as you scale.
OAuth 2.0: What It Actually Does
OAuth 2.0 is an authorization framework, not an authentication protocol. It defines how a user delegates limited access to a third party without sharing credentials. In SaaS, you use it for:
Social login (Sign in with Google/GitHub) — OAuth 2.0 + OpenID Connect (OIDC)
Third-party integrations — letting your app act on behalf of users in other services
Machine-to-machine auth — service accounts, API keys, and backend-to-backend calls
For user authentication specifically, OIDC builds on OAuth 2.0 by adding an id_token (JWT) containing user identity claims alongside the access token.
The OAuth 2.0 Authorization Code Flow
User initiates login User clicks "Log in with Google." App redirects to Google's authorization server with client_id, scope, redirect_uri, and state.
User authenticates and consents Google authenticates the user and shows a consent screen.
Authorization code returned Google redirects back to redirect_uri with an authorization code.
Token exchange (server-side) App exchanges the code for access_token + id_token server-side. Never expose this exchange to the client.
Token verification App verifies the id_token signature against Google's public keys (JWKS endpoint).
User record created/updated App upserts the local user record from the verified claims.
The state parameter is critical — always verify it on callback to prevent CSRF attacks.
OAuth 2.0 Authorization Code Flow: state parameter prevents CSRF; token exchange must always happen server-side.
RBAC: Role-Based Access Control Fundamentals
RBAC assigns permissions to roles, and roles to users. Rather than granting user A permission to do X directly, you define a role that has permission X, then assign that role to user A.
Core Concepts
Permission: A specific allowed action (e.g., projects:delete, billing:read).
Role: A named collection of permissions (e.g., admin, editor, viewer).
Role Assignment: The link between a user and a role, scoped to a workspace or resource.
Designing Your Role Hierarchy
Role
Typical Permissions
Owner
All permissions including billing and team management
Admin
All except billing and ownership transfer
Member/Editor
Create, read, update within their scope
Viewer
Read-only access
Billing Admin
Billing-only, no product data
Start with 3–4 roles. Expand only when real customer use cases demand it. Most SaaS products never need more than 6 distinct roles.
Multi-Tenant RBAC: The Trap Most Teams Fall Into
In multi-tenant SaaS, roles are always scoped to a tenant. A user who is an admin in Workspace A should have zero elevated permissions in Workspace B.
The naive implementation stores roles in a single users table column. This breaks immediately in multi-tenant contexts. The correct approach:
-- User can have different roles in different workspaces
CREATE TABLE workspace_members (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
workspace_id UUID NOT NULL REFERENCES workspaces(id),
user_id UUID NOT NULL REFERENCES users(id),
role VARCHAR(50) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(workspace_id, user_id)
);
Every authorization check must include workspace_id as a filter, resolved from server-side context (subdomain, header, or JWT claim).
Multi-tenant RBAC: every role assignment is scoped to a workspace_id — never stored globally on the user record.
Implementing Permission Checks
Centralize permission logic rather than scattering role checks throughout your codebase.
RBAC breaks down when permissions depend on attributes beyond role — the resource's owner, the user's plan, the data classification level. ABAC (attribute-based access control) evaluates policy expressions against subject, resource, and environment attributes:
"A member can edit a project only if they created it" — resource ownership check
"Admins on free plan can't export more than 10MB" — subscription tier check
"API access only from allowlisted IPs" — environmental check
Libraries like Casbin and Open Policy Agent implement ABAC with declarative policy files. Introduce ABAC when you find yourself adding more than 2–3 custom conditions to your RBAC permission checks.
JWT Best Practices for SaaS Authentication
Short access token expiry: 15 minutes to 1 hour. Use refresh tokens for silent re-auth.
Include workspace context in claims: Put workspace_id and role in the JWT to avoid DB lookups on every request.
Refresh token rotation: Issue a new refresh token with every use. Limits blast radius of stolen tokens.
Use RS256: Asymmetric signing (private key signs, public key verifies). Never HS256 in multi-service environments.
Common Pitfalls and How to Avoid Them
Pitfall
Fix
Role stored globally, not per-workspace
Scope roles to workspace in the workspace_members table
Permission checks scattered in business logic
Centralize in middleware or a dedicated authz service
No audit log for permission changes
Log all role assignments with actor, timestamp, reason
Trust user-supplied workspace_id
Resolve workspace from server-side context only
No token revocation on logout
Use short expiry + refresh rotation or maintain a server-side blacklist
What is the difference between OAuth 2.0 and RBAC?
OAuth 2.0 handles authentication — verifying who the user is. RBAC handles authorization — determining what that user is allowed to do. They complement each other: OAuth gets you the verified identity, RBAC controls resource access based on that identity's role.
What is RBAC in SaaS applications?
RBAC (role-based access control) assigns permissions to roles (Admin, Member, Viewer) and assigns those roles to users within a workspace. It's simpler to manage than per-user permission grants and scales cleanly for most B2B SaaS use cases.
When should I use ABAC instead of RBAC?
Use ABAC when permission decisions depend on resource attributes beyond the user's role — such as resource ownership, subscription tier, data classification, or environmental factors like IP address. RBAC + ABAC together is the enterprise-grade standard.
How do I prevent cross-tenant data leaks in multi-tenant SaaS?
Scope all roles to a workspace or tenant in a dedicated membership table. Every database query must include the workspace_id resolved from server-side context — never from user-supplied input. Never store roles in a global user record.
Need an expert team to provide digital solutions for your business?