Cyber Security

SAML vs OAuth vs OIDC: The Identity Standards Every Engineer Confuses

If you have ever sat in a design review where someone said 'let's just use OAuth for login' and watched the security engineer's eye twitch — this article is for you. These three protocols are the plumbing behind almost every Sign-in-with button on the internet, and even experienced engineers reach for the wrong one.

Meritshot Editorial Team17 min read
SAMLOAuthOIDCIdentitySSOAuthenticationSecurity
Back to Blog

SAML vs OAuth vs OIDC: The Identity Standards Every Engineer Confuses

If you have ever sat in a design review where someone said "let's just use OAuth for login" and watched the security engineer's eye twitch — you already know this article is for you.

These three protocols are the plumbing behind almost every "Sign in with..." button on the internet, every enterprise SSO portal, every B2B integration. And yet, even engineers with five years of experience reach for the wrong one. They use OAuth where they need OIDC. They bolt SAML onto a mobile app and wonder why the UX is broken. They store ID tokens like access tokens and accidentally hand attackers a privilege escalation.

The confusion is not a knowledge gap. It is a category error. SAML, OAuth 2.0, and OIDC do not compete for the same job — but the documentation, vendor marketing, and Stack Overflow answers blur them into a single fuzzy concept called "auth stuff."

This article cuts through that fuzz. We will skip the textbook definitions and go straight into where each one breaks, where each one shines, and the architectural decisions that separate engineers who ship secure systems from those who quietly create attack surface.

SAML XML assertion flow diagram showing enterprise SSO authentication request and response

Why Engineers Keep Confusing These Three

The confusion has three real causes, and naming them helps:

  • Vendors collapsed the vocabulary. Auth0, Okta, AWS Cognito, and Azure AD all let you toggle between SAML and OIDC with a dropdown. That UX implies they are alternatives. They are not — they are tools for different jobs that happen to overlap in one use case (login).
  • OAuth got hijacked for authentication. OAuth 2.0 was designed for authorization — granting a third-party app limited access to your data. But because the flow involves a login screen at the provider, developers started using OAuth to verify identity. That misuse is exactly what OIDC was built to fix.
  • Job titles changed faster than mental models. A "full-stack engineer" in 2026 routinely owns identity flows that used to belong to a dedicated IAM team. The protocols did not get simpler — the surface area engineers are expected to cover got wider.

The fix is not memorizing specs. It is having a clean mental model for which question each protocol answers:

  • SAML answers: Who is this user, and what attributes do they have, according to their employer's identity provider?
  • OAuth 2.0 answers: Has this user granted my app permission to access their resources at another service?
  • OIDC answers: Who is this user, in a way my app can verify cryptographically, without me having to handle their password?

Once you internalize that, most architectural decisions become obvious. The rest of this article is about the parts that do not.


SAML in the Wild: Where It Still Dominates (and Where It Quietly Fails)

SAML is the protocol developers love to declare dead. They are wrong. SAML still runs the enterprise.

Walk into any Fortune 500 company and you will find SAML powering the Single Sign-On portal that connects 200+ internal SaaS tools to the corporate identity provider — typically Okta, Azure AD, or Ping Identity. When a new hire joins, IT provisions their accounts in those SaaS apps via SAML's user attribute assertions. When they leave, deactivating one account in the IdP kills all 200 sessions.

Real scenario: the B2B SaaS contract clause

Here is where SAML hits practitioners directly. Imagine your startup just landed a contract with a 40,000-person bank. You are celebrating, then their procurement team sends the security questionnaire. Buried on page 7: "Application must support SAML 2.0 SSO with our enterprise IdP. SCIM provisioning required."

This is the moment every SaaS engineer learns SAML the hard way. The bank will not — cannot — use your "Sign in with Google" button. Their compliance posture requires that every login flow through their identity provider so they can enforce conditional access, log every authentication event for SOX audits, and revoke access centrally.

If your app does not speak SAML, you do not close the deal. It is that binary.

What goes right with SAML

  • Enterprise procurement loves it. SAML support is a checkbox on every enterprise security questionnaire. Having it unlocks deals you literally cannot win otherwise.
  • Rich attribute assertions. A SAML response can carry dozens of user attributes — department, employee ID, cost center, manager email — in a single signed XML blob. This is why HR-integrated apps still prefer SAML.
  • Centralized session control. IT can kill an employee's access to every SAML-connected app from one console. For compliance, this is non-negotiable.

