#942 Add the SignedOutCallbackRedirect event for OIDC

This commit is contained in:
Chris Ross (ASP.NET) 2017-09-21 12:28:24 -07:00
parent 31dd4ebd9c
commit 13fdbac48f
5 changed files with 643 additions and 583 deletions

View File

@ -38,6 +38,11 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// </summary>
public Func<RedirectContext, Task> OnRedirectToIdentityProviderForSignOut { get; set; } = context => Task.CompletedTask;
/// <summary>
/// Invoked before redirecting to the <see cref="OpenIdConnectOptions.SignedOutRedirectUri"/> at the end of a remote sign-out flow.
/// </summary>
public Func<RemoteSignOutContext, Task> OnSignedOutCallbackRedirect { get; set; } = context => Task.CompletedTask;
/// <summary>
/// Invoked when a request is received on the RemoteSignOutPath.
/// </summary>
@ -68,6 +73,8 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
public virtual Task RedirectToIdentityProviderForSignOut(RedirectContext context) => OnRedirectToIdentityProviderForSignOut(context);
public virtual Task SignedOutCallbackRedirect(RemoteSignOutContext context) => OnSignedOutCallbackRedirect(context);
public virtual Task RemoteSignOut(RemoteSignOutContext context) => OnRemoteSignOut(context);
public virtual Task TokenResponseReceived(TokenResponseReceivedContext context) => OnTokenResponseReceived(context);

View File

@ -9,6 +9,8 @@ namespace Microsoft.Extensions.Logging
{
private static Action<ILogger, Exception> _redirectToIdentityProviderForSignOutHandledResponse;
private static Action<ILogger, Exception> _redirectToIdentityProviderHandledResponse;
private static Action<ILogger, Exception> _signoutCallbackRedirectHandledResponse;
private static Action<ILogger, Exception> _signoutCallbackRedirectSkipped;
private static Action<ILogger, Exception> _updatingConfiguration;
private static Action<ILogger, Exception> _receivedIdToken;
private static Action<ILogger, Exception> _redeemingCodeForTokens;
@ -248,6 +250,14 @@ namespace Microsoft.Extensions.Logging
eventId: 49,
logLevel: LogLevel.Information,
formatString: "AuthenticationScheme: {AuthenticationScheme} signed out.");
_signoutCallbackRedirectHandledResponse = LoggerMessage.Define(
eventId: 50,
logLevel: LogLevel.Debug,
formatString: "RedirectToSignedOutRedirectUri.HandledResponse");
_signoutCallbackRedirectSkipped = LoggerMessage.Define(
eventId: 51,
logLevel: LogLevel.Debug,
formatString: "RedirectToSignedOutRedirectUri.Skipped");
}
public static void UpdatingConfiguration(this ILogger logger)
@ -345,6 +355,16 @@ namespace Microsoft.Extensions.Logging
_redirectToIdentityProviderHandledResponse(logger, null);
}
public static void SignoutCallbackRedirectHandledResponse(this ILogger logger)
{
_signoutCallbackRedirectHandledResponse(logger, null);
}
public static void SignoutCallbackRedirectSkipped(this ILogger logger)
{
_signoutCallbackRedirectSkipped(logger, null);
}
public static void UserInformationReceivedHandledResponse(this ILogger logger)
{
_userInformationReceivedHandledResponse(logger, null);

View File

@ -122,6 +122,10 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
Logger.RemoteSignOutSkipped();
return false;
}
if (remoteSignOutContext.Result.Failure != null)
{
throw new InvalidOperationException("An error was returned from the RemoteSignOut event.", remoteSignOutContext.Result.Failure);
}
}
if (message == null)
@ -273,18 +277,46 @@ namespace Microsoft.AspNetCore.Authentication.OpenIdConnect
/// Response to the callback from OpenId provider after session ended.
/// </summary>
/// <returns>A task executing the callback procedure</returns>
protected virtual Task<bool> HandleSignOutCallbackAsync()
protected async virtual Task<bool> HandleSignOutCallbackAsync()
{
if (Request.Query.TryGetValue(OpenIdConnectParameterNames.State, out StringValues protectedState))
var message = new OpenIdConnectMessage(Request.Query.Select(pair => new KeyValuePair<string, string[]>(pair.Key, pair.Value)));
AuthenticationProperties properties = null;
if (!string.IsNullOrEmpty(message.State))
{
var properties = Options.StateDataFormat.Unprotect(protectedState);
if (!string.IsNullOrEmpty(properties?.RedirectUri))
properties = Options.StateDataFormat.Unprotect(message.State);
}
var signOut = new RemoteSignOutContext(Context, Scheme, Options, message)
{
Properties = properties,
};
await Events.SignedOutCallbackRedirect(signOut);
if (signOut.Result != null)
{
if (signOut.Result.Handled)
{
Response.Redirect(properties.RedirectUri);
Logger.SignoutCallbackRedirectHandledResponse();
return true;
}
if (signOut.Result.Skipped)
{
Logger.SignoutCallbackRedirectSkipped();
return false;
}
if (signOut.Result.Failure != null)
{
throw new InvalidOperationException("An error was returned from the SignedOutCallbackRedirect event.", signOut.Result.Failure);
}
}
return Task.FromResult(true);
properties = signOut.Properties;
if (!string.IsNullOrEmpty(properties?.RedirectUri))
{
Response.Redirect(properties.RedirectUri);
}
return true;
}
/// <summary>

View File

@ -93,6 +93,10 @@ namespace Microsoft.AspNetCore.Authentication
{
return false;
}
else if (errorContext.Result.Failure != null)
{
throw new InvalidOperationException("An error was returned from the RemoteFailure event.", errorContext.Result.Failure);
}
}
throw exception;