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);
        }
示例#3
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.UserinfoEndpointPath.HasValue &&
                     Options.UserinfoEndpointPath == Request.Path)
            {
                notification.MatchesUserinfoEndpoint();
            }

            await Options.Provider.MatchEndpoint(notification);

            if (!notification.IsAuthorizationEndpoint &&
                !notification.IsLogoutEndpoint &&
                !notification.IsUserinfoEndpoint)
            {
                return(AuthenticateResult.Skip());
            }

            // 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(AuthenticateResult.Skip());
                    }

                    else if (!Request.ContentType.StartsWith("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase))
                    {
                        return(AuthenticateResult.Skip());
                    }

                    var form = await Request.ReadFormAsync(Context.RequestAborted);

                    request = new OpenIdConnectMessage(form.ToDictionary());
                }
            }

            // Missing or invalid requests are ignored in HandleAuthenticateAsync:
            // in this case, Skip is used to indicate authentication failed.
            if (request == null)
            {
                return(AuthenticateResult.Skip());
            }

            if (notification.IsAuthorizationEndpoint || notification.IsLogoutEndpoint)
            {
                if (string.IsNullOrEmpty(request.IdTokenHint))
                {
                    return(AuthenticateResult.Skip());
                }

                var ticket = await DeserializeIdentityTokenAsync(request.IdTokenHint, request);

                if (ticket == null)
                {
                    Logger.LogWarning("The identity token extracted from the id_token_hint " +
                                      "parameter was invalid and has been ignored.");

                    return(AuthenticateResult.Skip());
                }

                // Tickets are returned even if they
                // are considered invalid (e.g expired).
                return(AuthenticateResult.Success(ticket));
            }

            else if (notification.IsUserinfoEndpoint)
            {
                string token;
                if (!string.IsNullOrEmpty(request.AccessToken))
                {
                    token = request.AccessToken;
                }

                else
                {
                    string header = Request.Headers[HeaderNames.Authorization];
                    if (string.IsNullOrEmpty(header))
                    {
                        return(AuthenticateResult.Skip());
                    }

                    if (!header.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
                    {
                        return(AuthenticateResult.Skip());
                    }

                    token = header.Substring("Bearer ".Length);
                    if (string.IsNullOrWhiteSpace(token))
                    {
                        return(AuthenticateResult.Skip());
                    }
                }

                var ticket = await DeserializeAccessTokenAsync(token, request);

                if (ticket == null)
                {
                    Logger.LogWarning("The access token extracted from the userinfo " +
                                      "request was expired and has been ignored.");

                    return(AuthenticateResult.Skip());
                }

                if (!ticket.Properties.ExpiresUtc.HasValue ||
                    ticket.Properties.ExpiresUtc < Options.SystemClock.UtcNow)
                {
                    Logger.LogWarning("The access token extracted from the userinfo " +
                                      "request was expired and has been ignored.");

                    return(AuthenticateResult.Skip());
                }

                return(AuthenticateResult.Success(ticket));
            }

            return(AuthenticateResult.Skip());
        }