What goes wrong with SAML

  • It is XML, and the signatures are brittle. XML Signature Wrapping attacks were a real class of exploit. The spec is so flexible that misconfigured validators have been bypassed by manipulating which <Assertion> element actually gets validated versus the one that gets read for user identity.
  • Mobile and SPA UX is painful. SAML assumes a browser with cookies and HTTP redirects. Building a SAML flow into a native mobile app means opening a system browser, parsing redirects, and stitching the response back into your app. It works, but it is not a good experience.
  • IdP-initiated SSO is a security minefield. If your app accepts unsolicited SAML responses (where the IdP, not your app, starts the flow), you are vulnerable to login CSRF and response replay unless you are very careful with InResponseTo validation. Many implementations get this wrong.
  • Debugging is hostile. When a SAML integration breaks, you are staring at base64-encoded, signed, possibly encrypted XML. Every IdP serializes attributes differently. The error messages are useless.

When to reach for SAML

You reach for SAML when your customers are large enterprises whose IT teams have a non-negotiable requirement. You do not reach for SAML for a new consumer app, a mobile-first product, or anything where your users are not centrally managed by an IT department.

OAuth 2.0 authorization code flow showing token exchange between client and resource server

OAuth 2.0: Not What You Think It Is

The single biggest source of identity bugs in production systems is engineers using OAuth 2.0 for authentication. OAuth 2.0 is not an authentication protocol. It was never designed to be one. The original RFC (6749) is explicit about this.

OAuth 2.0 is a delegated authorization framework. It lets a user grant a third-party application limited, scoped, time-bound access to resources at another service — without giving that application their password.

Real scenario: the Zapier integration

Picture this concrete use case: a user wants Zapier to read new rows from their Google Sheets and create Trello cards. Zapier needs access to Google Sheets on behalf of the user. This is exactly what OAuth 2.0 was designed for.

The user clicks "Connect Google" in Zapier. They are redirected to Google's authorization server. Google shows a consent screen: "Zapier wants to access your Google Sheets — read only." The user clicks Allow. Google issues Zapier an access token scoped to sheets.readonly. Zapier stores it and uses it for API calls.

Notice what just happened — and what did not:

  • Zapier never saw the user's Google password.
  • Zapier got a token, not credentials.
  • The token is scoped (sheets, read-only) and expires.
  • Zapier did not learn the user's identity. The access token is opaque — it is not meant to tell Zapier who the user is. It just lets Zapier do things on their behalf.

That last point is where engineers go wrong. They see the OAuth flow, see that the user "logged in" with Google, and assume they now know the user. They then extract the user's email from some user-info endpoint and treat it as proof of identity. This is the bug. The access token does not prove identity — it proves authorization. The fact that you can use it to fetch a user's profile is a side effect, not a guarantee.

What goes right with OAuth 2.0

  • Granular scopes. You can ask for exactly the permissions you need (gmail.send, drive.file, calendar.events.readonly) and nothing more. Users see exactly what they are granting.
  • No password sharing. Third-party apps never see the user's credentials at the provider. This is OAuth's foundational win.
  • Token rotation and revocation. Refresh tokens let you maintain access without keeping the user clicking through consent screens. Revocation kills access without changing the password.
  • Machine-to-machine flows. The Client Credentials grant gives you OAuth for service-to-service auth — your backend authenticating to a payment API, for example.

What goes wrong with OAuth 2.0

  • The Implicit grant is dead, but still implemented. For years, SPAs used the Implicit flow, which returned tokens directly in the URL fragment. It has been deprecated since 2019 in favor of Authorization Code with PKCE. Yet old codebases still ship with it, exposing tokens to browser history, referer headers, and any script on the page.
  • Redirect URI validation is the number-one vulnerability source. Loose redirect matching (*.yourdomain.com, or substring matching) lets attackers steal authorization codes by registering subdomains or open redirects. The fix is exact-match registration. The implementation is often sloppy.
  • Phishing via OAuth consent. Attackers register malicious apps with names like "Microsoft Office Security" and trick users into granting them broad scopes. The user sees a real Microsoft consent screen, so they trust it. The granted permissions are real. This is now one of the dominant phishing vectors against M365 and Google Workspace tenants.
  • OAuth for authentication. Already covered. Do not do it. Use OIDC.

