OpenID Connect vs OAuth 2.0
What's the difference, and which one your application actually needs
If you have spent any time researching authentication, you have run into both terms: OAuth 2.0 and OpenID Connect. They are often mentioned together, sometimes used interchangeably, and the relationship between them is one of the most common sources of confusion in this space.
This article clears it up — what each protocol actually does, the real difference between the tokens they issue, and concrete scenarios for when you need one, the other, or both.
A quick recap of OAuth 2.0
OAuth 2.0 is an authorization protocol. It lets an application access specific resources on your behalf, without ever seeing your credentials. The result of an OAuth flow is an access token — a credential that proves the app is allowed to call a given API with a given set of permissions.
If you want the full step-by-step walkthrough of how this works in practice, the previous article covers it using the "Login with Google" flow as an example. Here, we focus on what comes next.
What OpenID Connect actually adds
Here is the problem OAuth 2.0 alone does not solve: an access token tells an API what the bearer is allowed to do. It does not reliably tell the client application who the user is. Access tokens were never designed to be parsed or trusted by the client itself — they are meant for the resource server, in whatever format that server expects.
OpenID Connect (OIDC) is a thin identity layer built directly on top of OAuth 2.0. It standardizes the missing piece: a reliable, verifiable way for the client to learn who just authenticated. It does this by introducing a new artifact — the ID token — and a new endpoint, the UserInfo endpoint.
The ID token is always a JWT, always signed, and always contains a standardized set of claims about the authentication event itself: who the user is, when they authenticated, and which application the token was issued for.
{
"iss": "https://your-identity-server.com",
"sub": "123456",
"aud": "your-client-id",
"exp": 1717003600,
"iat": 1717000000,
"auth_time": 1717000000,
"name": "Jane Doe",
"email": "jane@example.com"
}
Because the format and the claims are standardized, any OIDC-compliant client library knows exactly how to read this token, regardless of which authorization server issued it. That consistency is the entire point of the standard.
ID token vs access token — the distinction that matters
This is the single most misunderstood part of the OAuth/OIDC relationship, and it trips up even experienced developers.
The access token answers the question "what is this bearer allowed to do?". It is meant for the resource server — your API — which uses it to decide whether to accept or reject the request. What the access token looks like internally is deliberately left open by the OAuth 2.0 specification: the standard only says a token must exist and must be accepted by the resource server, but says nothing about its structure or content. In practice, most modern authorization servers — including OpenIddict — issue access tokens as JWTs, because JWTs are self-contained and can be verified without a network call. But the spec would equally accept an opaque random string, as long as the resource server knows how to validate it.
The ID token answers the question "who just authenticated, and when?". Unlike the access token, it is meant for the client application — the app that initiated the login — not for an API. And unlike the access token, its format is precisely defined by the OpenID Connect specification: an ID token is always a JWT, always signed, and must always contain a specific set of claims. The sub claim uniquely identifies the user, iss identifies the authorization server that issued it, aud identifies the client it was issued for, and iat/exp define when it was issued and when it expires. This standardization is not a minor detail — it means any OIDC-compliant client library, regardless of language or framework, knows exactly how to read and validate an ID token issued by any OIDC-compliant server. That interoperability is the core value of the standard. — it should never be sent to an API as a Bearer token.
⚠️ A common mistake
Using the ID token to call an API instead of the access token is a frequent error. The ID token was issued for the client to consume, often with a narrow audience restriction that an API was never meant to validate against. Always use the access token for API calls, and keep the ID token for establishing the local session.
There is also the UserInfo endpoint, which exists for cases where the ID token alone is not enough — for example, when the client needs additional profile data that was not included in the token to keep it small. The client calls this endpoint with the access token and receives the requested claims as a JSON response.
When you need only OAuth 2.0
Plain OAuth 2.0, without the OIDC layer, is the right fit whenever there is no human user involved in the exchange, or when the client does not need to know anything about identity — only about permissions.
- Machine-to-machine communication — a backend service calling another backend service, authenticated via the Client Credentials flow.
- Background jobs and scheduled tasks — a process that needs to call an API on its own behalf, with no user context at all.
- Third-party API access — granting an application access to a specific resource (like a calendar or a file store) without needing to establish "who is logged in" on the client side.
In all of these cases, an access token is all you need. Adding an identity layer would be unnecessary overhead.
When you need OpenID Connect
OIDC is the right choice whenever your application needs to know who the user is — not just what they are allowed to do.
- User login — any "Sign in with..." flow, where the application needs a name, an email, or a stable user identifier.
- Single Sign-On (SSO) — establishing a session across multiple applications that all trust the same identity provider.
- Personalized applications — anywhere the UI changes based on who is logged in, not just on what API calls succeed.
In practice, most real-world applications end up using both at once: OIDC to authenticate the user and establish identity, OAuth 2.0 access tokens to call APIs on the user's behalf afterward. They are not competing protocols — OIDC simply extends OAuth 2.0 with the piece it was missing.
Quick decision summary
Ask yourself one question: does my application need to know who the user is, or only what they can access?
- Only "what they can access" → OAuth 2.0 is enough.
- "Who they are" matters → you need OpenID Connect on top of OAuth 2.0.
- Both a login experience and API access → you need both, working together — which is what almost every modern identity server, including OpenIddict-based ones, gives you by default.
Both, out of the box
IdentitySuite is built on OpenIddict, which is certified for both OAuth 2.0 and OpenID Connect. Whether your application needs plain access tokens for machine-to-machine calls, full OIDC login flows, or both at the same time, the same authorization server handles it — with secure defaults and no protocol-level code to write.
About IdentitySuite
IdentitySuite simplifies enterprise authentication for .NET developers. Built on proven technologies like ASP.NET Core Identity and Openiddict, we eliminate the complexity of OAuth 2.0 and OpenID Connect implementation while maintaining enterprise-grade security standards.