|
|
|
@ -6,13 +6,10 @@ |
|
|
|
|
|
|
|
using System; |
|
|
|
using System.IO; |
|
|
|
using System.Linq; |
|
|
|
using System.Security.Claims; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using AspNet.Security.OpenIdConnect.Extensions; |
|
|
|
using AspNet.Security.OpenIdConnect.Server; |
|
|
|
using JetBrains.Annotations; |
|
|
|
using Microsoft.AspNetCore.Builder; |
|
|
|
using Microsoft.AspNetCore.Diagnostics; |
|
|
|
using Microsoft.AspNetCore.WebUtilities; |
|
|
|
using Microsoft.Extensions.Caching.Distributed; |
|
|
|
@ -91,60 +88,6 @@ namespace OpenIddict.Infrastructure { |
|
|
|
public override async Task HandleLogoutRequest([NotNull] HandleLogoutRequestContext context) { |
|
|
|
var services = context.HttpContext.RequestServices.GetRequiredService<OpenIddictServices<TUser, TApplication, TAuthorization, TScope, TToken>>(); |
|
|
|
|
|
|
|
// Only validate the id_token_hint if the user is still logged in.
|
|
|
|
// If the authentication cookie doesn't exist or is no longer valid,
|
|
|
|
// the user agent is immediately redirected to the client application.
|
|
|
|
if (!context.HttpContext.User.Identities.Any(identity => identity.IsAuthenticated)) { |
|
|
|
services.Logger.LogDebug("The logout request was silently processed without requiring user confirmation " + |
|
|
|
"because the user was not authenticated or his session was no longer valid."); |
|
|
|
|
|
|
|
// Redirect the user agent back to the client application.
|
|
|
|
await context.HttpContext.Authentication.SignOutAsync(context.Options.AuthenticationScheme); |
|
|
|
|
|
|
|
// Mark the response as handled
|
|
|
|
// to skip the rest of the pipeline.
|
|
|
|
context.HandleResponse(); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// At this stage, ensure the authentication cookie contains the required ClaimTypes.NameIdentifier claim.
|
|
|
|
// If it cannot be found, don't handle the logout request at this stage and continue to the next middleware.
|
|
|
|
var identifier = context.HttpContext.User.GetClaim(ClaimTypes.NameIdentifier); |
|
|
|
if (!string.IsNullOrEmpty(identifier)) { |
|
|
|
// When the client application sends an id_token_hint parameter, the corresponding identity can be retrieved using
|
|
|
|
// AuthenticateAsync and used as a way to determine whether the logout request has been sent by a legit caller.
|
|
|
|
// If the token cannot be extracted, don't handle the logout request at this stage and continue to the next middleware.
|
|
|
|
var principal = await context.HttpContext.Authentication.AuthenticateAsync(context.Options.AuthenticationScheme); |
|
|
|
if (principal != null && principal.HasClaim(ClaimTypes.NameIdentifier, identifier)) { |
|
|
|
services.Logger.LogInformation("The user '{Username}' was successfully logged out without requiring confirmation.", |
|
|
|
services.Users.GetUserName(principal)); |
|
|
|
|
|
|
|
// Delete the ASP.NET Core Identity cookies.
|
|
|
|
await services.SignIn.SignOutAsync(); |
|
|
|
|
|
|
|
// Redirect the user agent back to the client application.
|
|
|
|
await context.HttpContext.Authentication.SignOutAsync(context.Options.AuthenticationScheme); |
|
|
|
|
|
|
|
// Mark the response as handled
|
|
|
|
// to skip the rest of the pipeline.
|
|
|
|
context.HandleResponse(); |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
services.Logger.LogInformation("The logout request was not silently processed because " + |
|
|
|
"the id_token_hint parameter was missing or invalid or " + |
|
|
|
"didn't correspond to the logged in user."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
services.Logger.LogWarning("The logout request was not silently processed because the mandatory " + |
|
|
|
"ClaimTypes.NameIdentifier claim was missing from the current principal."); |
|
|
|
} |
|
|
|
|
|
|
|
// If no request_id parameter can be found in the current request, assume the OpenID Connect
|
|
|
|
// request was not serialized yet and store the entire payload in the distributed cache
|
|
|
|
// to make it easier to flow across requests and internal/external logout workflows.
|
|
|
|
|