The grant types you actually need to know

  • Authorization Code + PKCE: Default for any user-facing app — web, mobile, SPA. If you are not using this, you should be.
  • Client Credentials: Machine-to-machine. Your backend calling another backend. No user involved.
  • Refresh Token: Used alongside Authorization Code to refresh access without re-prompting the user.
  • Device Code: For input-constrained devices (smart TVs, CLI tools). The flow where you see "Visit example.com/device and enter code ABCD-1234."

The Implicit grant and Resource Owner Password Credentials grant exist. Pretend they do not. Both are deprecated for security reasons in OAuth 2.1.

OIDC identity token showing user claims returned by OpenID Connect provider

OIDC: The Standard You Are Already Using Without Knowing It

Every time you have clicked "Sign in with Google" and ended up logged into a website, you have used OpenID Connect. Not OAuth. OIDC.

OIDC is a thin authentication layer built on top of OAuth 2.0. It standardizes the thing OAuth deliberately left out: a verifiable way to learn who the user is. It does this by introducing a second token, the ID token, which is a JWT containing claims about the user's identity, signed by the identity provider.

Real scenario: the SaaS that almost shipped a security disaster

Here is a scenario that plays out somewhere every quarter. A startup is building a SaaS product. They want "Sign in with Google" to keep onboarding friction low. The junior engineer wires up Google OAuth, gets an access token, and writes code that:

  1. Calls Google's userinfo endpoint with the access token.
  2. Receives a JSON response with email, name, sub.
  3. Looks up the user in their database by email. If found, logs them in. If not, creates an account.

This ships to staging. Three months later, a security review flags it.

The bug: the access token does not prove the user is the one logging in. If an attacker can steal any Google access token issued to your app — through a leaky log, a misconfigured browser extension, a compromised dependency — they can hit your /api/auth/callback endpoint and impersonate any user. The userinfo endpoint will faithfully return their identity.

The OIDC fix: instead of trusting an access token to identify a user, you validate an ID token that was issued for your specific application. The ID token contains an aud (audience) claim that must match your client ID, an iss (issuer) claim you verify, a nonce you generated to prevent replay, and a signature you verify against the provider's published keys. An attacker with a leaked access token cannot forge a valid ID token, because they do not have Google's signing key.

This distinction — access token versus ID token, authorization versus authentication — is the single most important thing to understand about modern identity.

What goes right with OIDC

  • Standardized identity claims. Every OIDC provider returns the same well-defined claims (sub, email, email_verified, name, picture). Switching providers is mostly a config change.
  • JWT-based, self-contained. ID tokens are JWTs you can validate offline using the provider's public keys. No need to call back to the provider for every request.
  • Discovery via well-known endpoints. Every OIDC provider exposes /.well-known/openid-configuration, listing all their endpoints, supported scopes, and key URLs. Libraries auto-configure from this.
  • Works for both SSO and federation. OIDC handles both "log in to my app" and "log in to my app using another company's identity" with the same protocol.

What goes wrong with OIDC

  • Engineers skip signature validation. They decode the JWT (which is just base64), trust the claims, and skip the cryptographic verification. The JWT spec lets you do this. Real production code does this. It is catastrophic.
  • Nonce and state get conflated. state protects against CSRF on the authorization request. nonce protects against ID token replay. They are different things, do different jobs, and both must be validated. Many tutorials get this wrong.
  • email is treated as identity. Users can change their email at most providers. The stable identifier is sub (subject) — a provider-specific user ID. Apps that key user records on email break when users update their email, or worse, get account-takeover issues when an email is recycled.
  • The email_verified claim gets ignored. If a provider returns email_verified: false, the user has not proven they own that email. Logging them in by email anyway is how account takeover happens at organizations that mix self-signup and SSO.

The mental model that makes OIDC click

If you remember one thing: the access token is for APIs, the ID token is for you (the application). The access token is a bearer credential you send to a resource server. The ID token is a signed statement of identity you keep in your own backend, validate once, and use to establish a session.

