public override async Task <bool> InvokeAsync() { 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 && string.Equals(Request.Scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase)) { // Return the native error page for endpoints involving the user participation. if (notification.IsAuthorizationEndpoint || notification.IsLogoutEndpoint) { Options.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) { Options.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); }
// Implementing AuthenticateCoreAsync allows the inner application // to retrieve the identity extracted from the optional id_token_hint. protected override async Task <AuthenticationTicket> AuthenticateCoreAsync() { 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.UserinfoEndpointPath.HasValue && Options.UserinfoEndpointPath == Request.Path) { notification.MatchesUserinfoEndpoint(); } await Options.Provider.MatchEndpoint(notification); if (!notification.IsAuthorizationEndpoint && !notification.IsLogoutEndpoint && !notification.IsUserinfoEndpoint) { return(null); } // Try to retrieve the current OpenID Connect request from the OWIN context. // If the request cannot be found, this means that this middleware was configured // to use the automatic authentication mode and that AuthenticateCoreAsync // 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); } 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); } request = new OpenIdConnectMessage(await Request.ReadFormAsync()); } } // Missing or invalid requests are ignored in AuthenticateCoreAsync: // 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 DeserializeIdentityTokenAsync(request.IdTokenHint, request); if (ticket == null) { Options.Logger.LogWarning("The identity token extracted from the id_token_hint " + "parameter was invalid and has been ignored."); return(null); } // Tickets are returned even if they // are considered invalid (e.g expired). return(ticket); } else if (notification.IsUserinfoEndpoint) { string token; if (!string.IsNullOrEmpty(request.AccessToken)) { token = request.AccessToken; } else { var header = Request.Headers.Get("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 DeserializeAccessTokenAsync(token, request); if (ticket == null) { Options.Logger.LogWarning("The access token extracted from the userinfo " + "request was invalid and has been ignored."); return(null); } if (!ticket.Properties.ExpiresUtc.HasValue || ticket.Properties.ExpiresUtc < Options.SystemClock.UtcNow) { Options.Logger.LogWarning("The access token extracted from the userinfo " + "request was expired and has been ignored."); return(null); } return(ticket); } return(null); }