|
| 1 | +--- |
| 2 | +title: "ASP.NET Core OpenID Connect Handler Events" |
| 3 | +description: "ASP.NET Core's OpenID Connect handler events, what they are, and why you might want to use them." |
| 4 | +date: 2025-5-01 |
| 5 | +sidebar: |
| 6 | + order: 60 |
| 7 | + label: "OIDC Handler Events" |
| 8 | +--- |
| 9 | + |
| 10 | +The ASP.NET Core [OpenID Connect handler][handler] exposes events that a client can subscribe to intercept the OpenID |
| 11 | +Connect protocol flow. Understanding these events is important to understanding how to customize the OpenID Connect |
| 12 | +protocol flow from the client. We'll cover each of the events, what they are, and why you might want to subscribe to |
| 13 | +them. |
| 14 | + |
| 15 | +To use the `OpenIdConnectHandler` in your client applications, you will first need to install the |
| 16 | +`Microsoft.AspNetCore.Authentication.OpenIdConnect` NuGet package. |
| 17 | + |
| 18 | +```bash |
| 19 | +dotnet package add Microsoft.AspNetCore.Authentication.OpenIdConnect |
| 20 | +``` |
| 21 | + |
| 22 | +Followed by adding the `OpenIdConnectHandler` to your application. |
| 23 | + |
| 24 | +```csharp |
| 25 | +// Program.cs |
| 26 | +builder.Services.AddAuthentication(options => |
| 27 | + { |
| 28 | + options.DefaultScheme = "cookie"; |
| 29 | + options.DefaultChallengeScheme = "oidc"; |
| 30 | + options.DefaultSignOutScheme = "oidc"; |
| 31 | + }) |
| 32 | + .AddCookie("cookie", options => |
| 33 | + { |
| 34 | + options.Cookie.Name = "__Host-bff"; |
| 35 | + options.Cookie.SameSite = SameSiteMode.Strict; |
| 36 | + }) |
| 37 | + .AddOpenIdConnect("oidc", options => |
| 38 | + { |
| 39 | + options.Authority = "https://demo.duendesoftware.com"; |
| 40 | + options.ClientId = "interactive.confidential"; |
| 41 | + options.ClientSecret = "secret"; |
| 42 | + options.ResponseType = "code"; |
| 43 | + options.ResponseMode = "query"; |
| 44 | + |
| 45 | + options.GetClaimsFromUserInfoEndpoint = true; |
| 46 | + options.SaveTokens = true; |
| 47 | + options.MapInboundClaims = false; |
| 48 | + |
| 49 | + options.Scope.Clear(); |
| 50 | + options.Scope.Add("openid"); |
| 51 | + options.Scope.Add("profile"); |
| 52 | + options.Scope.Add("api"); |
| 53 | + options.Scope.Add("offline_access"); |
| 54 | + |
| 55 | + options.TokenValidationParameters.NameClaimType = "name"; |
| 56 | + options.TokenValidationParameters.RoleClaimType = "role"; |
| 57 | + |
| 58 | + }); |
| 59 | +``` |
| 60 | + |
| 61 | +From here you can use the `options.Events` property to subscribe to the events you want to use. Let's look at each of the events in more detail. |
| 62 | + |
| 63 | +## OpenID Connect Events |
| 64 | + |
| 65 | +All events either occur before a request is sent to the identity provider, or after a response is received from the |
| 66 | +identity provider. Understanding the direction of these events can help you determine when to subscribe to them. Let's call events coming from the identity provider **incoming** and events going to the identity provider **outgoing** for an easier understanding. |
| 67 | + |
| 68 | +| **Event Name** | **Usage** | |
| 69 | +|------------------------------------------|--------------| |
| 70 | +| `OnAuthenticationFailed` | **Incoming** | |
| 71 | +| `OnAuthorizationCodeReceived` | **Incoming** | |
| 72 | +| `OnMessageReceived` | **Incoming** | |
| 73 | +| `OnRedirectToIdentityProvider` | **Outgoing** | |
| 74 | +| `OnRedirectToIdentityProviderForSignOut` | **Outgoing** | |
| 75 | +| `OnSignedOutCallbackRedirect` | **Outgoing** | |
| 76 | +| `OnRemoteSignOut` | **Incoming** | |
| 77 | +| `OnTokenResponseReceived` | **Incoming** | |
| 78 | +| `OnTokenValidated` | **Incoming** | |
| 79 | +| `OnUserInformationReceived` | **Incoming** | |
| 80 | +| `OnPushAuthorization` (**.NET 9+ only**) | **Outgoing** | |
| 81 | + |
| 82 | +## Commonly Subscribed Events |
| 83 | + |
| 84 | +While there are many events available in the `OpenIdConnectEvents` class, only a few are commonly subscribed. We suggest you start with the most commonly subscribed events and then subscribe to the remaining events as needed. |
| 85 | + |
| 86 | +For ASP.NET Core developers, the most commonly subscribed events are: |
| 87 | + |
| 88 | +1. **`OnRedirectToIdentityProvider`**: Useful for customizing login requests (e.g., appending extra parameters). |
| 89 | +2. **`OnRedirectToIdentityProviderForSignOut`**: Often required to customize the behavior of sign-out requests. |
| 90 | +3. **`OnTokenValidated`**: Frequently used to customize the claims processing or validate custom claims included in the |
| 91 | + ID token. |
| 92 | +4. **`OnUserInformationReceived`**: Sometimes used to process additional user data retrieved from the UserInfo |
| 93 | + endpoint (if enabled). |
| 94 | + |
| 95 | +## Descriptions |
| 96 | + |
| 97 | +### OnAuthenticationFailed |
| 98 | + |
| 99 | +- **When called**: Triggered whenever an exception occurs during the authentication process. This event provides an |
| 100 | + opportunity to handle or log errors. |
| 101 | +- **How often**: Only called when an authentication error happens. |
| 102 | +- **Example use case**: Use this event to log detailed error messages or display a custom error page to the user instead |
| 103 | + of the default behavior. |
| 104 | +- **Commonly subscribed**: No, unless you need specific error-handling logic. |
| 105 | + |
| 106 | +### OnAuthorizationCodeReceived |
| 107 | + |
| 108 | +- **When called**: Invoked after an authorization code is received and before it is redeemed for tokens. |
| 109 | +- **How often**: Called once per successful authorization code flow request. |
| 110 | +- **Example use case**: Validate the authorization code or add extra functionality (e.g., logging or monitoring) when |
| 111 | + the code is received. |
| 112 | +- **Commonly subscribed**: Rarely, unless custom logic is required before token redemption. |
| 113 | + |
| 114 | +### OnMessageReceived |
| 115 | + |
| 116 | +- **When called**: Triggered when a protocol message (e.g., an authorization response, logout request) is first |
| 117 | + received. |
| 118 | +- **How often**: Called once per incoming protocol message. |
| 119 | +- **Example use case**: Inspect or modify protocol messages for debugging or to handle additional query parameters |
| 120 | + passed by the identity provider. |
| 121 | +- **Commonly subscribed**: No, unless advanced customization is needed. |
| 122 | + |
| 123 | +### OnRedirectToIdentityProvider |
| 124 | + |
| 125 | +- **When called**: Invoked when redirecting the user to the identity provider for authentication. You can modify the |
| 126 | + outgoing authentication request. |
| 127 | +- **How often**: Called once per user authentication attempt (e.g., a "login"). |
| 128 | +- **Example use case**: Add custom query parameters to the request or modify the state parameter. |
| 129 | +- **Commonly subscribed**: Yes—often used to customize the authentication request. |
| 130 | + |
| 131 | +### OnRedirectToIdentityProviderForSignOut |
| 132 | + |
| 133 | +- **When called**: Triggered before redirecting the user to the identity provider to start the sign-out process. |
| 134 | +- **How often**: Called once per user sign-out request. |
| 135 | +- **Example use case**: Modify the logout request, such as appending additional parameters. |
| 136 | +- **Commonly subscribed**: Yes, if signing out requires customization. |
| 137 | + |
| 138 | +### OnSignedOutCallbackRedirect |
| 139 | + |
| 140 | +- **When called**: Invoked after a remote sign-out is completed and before redirecting the user to the |
| 141 | + `SignedOutRedirectUri`. |
| 142 | +- **How often**: Called once per remote sign-out. |
| 143 | +- **Example use case**: Log or perform business logic after the remote sign-out. |
| 144 | +- **Commonly subscribed**: Rarely, unless additional behavior is needed. |
| 145 | + |
| 146 | +### OnRemoteSignOut |
| 147 | + |
| 148 | +- **When called**: Called when a remote sign-out request is received on the `RemoteSignOutPath` endpoint. |
| 149 | +- **How often**: Called once per incoming remote sign-out request. |
| 150 | +- **Example use case**: Perform cleanup tasks such as clearing local session data upon receiving a sign-out request from |
| 151 | + the identity provider. |
| 152 | +- **Commonly subscribed**: Rarely, but important in distributed or multi-tenant systems. |
| 153 | + |
| 154 | +### OnTokenResponseReceived |
| 155 | + |
| 156 | +- **When called**: Triggered after an authorization code exchange is completed and the token endpoint returns tokens. |
| 157 | +- **How often**: Called once per token request. |
| 158 | +- **Example use case**: Log or debug the token response, or inspect additional data included in the token response. |
| 159 | +- **Commonly subscribed**: No, unless debugging or inspection of tokens is required. |
| 160 | + |
| 161 | +### OnTokenValidated |
| 162 | + |
| 163 | +- **When called**: Invoked after the ID token has been validated and an `AuthenticationTicket` has been created. |
| 164 | +- **How often**: Called once per token validation process. |
| 165 | +- **Example use case**: Add or modify claims in the `ClaimsPrincipal` or validate custom claims included in the token. |
| 166 | +- **Commonly subscribed**: Yes—this is one of the most commonly used events for customizing claims. |
| 167 | + |
| 168 | +### OnUserInformationReceived |
| 169 | + |
| 170 | +- **When called**: Triggered when retrieving user information from the UserInfo endpoint (if |
| 171 | + `GetClaimsFromUserInfoEndpoint = true`). |
| 172 | +- **How often**: Called once per user information fetch (e.g., per login). |
| 173 | +- **Example use case**: Extend or modify user claims based on the additional information retrieved from the UserInfo |
| 174 | + endpoint. |
| 175 | +- **Commonly subscribed**: Sometimes, if extra claims processing is required. |
| 176 | + |
| 177 | +### OnPushAuthorization |
| 178 | + |
| 179 | +- **When called**: Invoked before sending authorization parameters using the Pushed Authorization Request (PAR) |
| 180 | + mechanism. |
| 181 | +- **How often**: Called once per outgoing PAR-based authorization request. |
| 182 | +- **Example use case**: Modify or log pushed authorization parameters. |
| 183 | +- **Commonly subscribed**: Rarely, as this is used mainly in advanced scenarios. |
| 184 | + |
| 185 | +[handler]: https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.openidconnect.openidconnecthandler?view=aspnetcore-9.0 |
0 commit comments