Send the access token to APIs. Do not send the ID token to APIs. Do not accept access tokens as proof of identity. This single discipline prevents most identity bugs.

Security engineer building identity federation between SAML identity provider and OAuth client

The Decision Framework: Which One, When

After the previous three sections, the decision tree becomes much smaller. Here is the practical guide:

  • Building a consumer app with social login? OIDC. Always OIDC. Google, Apple, Facebook, GitHub — all of them implement OIDC (or OIDC-like flows).
  • Selling B2B SaaS to enterprises? Both SAML and OIDC. SAML for the Fortune 500 procurement gate. OIDC for the modern customers and your own product login. Most successful SaaS products support both.
  • Building a third-party integration that needs API access? OAuth 2.0 with Authorization Code + PKCE. You need scoped access tokens, not identity.
  • Service-to-service authentication inside your infrastructure? OAuth 2.0 Client Credentials, or mTLS, or signed JWTs (a different topic). Not SAML. Not OIDC.
  • Smart TV / CLI / device authentication? OAuth 2.0 Device Code flow. Nothing else handles this well.

The migration pattern: SAML to OIDC

A pattern emerging across the industry: enterprises modernizing their identity stack are moving from SAML to OIDC where they can. Microsoft, Google, and Okta all push OIDC as the default for new integrations. SAML support is maintained for legacy SaaS but no longer the recommended path.

If you are greenfielding, start with OIDC. Add SAML when a customer demands it. The reverse migration (OIDC-only product trying to add SAML mid-enterprise-sales-cycle) is painful and slow.


The Gotchas That Bite in Production

A few hard-won lessons that do not fit cleanly into the previous sections:

  • Logout is harder than login. SAML has Single Logout (SLO), which is famously unreliable across IdPs. OIDC has front-channel and back-channel logout, both of which require careful implementation. Most apps just kill the local session and pray. Real enterprise customers will flag this in security reviews.
  • Token storage in browsers is unsolved. localStorage is vulnerable to XSS. httpOnly cookies are vulnerable to CSRF without strict SameSite. The current best practice is backend-for-frontend (BFF) pattern: keep tokens server-side, hand the browser a session cookie. SPAs that store tokens client-side are a step behind.
  • Refresh token rotation is not optional. A leaked refresh token is a long-lived bearer credential. Rotation (issuing a new refresh token with every use and revoking the old one on reuse detection) limits the blast radius. Modern IdPs do this by default. Older code often does not.
  • Clock skew breaks JWT validation. ID tokens have iat, nbf, and exp claims, all validated against the current time. A server with a clock off by 10 minutes will reject valid tokens or accept expired ones. NTP is not optional.
  • The acr and amr claims exist for a reason. If your app needs to know whether the user authenticated with MFA versus password-only, those claims tell you. Most apps ignore them and just trust that "logged in" means "fully authenticated." That assumption breaks under step-up auth requirements.

Enterprise identity infrastructure showing the three protocol layers in a production system

Where This Knowledge Stops Being Enough

Understanding SAML, OAuth 2.0, and OIDC is one piece of a much larger system. Once you have internalized the distinctions, the questions that come next are the ones that actually decide whether your authentication architecture survives contact with real users, attackers, and auditors:

  • How do you design a session layer that handles step-up authentication, MFA challenges, and risk-based re-authentication without rebuilding your entire login flow?
  • How do you build a tenant-aware multi-IdP architecture for B2B SaaS — where every enterprise customer brings their own SAML or OIDC provider, and your product has to federate them all into a consistent permissions model?
  • How do attackers actually exploit identity systems in the wild — OAuth phishing campaigns, golden SAML attacks against compromised IdPs, refresh token theft chains — and how do defenders detect them?

Those are the questions practitioners hit on day three of any real identity project, and they are exactly the ground covered in Meritshot's Cyber Security and Full Stack Development programmes. The curriculum does not stop at protocol diagrams — it walks learners through live case studies of real breaches, hands-on labs where you build and break SSO integrations, and mentorship from engineers who have shipped identity systems at scale. If you have reached the end of this article and you are now curious about how the pieces actually fit together in production — that is the conversation Meritshot is built to continue. Explore the Cyber Security programme at Meritshot and take the next step from protocol literacy to production-ready security engineering.

Recommended