/// <summary> /// Handles the remote callback asynchronous. /// </summary> /// <returns></returns> protected virtual async Task <bool> HandleRemoteCallbackAsync() { var ticket = await this.AuthenticateAsync().ConfigureAwait(false); if (ticket == null) { var errorContext = new RemoteFailureContext( this.Context, this.Scheme, this.Options, new Exception("Invalid return state, unable to redirect.")); await this.Options.Events.RemoteFailure(errorContext).ConfigureAwait(false); if (errorContext.Result.Handled) { return(true); } if (errorContext.Result.Skipped) { return(false); } this.Context.Response.StatusCode = 500; return(true); } return(true); }
private static Task HandleOnRemoteFailure(RemoteFailureContext context) { context.Response.Redirect(context.Properties.RedirectUri); context.HandleResponse(); return(Task.FromResult(0)); }
private async Task AddMicrosoftIdentityWebApp_TestB2cSpecificSetup(IServiceCollection services, Func <RemoteFailureContext, Task> remoteFailureFuncMock) { var provider = services.BuildServiceProvider(); var oidcOptions = provider.GetRequiredService <IOptionsFactory <OpenIdConnectOptions> >().Create(OidcScheme); // Assert B2C name claim type Assert.Equal(ClaimConstants.Name, oidcOptions.TokenValidationParameters.NameClaimType); var(httpContext, authScheme, authProperties) = CreateContextParameters(provider); authProperties.Items[OidcConstants.PolicyKey] = TestConstants.B2CEditProfileUserFlow; var redirectContext = new RedirectContext(httpContext, authScheme, oidcOptions, authProperties) { ProtocolMessage = new OpenIdConnectMessage() { IssuerAddress = $"IssuerAddress/{TestConstants.B2CSignUpSignInUserFlow}/" }, }; (httpContext, authScheme, authProperties) = CreateContextParameters(provider); var remoteFailureContext = new RemoteFailureContext(httpContext, authScheme, new RemoteAuthenticationOptions(), new Exception()); await oidcOptions.Events.RedirectToIdentityProvider(redirectContext).ConfigureAwait(false); await oidcOptions.Events.RemoteFailure(remoteFailureContext).ConfigureAwait(false); await remoteFailureFuncMock.ReceivedWithAnyArgs().Invoke(Arg.Any <RemoteFailureContext>()).ConfigureAwait(false); // Assert issuer is updated to non-default user flow Assert.Contains(TestConstants.B2CEditProfileUserFlow, redirectContext.ProtocolMessage.IssuerAddress); Assert.NotNull(redirectContext.ProtocolMessage.Parameters[ClaimConstants.ClientInfo]); Assert.Equal(Constants.One, redirectContext.ProtocolMessage.Parameters[ClaimConstants.ClientInfo].ToString(CultureInfo.InvariantCulture)); }
private static Task HandleRemoteLoginFailure(RemoteFailureContext ctx) { ctx.HttpContext.Items["ErrorMessage"] = ctx.Failure.Message; ctx.Response.Redirect("/Account/Login"); ctx.HandleResponse(); return(Task.CompletedTask); }
/// <summary> /// Returns whether the specified failure context indicates that request correlation for XSRF failed. /// </summary> /// <param name="context">The current failure context.</param> /// <returns> /// <see langword="true"/> if request correlation failed; otherwise <see langword="false"/>. /// </returns> private static bool IsCorrelationFailure(RemoteFailureContext context) { // See https://github.com/aspnet/Security/blob/ad425163b29b1e09a41e84423b0dcbac797c9164/src/Microsoft.AspNetCore.Authentication.OAuth/OAuthHandler.cs#L66 // and https://github.com/aspnet/Security/blob/2d1c56ce5ccfc15c78dd49cee772f6be473f3ee2/src/Microsoft.AspNetCore.Authentication/RemoteAuthenticationHandler.cs#L203 // This effectively means that the user did not pass their cookies along correctly to correlate the request. return(string.Equals(context.Failure.Message, "Correlation failed.", StringComparison.Ordinal)); }
public static async Task Handle_Denied_Permissions(string query, string expected) { // Arrange var httpContext = new DefaultHttpContext(); var request = new DefaultHttpRequest(httpContext) { QueryString = new QueryString(query) }; var scheme = new AuthenticationScheme("amazon-auth", "Amazon", typeof(AmazonAuthenticationHandler)); var options = new RemoteAuthenticationOptions(); var failure = new InvalidOperationException(); var context = new RemoteFailureContext(httpContext, scheme, options, failure); var provider = Guid.NewGuid().ToString(); var secureDataFormat = Mock.Of <ISecureDataFormat <object> >(); var logger = Mock.Of <ILogger>(); // Act await OAuthEventsHandler.HandleRemoteFailure(context, provider, secureDataFormat, logger, PropertiesProvider); // Assert httpContext.Response.GetTypedHeaders().Location.OriginalString.ShouldBe(expected); }
public async Task OnRemoteError_HandlesResponseWhenUserCancelsFlowFromTheAzureADB2CUserInterface() { // Arrange var handlers = new AzureADB2COpenIDConnectEventHandlers( AzureADB2CDefaults.AuthenticationScheme, new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); var remoteFailureContext = new RemoteFailureContext( new DefaultHttpContext(), new AuthenticationScheme( AzureADB2CDefaults.AuthenticationScheme, displayName: null, handlerType: typeof(OpenIdConnectHandler)), new OpenIdConnectOptions(), new OpenIdConnectProtocolException("access_denied")); // Act await handlers.OnRemoteFailure(remoteFailureContext); // Assert Assert.Equal(StatusCodes.Status302Found, remoteFailureContext.Response.StatusCode); Assert.Equal("/", remoteFailureContext.Response.Headers.Location); Assert.True(remoteFailureContext.Result.Handled); }
public async Task OnRemoteError_HandlesResponseWhenTryingToResetPasswordFromTheLoginPage() { // Arrange var handlers = new AzureADB2COpenIDConnectEventHandlers( AzureADB2CDefaults.AuthenticationScheme, new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); var remoteFailureContext = new RemoteFailureContext( new DefaultHttpContext(), new AuthenticationScheme( AzureADB2CDefaults.AuthenticationScheme, displayName: null, handlerType: typeof(OpenIdConnectHandler)), new OpenIdConnectOptions(), new OpenIdConnectProtocolException("AADB2C90118")); // Act await handlers.OnRemoteFailure(remoteFailureContext); // Assert Assert.Equal(StatusCodes.Status302Found, remoteFailureContext.Response.StatusCode); Assert.Equal("/AzureADB2C/Account/ResetPassword/AzureADB2C", remoteFailureContext.Response.Headers.Location); Assert.True(remoteFailureContext.Result.Handled); }
public async Task OnRemoteError_HandlesResponseWhenErrorIsUnknown() { // Arrange var handlers = new AzureADB2COpenIDConnectEventHandlers( AzureADB2CDefaults.AuthenticationScheme, new AzureADB2COptions() { SignUpSignInPolicyId = "B2C_1_SiUpIn" }); var remoteFailureContext = new RemoteFailureContext( new DefaultHttpContext(), new AuthenticationScheme( AzureADB2CDefaults.AuthenticationScheme, displayName: null, handlerType: typeof(OpenIdConnectHandler)), new OpenIdConnectOptions(), new OpenIdConnectProtocolException("some_other_error")); // Act await handlers.OnRemoteFailure(remoteFailureContext); // Assert Assert.Equal(StatusCodes.Status302Found, remoteFailureContext.Response.StatusCode); Assert.Equal("/AzureADB2C/Account/Error", remoteFailureContext.Response.Headers[HeaderNames.Location]); Assert.True(remoteFailureContext.Result.Handled); }
public static async Task HandleOnRemoteFailure(RemoteFailureContext context) { context.Response.StatusCode = 500; context.Response.ContentType = "text/html"; await context.Response.WriteAsync("<html><body>"); await context.Response.WriteAsync("A remote failure has occurred: " + UrlEncoder.Default.Encode(context.Failure.Message) + "<br>"); /* unkown issue * if (context.Properties != null) * { * await context.Response.WriteAsync("Properties:<br>"); * foreach (var pair in context.Properties.Items) * { * await context.Response.WriteAsync($"-{ UrlEncoder.Default.Encode(pair.Key)}={ UrlEncoder.Default.Encode(pair.Value)}<br>"); * } * }*/ await context.Response.WriteAsync("<a href=\"/\">Home</a>"); await context.Response.WriteAsync("</body></html>"); // context.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(context.Failure.Message)); context.HandleResponse(); }
private async Task HandleOnRemoteFailure(RemoteFailureContext context) { context.Response.StatusCode = 500; context.Response.ContentType = "text/html"; await context.Response.WriteAsync("<html><head><link rel='preconnect' href='https://fonts.gstatic.com'><link href='https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap' rel ='stylesheet'><link rel='stylesheet' href='css/bootstrap.min.css'/><link rel='stylesheet' href='css/style.css'/></head><body><div class='login-wrapper'><div class='container'><div class='logo-wrapper'><img class='logo-img' src='image/logo.png' alt='' /></div>"); await context.Response.WriteAsync("<div><div class='login-form mb-4' style=height:50% !important;><h4>You have denied the application permissions.<br> Please try again.</h4><br>"); //await context.Response.WriteAsync("A remote failure has occurred: <br>" + // context.Failure.Message.Split(Environment.NewLine).Select(s => HtmlEncoder.Default.Encode(s) + "<br>").Aggregate((s1, s2) => s1 + s2)); //if (context.Properties != null) //{ // await context.Response.WriteAsync("Properties:<br>"); // foreach (var pair in context.Properties.Items) // { // await context.Response.WriteAsync($"-{ HtmlEncoder.Default.Encode(pair.Key)}={ HtmlEncoder.Default.Encode(pair.Value)}<br>"); // } //} await context.Response.WriteAsync("<h5><a href=\"/\">Home</a></h5></div></div></div>"); await context.Response.WriteAsync("</body></html>"); // context.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(context.Failure.Message)); context.HandleResponse(); }
/// <summary> /// Get Request Token /// </summary> /// <returns></returns> private async Task <PocketRequestTokenResult> GetRequestTokenAsync() { try { var requestBody = new PocketRequestTokenRequest() { ConsumerKey = Options.ConsumerKey, RedirectUri = BuildRedirectUri(Options.CallbackPath.Value) }; var playLoad = PrepareRequestTokenPlayLoad(requestBody); var res = await Options.Backchannel.PostAsync(Options.RequestTokenEndpoint, playLoad); if (res.IsSuccessStatusCode) { var str = await res.Content.ReadAsStringAsync(); var tokenRes = JsonConvert.DeserializeObject <PocketRequestTokenResponse>(str); return(PocketRequestTokenResult.Success(tokenRes)); } else { await ProcessPocketRemoteFail(res); } } catch (Exception ex) { var remoteFailure = new RemoteFailureContext(Context, Scheme, Options, ex); await Events.OnRemoteFailure(remoteFailure); } return(PocketRequestTokenResult.Fail()); }
private async Task HandleOnRemoteFailure(RemoteFailureContext context) { context.Response.StatusCode = 500; context.Response.ContentType = "text/html"; await context.Response.WriteAsync("<html><body>"); await context.Response.WriteAsync("A remote failure has occurred: <br>" + context.Failure.Message.Split(Environment.NewLine).Select(s => HtmlEncoder.Default.Encode(s) + "<br>").Aggregate((s1, s2) => s1 + s2)); if (context.Properties != null) { await context.Response.WriteAsync("Properties:<br>"); foreach (var pair in context.Properties.Items) { await context.Response.WriteAsync($"-{ HtmlEncoder.Default.Encode(pair.Key)}={ HtmlEncoder.Default.Encode(pair.Value)}<br>"); } } await context.Response.WriteAsync("<a href=\"/\">Home</a>"); await context.Response.WriteAsync("</body></html>"); // context.Response.Redirect("/error?FailureMessage=" + UrlEncoder.Default.Encode(context.Failure.Message)); context.HandleResponse(); }
public Task OnRemoteFailure(RemoteFailureContext context) { context.HandleResponse(); // Handle the error code that Azure Active Directory B2C throws when trying to reset a password from the login page // because password reset is not supported by a "sign-up or sign-in policy". // Below is a sample error message: // 'access_denied', error_description: 'AADB2C90118: The user has forgotten their password. // Correlation ID: f99deff4-f43b-43cc-b4e7-36141dbaf0a0 // Timestamp: 2018-03-05 02:49:35Z //', error_uri: 'error_uri is null'. if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118")) { // If the user clicked the reset password link, redirect to the reset password route context.Response.Redirect($"{context.Request.PathBase}/AzureADB2C/Account/ResetPassword/{SchemeName}"); } // Access denied errors happen when a user cancels an action on the Azure Active Directory B2C UI. We just redirect back to // the main page in that case. // Message contains error: 'access_denied', error_description: 'AADB2C90091: The user has cancelled entering self-asserted information. // Correlation ID: d01c8878-0732-4eb2-beb8-da82a57432e0 // Timestamp: 2018-03-05 02:56:49Z // ', error_uri: 'error_uri is null'. else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied")) { context.Response.Redirect($"{context.Request.PathBase}/"); } else { context.Response.Redirect($"{context.Request.PathBase}/AzureADB2C/Account/Error"); } return(Task.CompletedTask); }
/// <summary> /// Returns whether the specified failure context indicates the user denied account linking permission. /// </summary> /// <param name="context">The current failure context.</param> /// <returns> /// <see langword="true"/> if account linking permission was denied; otherwise <see langword="false"/>. /// </returns> private static bool WasPermissionDenied(RemoteFailureContext context) { string error = context.Request.Query["error"].FirstOrDefault(); if (string.Equals(error, "access_denied", StringComparison.Ordinal) || string.Equals(error, "consent_required", StringComparison.Ordinal)) { return(true); } string reason = context.Request.Query["error_reason"].FirstOrDefault(); if (string.Equals(reason, "user_denied", StringComparison.Ordinal)) { return(true); } string description = context.Request.Query["error_description"].FirstOrDefault(); if (!string.IsNullOrEmpty(description) && description.Contains("denied", StringComparison.OrdinalIgnoreCase)) { return(true); } return(context.Request.Query.ContainsKey("denied")); }
public Task OnRemoteFailure(RemoteFailureContext context) { context.HandleResponse(); // Handle the error code that Azure AD B2C throws when trying to reset a password from the login page // because password reset is not supported by a "sign-up or sign-in policy" if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118")) { context.Response.Redirect("/Session/ResetPassword"); } else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied")) { context.Response.Redirect("/"); } else { // https://github.com/Azure-Samples/active-directory-b2c-dotnetcore-webapp/issues/29 var message = Regex.Replace(context.Failure.Message, @"[^\u001F-\u007F]+", string.Empty); context.Response.Redirect("/Home/Error?message=" + message); // context.Response.Redirect("/Home/Error?message=" + context.Failure.Message); /* if you have this exception: * Message contains error: 'invalid_request', error_description: 'AADB2C90205: This application does not have sufficient permissions against this web resource to perform the operation. * Correlation ID: 073af821-4d5c-4db1-9d51-5f57d2c148e2Timestamp: 2018-04-09 09:37:13Z', error_uri: 'error_uri is null'. * * Please check this https://github.com/Azure-Samples/active-directory-b2c-javascript-msal-singlepageapp/issues/4 */ } return(Task.FromResult(0)); }
private async Task HandleOnRemoteFailure(RemoteFailureContext context) { if (context.Failure.Message.Contains("access_denied")) { context.Response.StatusCode = 403; } context.HandleResponse(); }
// Handle sign-in errors differently than generic errors. private Task OnAuthenticationFailed(RemoteFailureContext context) { context.HandleResponse(); var message = Regex.Replace(context.Failure?.Message, @"[^\u001F-\u007F]+", string.Empty); context.Response.Redirect("/Home/Error?message=" + message); return(Task.FromResult(0)); }
/// <summary> /// Method to handle the remote failures if any from authentication server /// </summary> /// <param name="context"> The RemoteFailureContext that contains the failure error message </param> /// <returns> Throw the exception with the received failure message from remote </returns> public Task OnRemoteFailure(RemoteFailureContext context) { context.HandleResponse(); // Throw the exception to log the failure message in ApplicationInsights AND respond user with system failure message // This is further handled by ExceptionAttribute class throw (new Exception(context.Failure.Message)); }
public Task HandleRemoteFailure(RemoteFailureContext context) { this.logger.LogError(EventIDs.ExternalAuthNProviderError, context.Failure, LogMessages.AuthNProviderError); context.HandleResponse(); context.Response.Redirect($"/Home/AuthNError?messageid={(int)AuthNFailureMessageID.ExternalAuthNProviderError}"); return(Task.CompletedTask); }
public override Task RemoteFailure(RemoteFailureContext context) { _log.WriteErrorAsync("Authentication", "RemoteFailure", context.Failure.Message + context.Failure.InnerException, context.Failure).Wait(); context.HandleResponse(); context.Response.Redirect("/Home/AuthenticationFailed"); return(Task.FromResult(0)); }
// TODO: Replace with better implementation, use built-in error handling. /// <summary> /// When an oath authorization or token request fails. /// </summary> /// <param name="context"></param> /// <returns></returns> public static async Task HandleOnRemoteFailure(RemoteFailureContext context) { var handler = context.HttpContext.RequestServices.GetRequiredService <JsonErrorHandler>(); context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.ContentType = "application/json"; await context.Response.WriteAsync(handler.Serialize(new OauthException(context.Failure))); context.HandleResponse(); }
private async Task HandleOnRemoteFailure(RemoteFailureContext context) { var url = context.Request.Host.ToString(); context.HandleResponse(); await Task.Run(() => { context.Response.Redirect("/Home", true); }); }
/// <summary> /// 远程服务器(如授权失败时)错误处理程序。 /// </summary> /// <param name="remoteFailureContext"></param> /// <returns></returns> private Task OnRemoteFailureHandler(RemoteFailureContext remoteFailureContext) { remoteFailureContext.HandleResponse(); if (!remoteFailureContext.HttpContext.Response.HasStarted) { //TODO 写入日志 //TODO 向HttpContext.Response写入友好的错误提示信息展示给用户 } return(Task.CompletedTask); }
public static Task HandleRemoteFailure(this RemoteFailureContext context) { Log.Error( context.Failure, "External authentication remote failure. {Scheme}", context.Scheme.Name); context.Response.RedirectExternalError(context.Scheme.Name, context.Properties); context.HandleResponse(); return(Task.CompletedTask); }
private Task HandleRemoteFailure(RemoteFailureContext context) { if (context.Failure.Message.ToLower().Contains("correlation")) { context.HandleResponse(); context.Response.Redirect("/Home/CorrelationError"); return(Task.FromResult(0)); } else { throw context.Failure; } }
#pragma warning disable CS1998 private async Task HandleOnRemoteFailure(RemoteFailureContext context) { var msg = context.Failure.Message.Split(Environment.NewLine).Select(s => s + Environment.NewLine).Aggregate((s1, s2) => s1 + s2); if (context.Properties != null) foreach (var pair in context.Properties.Items) msg = $"{msg}{Environment.NewLine}-{pair.Key}={pair.Value}"; Log.Logger.Error($"External authentication error: {msg}"); context.Response.Redirect($"/externalauth/error/{ErrorEnum.ExternalAuthError}"); context.HandleResponse(); }
/// <summary> /// Handles a remote failure. /// </summary> /// <param name="context">The failure context.</param> /// <returns> /// A <see cref="Task"/> representing the completion of the operation. /// </returns> private async Task HandleRemoteFailure(RemoteFailureContext context) { try { await HandleRemoteFailure( context, _options.SignInScheme, _options.StateDataFormat, _logger, (p) => p?.Items); } catch (Exception ex) { _logger.LogError(default, ex, "Failed to handle remote failure: {Message}.", ex.Message);
/// <summary> /// Handles a remote failure. /// </summary> /// <param name="context">The failure context.</param> /// <returns> /// A <see cref="Task"/> representing the completion of the operation. /// </returns> private async Task HandleRemoteFailure(RemoteFailureContext context) { try { await HandleRemoteFailure( context, _options.SignInScheme !, _options.StateDataFormat, _logger, (p) => p?.Items); } #pragma warning disable CA1031 catch (Exception ex) #pragma warning restore CA1031 { _logger.LogError(default, ex, "Failed to handle remote failure: {Message}.", ex.Message);
/// <summary> /// Handles a remote failure. /// </summary> /// <typeparam name="T">The type of the secure data.</typeparam> /// <param name="context">The failure context.</param> /// <param name="provider">The authentication provider.</param> /// <param name="secureDataFormat">The secure data format.</param> /// <param name="logger">The <see cref="ILogger"/> to use.</param> /// <param name="propertiesProvider">A delegate to a method to retrieve authentication properties from the secure data.</param> /// <returns> /// A <see cref="Task"/> representing the completion of the operation. /// </returns> public static Task HandleRemoteFailure <T>( RemoteFailureContext context, string provider, ISecureDataFormat <T> secureDataFormat, ILogger logger, Func <T, IDictionary <string, string>?> propertiesProvider) { string?path = GetSiteErrorRedirect(context, secureDataFormat, propertiesProvider); if (string.IsNullOrEmpty(path) || !Uri.TryCreate(path, UriKind.Relative, out Uri? notUsed)) { path = "/"; } SiteMessage message; if (WasPermissionDenied(context)) { message = SiteMessage.LinkDenied; logger.LogTrace("User denied permission."); } else { message = SiteMessage.LinkFailed; var eventId = default(EventId); string errors = string.Join(";", context.Request.Query.Select((p) => $"'{p.Key}' = '{p.Value}'")); string logMessage = $"Failed to sign-in using '{provider}': '{context.Failure.Message}'. Errors: {errors}."; if (IsCorrelationFailure(context)) { // Not a server-side problem, so do not create log noise logger.LogTrace(eventId, context.Failure, logMessage); } else { logger.LogError(eventId, context.Failure, logMessage); } } context.Response.Redirect($"{path}?Message={message}"); context.HandleResponse(); return(Task.CompletedTask); }