protected override async Task ApplyResponseChallengeAsync() { var context = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode); if (context == null || Response.StatusCode != 401) { return; } Response.StatusCode = 200; // Note: always return the error/error_description/error_uri/realm/scope specified // in the authentication properties even if IncludeErrorDetails is set to false. var notification = new ApplyChallengeContext(Context, Options, context.Properties) { Error = context.Properties.GetProperty(OAuthIntrospectionConstants.Properties.Error), ErrorDescription = context.Properties.GetProperty(OAuthIntrospectionConstants.Properties.ErrorDescription), ErrorUri = context.Properties.GetProperty(OAuthIntrospectionConstants.Properties.ErrorUri), Realm = context.Properties.GetProperty(OAuthIntrospectionConstants.Properties.Realm), Scope = context.Properties.GetProperty(OAuthIntrospectionConstants.Properties.Scope), }; // If an error was stored by HandleAuthenticateAsync, // add the corresponding details to the notification. var error = Context.Get <OAuthIntrospectionError>(typeof(OAuthIntrospectionError).FullName); if (error != null && Options.IncludeErrorDetails) { // If no error was specified in the authentication properties, // try to use the error returned from HandleAuthenticateAsync. if (string.IsNullOrEmpty(notification.Error)) { notification.Error = error.Error; } // If no error_description was specified in the authentication properties, // try to use the error_description returned from AuthenticateCoreAsync. if (string.IsNullOrEmpty(notification.ErrorDescription)) { notification.ErrorDescription = error.ErrorDescription; } // If no error_uri was specified in the authentication properties, // try to use the error_uri returned from AuthenticateCoreAsync. if (string.IsNullOrEmpty(notification.ErrorUri)) { notification.ErrorUri = error.ErrorUri; } // If no realm was specified in the authentication properties, // try to use the realm returned from AuthenticateCoreAsync. if (string.IsNullOrEmpty(notification.Realm)) { notification.Realm = error.Realm; } // If no scope was specified in the authentication properties, // try to use the scope returned from AuthenticateCoreAsync. if (string.IsNullOrEmpty(notification.Scope)) { notification.Scope = error.Scope; } } // At this stage, if no realm was provided, try to // fallback to the realm registered in the options. if (string.IsNullOrEmpty(notification.Realm)) { notification.Realm = Options.Realm; } await Options.Events.ApplyChallenge(notification); if (notification.Handled) { return; } Response.StatusCode = 401; // Optimization: avoid allocating a StringBuilder if the // WWW-Authenticate header doesn't contain any parameter. if (string.IsNullOrEmpty(notification.Realm) && string.IsNullOrEmpty(notification.Error) && string.IsNullOrEmpty(notification.ErrorDescription) && string.IsNullOrEmpty(notification.ErrorUri) && string.IsNullOrEmpty(notification.Scope)) { Response.Headers.Append(OAuthIntrospectionConstants.Headers.WWWAuthenticate, OAuthIntrospectionConstants.Schemes.Bearer); } else { var builder = new StringBuilder(OAuthIntrospectionConstants.Schemes.Bearer); // Append the realm if one was specified. if (!string.IsNullOrEmpty(notification.Realm)) { builder.Append(' '); builder.Append(OAuthIntrospectionConstants.Parameters.Realm); builder.Append("=\""); builder.Append(notification.Realm); builder.Append('"'); } // Append the error if one was specified. if (!string.IsNullOrEmpty(notification.Error)) { if (!string.IsNullOrEmpty(notification.Realm)) { builder.Append(','); } builder.Append(' '); builder.Append(OAuthIntrospectionConstants.Parameters.Error); builder.Append("=\""); builder.Append(notification.Error); builder.Append('"'); } // Append the error_description if one was specified. if (!string.IsNullOrEmpty(notification.ErrorDescription)) { if (!string.IsNullOrEmpty(notification.Realm) || !string.IsNullOrEmpty(notification.Error)) { builder.Append(','); } builder.Append(' '); builder.Append(OAuthIntrospectionConstants.Parameters.ErrorDescription); builder.Append("=\""); builder.Append(notification.ErrorDescription); builder.Append('"'); } // Append the error_uri if one was specified. if (!string.IsNullOrEmpty(notification.ErrorUri)) { if (!string.IsNullOrEmpty(notification.Realm) || !string.IsNullOrEmpty(notification.Error) || !string.IsNullOrEmpty(notification.ErrorDescription)) { builder.Append(','); } builder.Append(' '); builder.Append(OAuthIntrospectionConstants.Parameters.ErrorUri); builder.Append("=\""); builder.Append(notification.ErrorUri); builder.Append('"'); } // Append the scope if one was specified. if (!string.IsNullOrEmpty(notification.Scope)) { if (!string.IsNullOrEmpty(notification.Realm) || !string.IsNullOrEmpty(notification.Error) || !string.IsNullOrEmpty(notification.ErrorDescription) || !string.IsNullOrEmpty(notification.ErrorUri)) { builder.Append(','); } builder.Append(' '); builder.Append(OAuthIntrospectionConstants.Parameters.Scope); builder.Append("=\""); builder.Append(notification.Scope); builder.Append('"'); } Response.Headers.Append(OAuthIntrospectionConstants.Headers.WWWAuthenticate, builder.ToString()); } }
/// <summary> /// Invoked when a challenge response is returned to the caller. /// </summary> public virtual Task ApplyChallenge(ApplyChallengeContext context) => OnApplyChallenge(context);