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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
 /// <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);