public override Task MatchEndpoint(MatchEndpointContext context) { // Note: by default, OpenIdConnectServerHandler only handles authorization requests made to the authorization endpoint. // This context handler uses a more relaxed policy that allows extracting authorization requests received at // /connect/authorize/accept and /connect/authorize/deny (see AuthorizationController.cs for more information). if (context.Options.AuthorizationEndpointPath.HasValue && context.Request.Path.StartsWithSegments(context.Options.AuthorizationEndpointPath)) { context.MatchesAuthorizationEndpoint(); } return Task.FromResult(0); }
protected override async Task <bool> HandleUnauthorizedAsync(ChallengeContext context) { var notification = new MatchEndpointContext(Context, Options); if (Options.UserinfoEndpointPath.HasValue && Options.UserinfoEndpointPath == Request.Path) { notification.MatchesUserinfoEndpoint(); } await Options.Provider.MatchEndpoint(notification); // Return true to indicate to the authentication pipeline that // the 401 response shouldn't be handled by the other middleware. if (!notification.IsUserinfoEndpoint) { return(true); } Response.StatusCode = 401; Response.Headers[HeaderNames.WWWAuthenticate] = "error=" + OpenIdConnectConstants.Errors.InvalidGrant; return(false); }
public override async Task <bool> HandleRequestAsync() { var notification = new MatchEndpointContext(Context, Options); if (Options.AuthorizationEndpointPath.HasValue && Options.AuthorizationEndpointPath == Request.Path) { notification.MatchesAuthorizationEndpoint(); } else if (Options.ConfigurationEndpointPath.HasValue && Options.ConfigurationEndpointPath == Request.Path) { notification.MatchesConfigurationEndpoint(); } else if (Options.CryptographyEndpointPath.HasValue && Options.CryptographyEndpointPath == Request.Path) { notification.MatchesCryptographyEndpoint(); } else if (Options.IntrospectionEndpointPath.HasValue && Options.IntrospectionEndpointPath == Request.Path) { notification.MatchesIntrospectionEndpoint(); } else if (Options.LogoutEndpointPath.HasValue && Options.LogoutEndpointPath == Request.Path) { notification.MatchesLogoutEndpoint(); } else if (Options.RevocationEndpointPath.HasValue && Options.RevocationEndpointPath == Request.Path) { notification.MatchesRevocationEndpoint(); } else if (Options.TokenEndpointPath.HasValue && Options.TokenEndpointPath == Request.Path) { notification.MatchesTokenEndpoint(); } else if (Options.UserinfoEndpointPath.HasValue && Options.UserinfoEndpointPath == Request.Path) { notification.MatchesUserinfoEndpoint(); } await Options.Provider.MatchEndpoint(notification); if (notification.HandledResponse) { return(true); } else if (notification.Skipped) { return(false); } // Reject non-HTTPS requests handled by ASOS if AllowInsecureHttp is not set to true. if (!Options.AllowInsecureHttp && !Request.IsHttps) { // Return the native error page for endpoints involving the user participation. if (notification.IsAuthorizationEndpoint || notification.IsLogoutEndpoint) { Logger.LogWarning("The current request was rejected because the OpenID Connect server middleware " + "has been configured to reject HTTP requests. To permanently disable the transport " + "security requirement, set 'OpenIdConnectServerOptions.AllowInsecureHttp' to 'true'."); return(await SendNativePageAsync(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = "This server only accepts HTTPS requests." })); } // Return a JSON error for endpoints that don't involve the user participation. else if (notification.IsConfigurationEndpoint || notification.IsCryptographyEndpoint || notification.IsIntrospectionEndpoint || notification.IsRevocationEndpoint || notification.IsTokenEndpoint || notification.IsUserinfoEndpoint) { Logger.LogWarning("The current request was rejected because the OpenID Connect server middleware " + "has been configured to reject HTTP requests. To permanently disable the transport " + "security requirement, set 'OpenIdConnectServerOptions.AllowInsecureHttp' to 'true'."); return(await SendPayloadAsync(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = "This server only accepts HTTPS requests." })); } } if (notification.IsAuthorizationEndpoint) { return(await InvokeAuthorizationEndpointAsync()); } else if (notification.IsConfigurationEndpoint) { return(await InvokeConfigurationEndpointAsync()); } else if (notification.IsCryptographyEndpoint) { return(await InvokeCryptographyEndpointAsync()); } else if (notification.IsIntrospectionEndpoint) { return(await InvokeIntrospectionEndpointAsync()); } else if (notification.IsLogoutEndpoint) { return(await InvokeLogoutEndpointAsync()); } else if (notification.IsRevocationEndpoint) { return(await InvokeRevocationEndpointAsync()); } else if (notification.IsTokenEndpoint) { return(await InvokeTokenEndpointAsync()); } else if (notification.IsUserinfoEndpoint) { return(await InvokeUserinfoEndpointAsync()); } return(false); }
protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { var notification = new MatchEndpointContext(Context, Options); if (Options.AuthorizationEndpointPath.HasValue && Options.AuthorizationEndpointPath == Request.Path) { notification.MatchesAuthorizationEndpoint(); } else if (Options.LogoutEndpointPath.HasValue && Options.LogoutEndpointPath == Request.Path) { notification.MatchesLogoutEndpoint(); } else if (Options.ProfileEndpointPath.HasValue && Options.ProfileEndpointPath == Request.Path) { notification.MatchesProfileEndpoint(); } await Options.Provider.MatchEndpoint(notification); if (!notification.IsAuthorizationEndpoint && !notification.IsLogoutEndpoint && !notification.IsProfileEndpoint) { return(null); } // Try to retrieve the current OpenID Connect request from the ASP.NET context. // If the request cannot be found, this means that this middleware was configured // to use the automatic authentication mode and that HandleAuthenticateAsync // was invoked before Invoke*EndpointAsync: in this case, the OpenID Connect // request is directly extracted from the query string or the request form. var request = Context.GetOpenIdConnectRequest(); if (request == null) { if (string.Equals(Request.Method, "GET", StringComparison.OrdinalIgnoreCase)) { request = new OpenIdConnectMessage(Request.Query.ToDictionary()); } else if (string.Equals(Request.Method, "POST", StringComparison.OrdinalIgnoreCase)) { if (string.IsNullOrEmpty(Request.ContentType)) { return(null); } else if (!Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase)) { return(null); } var form = await Request.ReadFormAsync(Context.RequestAborted); request = new OpenIdConnectMessage(form.ToDictionary()); } } // Missing or invalid requests are ignored in HandleAuthenticateAsync: // in this case, null is always returned to indicate authentication failed. if (request == null) { return(null); } if (notification.IsAuthorizationEndpoint || notification.IsLogoutEndpoint) { if (string.IsNullOrEmpty(request.IdTokenHint)) { return(null); } var ticket = await ReceiveIdentityTokenAsync(request.IdTokenHint, request); if (ticket == null) { Logger.LogVerbose("Invalid id_token_hint"); return(null); } // Tickets are returned even if they // are considered invalid (e.g expired). return(AuthenticateResult.Success(ticket)); } else if (notification.IsProfileEndpoint) { string token; if (!string.IsNullOrEmpty(request.AccessToken)) { token = request.AccessToken; } else { string header = Request.Headers[HeaderNames.Authorization]; if (string.IsNullOrEmpty(header)) { return(null); } if (!header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { return(null); } token = header.Substring("Bearer ".Length); if (string.IsNullOrWhiteSpace(token)) { return(null); } } var ticket = await ReceiveAccessTokenAsync(token, request); if (ticket == null) { Logger.LogVerbose("Invalid access_token"); return(null); } if (!ticket.Properties.ExpiresUtc.HasValue || ticket.Properties.ExpiresUtc < Options.SystemClock.UtcNow) { Logger.LogVerbose("Expired access_token"); return(null); } return(AuthenticateResult.Success(ticket)); } return(null); }
public override async Task <bool> HandleRequestAsync() { var notification = new MatchEndpointContext(Context, Options); if (Options.AuthorizationEndpointPath.HasValue && Options.AuthorizationEndpointPath == Request.Path) { notification.MatchesAuthorizationEndpoint(); } else if (Options.TokenEndpointPath.HasValue && Options.TokenEndpointPath == Request.Path) { notification.MatchesTokenEndpoint(); } else if (Options.ValidationEndpointPath.HasValue && Options.ValidationEndpointPath == Request.Path) { notification.MatchesValidationEndpoint(); } else if (Options.ProfileEndpointPath.HasValue && Options.ProfileEndpointPath == Request.Path) { notification.MatchesProfileEndpoint(); } else if (Options.LogoutEndpointPath.HasValue && Options.LogoutEndpointPath == Request.Path) { notification.MatchesLogoutEndpoint(); } else if (Options.ConfigurationEndpointPath.HasValue && Options.ConfigurationEndpointPath == Request.Path) { notification.MatchesConfigurationEndpoint(); } else if (Options.CryptographyEndpointPath.HasValue && Options.CryptographyEndpointPath == Request.Path) { notification.MatchesCryptographyEndpoint(); } await Options.Provider.MatchEndpoint(notification); if (notification.HandledResponse) { return(true); } else if (notification.Skipped) { return(false); } // Reject non-HTTPS requests handled by the OpenID Connect // server middleware if AllowInsecureHttp is not set to true. if (!Options.AllowInsecureHttp && !Request.IsHttps) { Logger.LogWarning("The HTTP request was rejected because AllowInsecureHttp was false."); if (notification.IsAuthorizationEndpoint || notification.IsLogoutEndpoint) { // Return the native error page for endpoints involving the user participation. await SendNativeErrorPageAsync(new OpenIdConnectMessage { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = "This server only accepts HTTPS requests." }); return(true); } else if (notification.IsTokenEndpoint || notification.IsProfileEndpoint || notification.IsValidationEndpoint || notification.IsConfigurationEndpoint || notification.IsCryptographyEndpoint) { // Return a JSON error for endpoints that don't involve the user participation. await SendErrorPayloadAsync(new OpenIdConnectMessage { Error = OpenIdConnectConstants.Errors.InvalidRequest, ErrorDescription = "This server only accepts HTTPS requests." }); return(true); } } if (notification.IsAuthorizationEndpoint) { return(await InvokeAuthorizationEndpointAsync()); } else if (notification.IsLogoutEndpoint) { return(await InvokeLogoutEndpointAsync()); } else if (notification.IsTokenEndpoint) { await InvokeTokenEndpointAsync(); return(true); } else if (notification.IsValidationEndpoint) { await InvokeValidationEndpointAsync(); return(true); } else if (notification.IsProfileEndpoint) { return(await InvokeProfileEndpointAsync()); } else if (notification.IsConfigurationEndpoint) { await InvokeConfigurationEndpointAsync(); return(true); } else if (notification.IsCryptographyEndpoint) { await InvokeCryptographyEndpointAsync(); return(true); } return(false); }
/// <summary> /// Called to determine if an incoming request is treated as an authorization or token /// endpoint. If Options.AuthorizationEndpointPath or Options.TokenEndpointPath /// are assigned values, then handling this event is optional and context.IsAuthorizationEndpoint and context.IsTokenEndpoint /// will already be true if the request path matches. /// </summary> /// <param name="context">The context of the event carries information in and results out.</param> /// <returns>Task to enable asynchronous execution</returns> public virtual Task MatchEndpoint(MatchEndpointContext context) => OnMatchEndpoint(context);