---
title: "OpenID Connect (OIDC) in ASP.NET Core: Guides and FAQ"
description: "What OpenID Connect (OIDC) and OAuth 2.0 are, and my guides to the ASP.NET Core side: state and nonce, missing claims, PAR, custom parameters and JwtBearer."
url: https://nestenius.se/openid-connect/
type: hub
lang: en
site: https://nestenius.se/
---

# OpenID Connect (OIDC) in ASP.NET Core: Guides and FAQ

I have written a lot about OpenID Connect on this blog, mostly about what happens inside ASP.NET Core when a user signs in. This page puts those posts in a sensible reading order and answers the questions I get most often. For the protocol itself, step by step, see my [OpenID Connect for Developers guide](https://tn-data.se/openid-connect/) on tn-data.se.

## What Is OpenID Connect (OIDC)?

**OpenID Connect**, or **OIDC**, is an identity layer on top of OAuth 2.0. It gives applications a standard way to sign users in through a separate identity provider, such as Duende IdentityServer, Microsoft Entra ID or Keycloak. After the login, the application gets an **ID token** that says who the user is, and usually an **access token** for calling APIs on the user's behalf.

In ASP.NET Core, the OpenID Connect handler does the client side for you: it redirects the user to the provider, receives the authorization code, swaps it for tokens over a back channel, and hands the user over to the cookie handler.

![The OpenID Connect authorization code flow: the browser is redirected to IdentityServer to log in, returns to the client application with an authorization code, and the client exchanges the code for tokens over the back channel.](https://nestenius.se/_astro/oidc-authorization-code-flow-browser-client-identity-server.BPWatnb-_Z1jFfP3.webp)

## OAuth 2.0 vs OpenID Connect

**OAuth 2.0** is about access: it lets an application get an access token to call an API, without handling the user's password. It does not tell the application who the user is. **OpenID Connect** builds on OAuth 2.0 and adds that part: the ID token, standard claims about the user, the UserInfo endpoint and a discovery document. In practice you use both together. OpenID Connect signs the user in, and the OAuth 2.0 access token protects your APIs.

The [guide on tn-data.se](https://tn-data.se/openid-connect/) covers the differences in more detail, together with the OAuth versions, the grants and the flows.

## What Goes Wrong in Practice

The protocol is the same everywhere, but most of the problems I see are in the client and the API. They come up in questions from developers, in my workshops and in client projects:

- **The login is a black box.** The OpenID Connect handler does many steps for you, so when the login fails, you don't know which step failed. Watching the traffic in Fiddler is often the fastest way to find out.
- **State and nonce are a mystery.** The `state` parameter protects the callback against cross-site request forgery, and in ASP.NET Core it also carries your encrypted `AuthenticationProperties`. The `nonce` ties the ID token to the login that asked for it, and it is kept in a cookie until the user comes back.
- **The browser blocks the login cookies.** The nonce cookie must survive the round trip to the provider. Over plain HTTP, or with the wrong `SameSite` setting, the browser drops them and the login fails.
- **Claims go missing on the way in.** The provider sends the claim in the ID token or from the UserInfo endpoint, and then the handler's claim actions and claim mapping drop it or rename it before it reaches your `User` object.
- **The ID token and the access token get mixed up.** The ID token is for your client application. The access token is for your API, and the API validates it with the JwtBearer handler.
- **Sensitive parameters travel in the URL.** A normal authorization request puts its parameters in the browser's address bar. Pushed Authorization Requests (PAR) send them over the back channel instead.
- **Tokens end up in the browser.** For single-page apps, I recommend the BFF pattern, so tokens stay on the server.

![How state and nonce are used in an OpenID Connect login: the client sends both to the identity provider, gets the state back on the redirect, and finds the nonce inside the ID token.](https://nestenius.se/_astro/openid-connect-state-nonce-flow-client-sts-id-token.D_Oo9Ijx_Z2cVRH3.webp)

If you use Duende IdentityServer as your provider, my [IdentityServer page](https://nestenius.se/identityserver/) covers the server side.

## Start Here

If OpenID Connect itself is new to you, read my [OpenID Connect for Developers guide](https://tn-data.se/openid-connect/) first. The posts below are much easier to follow when you know what tokens, scopes, claims and flows are.

### 1. Understand the login in ASP.NET Core

- [Demystifying OpenID Connect's State and Nonce Parameters in ASP.NET Core](https://nestenius.se/net/demystifying-openid-connects-state-and-nonce-parameters-in-asp-net-core/): what is inside these two parameters and what they protect against.
- [Debugging cookie problems in ASP.NET Core](https://nestenius.se/net/debugging-cookie-problems/): the cookies involved in an OpenID Connect login, and why the browser sometimes rejects them.
- [Exploring what is inside the ASP.NET Core cookies](https://nestenius.se/net/exploring-what-is-inside-the-asp-net-core-cookies/): what ends up in the authentication cookie after the login.
- [What's new in ASP.NET Core authentication in .NET 11](https://nestenius.se/net/whats-new-in-asp-net-core-authentication-in-net-11/): what changed in the cookie and OpenID Connect handlers and in Data Protection, based on .NET 11 RC2.

### 2. Get the claims you expect

- [Debugging OpenID Connect Claim Problems in ASP.NET Core](https://nestenius.se/net/missing-openid-connect-claims-in-asp-net-core/): the ID token, UserInfo, claim actions, claim mapping and the name and role claims.

### 3. Make the authorization request safer

- [Pushed Authorization Requests (PAR) in ASP.NET Core 9](https://nestenius.se/net/pushed-authorization-requests-par-in-asp-net-core-9/): what PAR is, why it makes sign-in safer, and how to use it with Duende IdentityServer.
- [AdditionalAuthorizationParameters in ASP.NET Core 9](https://nestenius.se/net/additionalauthorizationparameters-in-asp-net-core-9/): add custom parameters to the authorization request without workarounds, also with PAR.

### 4. Protect your APIs with access tokens

- [Troubleshooting JwtBearer authentication issues in ASP.NET Core](https://nestenius.se/net/troubleshooting-jwtbearer-authentication-problems-in-asp-net-core/): 401 or 403 from your API, and how to find out why.
- [Debugging JwtBearer Claim Problems in ASP.NET Core](https://nestenius.se/net/debugging-jwtbearer-claim-problems-in-asp-net-core/): missing or renamed claims in the access token on the API side.

### 5. Keep tokens out of the browser (BFF)

- [Implementing BFF Pattern in ASP.NET Core for SPAs](https://nestenius.se/net/implementing-bff-pattern-in-asp-net-core-for-spas/): why OpenID Connect tokens in a single-page app are a risk. Part 1 of a seven-part series.
- [BFF in ASP.NET Core #5 - Automatic Token Renewal](https://nestenius.se/net/bff-in-asp-net-core-5-automatic-token-renewal/): refresh tokens in a BFF, so users stay signed in.

## Frequently Asked Questions

### What does OIDC stand for?

OIDC is short for OpenID Connect. It is the identity layer on top of OAuth 2.0 that most modern sign-in solutions use, and the two names mean the same thing.

### What are the state and nonce parameters for?

The `state` parameter protects the callback from the identity provider against cross-site request forgery. The `nonce` ends up inside the ID token, so the client can check that the token was issued for its own login request and not injected by someone else. In ASP.NET Core, the OpenID Connect handler creates and checks both for you. My post [Demystifying OpenID Connect's State and Nonce Parameters](https://nestenius.se/net/demystifying-openid-connects-state-and-nonce-parameters-in-asp-net-core/) shows what is inside them.

### Why is a claim missing after an OpenID Connect login in ASP.NET Core?

First check that the provider sends it, in the ID token or from the UserInfo endpoint. If it does, the OpenID Connect handler is dropping or renaming it: by default its claim actions delete a list of protocol claims and keep only some, and claim mapping renames others. I go through each step in [Debugging OpenID Connect Claim Problems in ASP.NET Core](https://nestenius.se/net/missing-openid-connect-claims-in-asp-net-core/).

### What is Pushed Authorization Requests (PAR)?

PAR is an OAuth standard where the client sends the authorization parameters to the identity provider over a back-channel request first, and then redirects the browser with only a short reference. The parameters stay out of the URL and can't be changed on the way. ASP.NET Core 9 supports PAR in its OpenID Connect handler. See [Pushed Authorization Requests (PAR) in ASP.NET Core 9](https://nestenius.se/net/pushed-authorization-requests-par-in-asp-net-core-9/).

### How do I add custom parameters to the authorization request in ASP.NET Core?

From ASP.NET Core 9, add them to `AdditionalAuthorizationParameters` in the OpenID Connect options. Before that, you needed workarounds such as the `OnRedirectToIdentityProvider` event. See [AdditionalAuthorizationParameters in ASP.NET Core 9](https://nestenius.se/net/additionalauthorizationparameters-in-asp-net-core-9/).

### Should I learn OpenID Connect or IdentityServer first?

OpenID Connect. The protocol is the same whether your provider is IdentityServer, Entra ID or Keycloak, and once you know what goes over the wire, every provider gets easier. Then see my [IdentityServer page](https://nestenius.se/identityserver/).

## Want to Go Further?

For the protocol itself, start with my free [OpenID Connect for Developers guide](https://tn-data.se/openid-connect/) on tn-data.se.

[![Getting Started: OpenID Connect, a Dometrain course by Tore Nestenius](https://nestenius.se/_astro/getting-started-openid-connect-thumbnail.BKepI2R0_Z10O631.webp)](https://dometrain.com/course/getting-started-openid-connect/?ref=tore-nestenius) [![Getting Started: Authentication and Authorization in .NET, a Dometrain course by Tore Nestenius](https://nestenius.se/_astro/getting-started-authentication-and-authorization-in-dotnet-thumbnail.CZ0_PMy1_Z2lFmgK.webp)](https://dometrain.com/course/getting-started-authentication-and-authorization-in-dotnet/?ref=tore-nestenius)

My Dometrain course [Getting Started: OpenID Connect](https://dometrain.com/course/getting-started-openid-connect/?ref=tore-nestenius) covers OAuth 2 and OpenID Connect at the protocol level: tokens, signing, scopes, claims and the flows. It is not tied to .NET, so it works whatever language your applications use. For the ASP.NET Core side (the authentication middleware, cookies and authorization), see [Getting Started: Authentication and Authorization in .NET](https://dometrain.com/course/getting-started-authentication-and-authorization-in-dotnet/?ref=tore-nestenius).

If your team needs help with OpenID Connect in ASP.NET Core, you can [hire me](https://tn-data.se/consulting/#identity).

## About me

Hi, I'm Tore Nestenius, a consultant and trainer in Göteborg, Sweden. I specialize in authentication, identity and security in .NET, and help teams with software architecture and Azure. I have worked with .NET since 2002.

[![Microsoft Most Valuable Professional (MVP) badge](https://nestenius.se/_astro/microsoft-mvp-badge.BZMWQT9U_dBFrM.webp)](https://mvp.microsoft.com/en-US/mvp/profile/5150f7cb-54d8-48d8-a450-46b2b677d634)

[Read more about me →](https://nestenius.se/about/)

## My Dometrain courses

Video courses I have made for Dometrain, with hands-on demos in .NET.

[View course: Getting Started: OpenID Connect →](https://dometrain.com/course/getting-started-openid-connect/?ref=tore-nestenius)

[View course: Getting Started: Authentication and Authorization in .NET →](https://dometrain.com/course/getting-started-authentication-and-authorization-in-dotnet/?ref=tore-nestenius)

## Work with me

Need a hand with authentication, architecture or a hard .NET problem? I offer consulting, coaching and training for development teams.

[Learn more →](https://nestenius.se/services/)
