mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	Merge branch 'master' into develop
This commit is contained in:
		@@ -7,7 +7,7 @@ namespace Ocelot.Authorisation
 | 
			
		||||
{
 | 
			
		||||
    using Infrastructure.Claims.Parser;
 | 
			
		||||
 | 
			
		||||
    public class ClaimsAuthoriser : IAuthoriser
 | 
			
		||||
    public class ClaimsAuthoriser : IClaimsAuthoriser
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IClaimsParser _claimsParser;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,8 @@ namespace Ocelot.Authorisation
 | 
			
		||||
{
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
    public interface IAuthoriser
 | 
			
		||||
    public interface IClaimsAuthoriser
 | 
			
		||||
    {
 | 
			
		||||
        Response<bool> Authorise(ClaimsPrincipal claimsPrincipal,
 | 
			
		||||
            Dictionary<string, string> routeClaimsRequirement);
 | 
			
		||||
        Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, Dictionary<string, string> routeClaimsRequirement);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								src/Ocelot/Authorisation/IScopesAuthoriser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Ocelot/Authorisation/IScopesAuthoriser.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Authorisation
 | 
			
		||||
{
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
 | 
			
		||||
    public interface IScopesAuthoriser
 | 
			
		||||
    {
 | 
			
		||||
        Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using Ocelot.Infrastructure.RequestData;
 | 
			
		||||
using Ocelot.Logging;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using Ocelot.Configuration;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Authorisation.Middleware
 | 
			
		||||
{
 | 
			
		||||
@@ -13,17 +14,20 @@ namespace Ocelot.Authorisation.Middleware
 | 
			
		||||
    public class AuthorisationMiddleware : OcelotMiddleware
 | 
			
		||||
    {
 | 
			
		||||
        private readonly RequestDelegate _next;
 | 
			
		||||
        private readonly IAuthoriser _authoriser;
 | 
			
		||||
        private readonly IClaimsAuthoriser _claimsAuthoriser;
 | 
			
		||||
        private readonly IScopesAuthoriser _scopesAuthoriser;
 | 
			
		||||
        private readonly IOcelotLogger _logger;
 | 
			
		||||
 | 
			
		||||
        public AuthorisationMiddleware(RequestDelegate next,
 | 
			
		||||
            IRequestScopedDataRepository requestScopedDataRepository,
 | 
			
		||||
            IAuthoriser authoriser,
 | 
			
		||||
            IClaimsAuthoriser claimsAuthoriser,
 | 
			
		||||
            IScopesAuthoriser scopesAuthoriser,
 | 
			
		||||
            IOcelotLoggerFactory loggerFactory)
 | 
			
		||||
            : base(requestScopedDataRepository)
 | 
			
		||||
        {
 | 
			
		||||
            _next = next;
 | 
			
		||||
            _authoriser = authoriser;
 | 
			
		||||
            _claimsAuthoriser = claimsAuthoriser;
 | 
			
		||||
            _scopesAuthoriser = scopesAuthoriser;
 | 
			
		||||
            _logger = loggerFactory.CreateLogger<AuthorisationMiddleware>();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -31,11 +35,41 @@ namespace Ocelot.Authorisation.Middleware
 | 
			
		||||
        {
 | 
			
		||||
            _logger.LogDebug("started authorisation");
 | 
			
		||||
 | 
			
		||||
            if (DownstreamRoute.ReRoute.IsAuthorised)
 | 
			
		||||
            if (IsAuthenticatedRoute(DownstreamRoute.ReRoute))
 | 
			
		||||
            {
 | 
			
		||||
                _logger.LogDebug("route is authenticated scopes must be checked");
 | 
			
		||||
 | 
			
		||||
                var authorised = _scopesAuthoriser.Authorise(context.User, DownstreamRoute.ReRoute.AuthenticationOptions.AllowedScopes);
 | 
			
		||||
 | 
			
		||||
                if (authorised.IsError)
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogDebug("error authorising user scopes");
 | 
			
		||||
 | 
			
		||||
                    SetPipelineError(authorised.Errors);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (IsAuthorised(authorised))
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogDebug("user scopes is authorised calling next authorisation checks");
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    _logger.LogDebug("user scopes is not authorised setting pipeline error");
 | 
			
		||||
 | 
			
		||||
                    SetPipelineError(new List<Error>
 | 
			
		||||
                    {
 | 
			
		||||
                        new UnauthorisedError(
 | 
			
		||||
                            $"{context.User.Identity.Name} unable to access {DownstreamRoute.ReRoute.UpstreamPathTemplate.Value}")
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (IsAuthorisedRoute(DownstreamRoute.ReRoute))
 | 
			
		||||
            {
 | 
			
		||||
                _logger.LogDebug("route is authorised");
 | 
			
		||||
 | 
			
		||||
                var authorised = _authoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement);
 | 
			
		||||
                var authorised = _claimsAuthoriser.Authorise(context.User, DownstreamRoute.ReRoute.RouteClaimsRequirement);
 | 
			
		||||
 | 
			
		||||
                if (authorised.IsError)
 | 
			
		||||
                {
 | 
			
		||||
@@ -78,5 +112,15 @@ namespace Ocelot.Authorisation.Middleware
 | 
			
		||||
        {
 | 
			
		||||
            return authorised.Data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool IsAuthenticatedRoute(ReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            return reRoute.IsAuthenticated;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private static bool IsAuthorisedRoute(ReRoute reRoute)
 | 
			
		||||
        {
 | 
			
		||||
            return reRoute.IsAuthorised;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/Ocelot/Authorisation/ScopeNotAuthorisedError.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/Ocelot/Authorisation/ScopeNotAuthorisedError.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Authorisation
 | 
			
		||||
{
 | 
			
		||||
    public class ScopeNotAuthorisedError : Error
 | 
			
		||||
    {
 | 
			
		||||
        public ScopeNotAuthorisedError(string message) 
 | 
			
		||||
            : base(message, OcelotErrorCode.ScopeNotAuthorisedError)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								src/Ocelot/Authorisation/ScopesAuthoriser.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/Ocelot/Authorisation/ScopesAuthoriser.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
using IdentityModel;
 | 
			
		||||
using Ocelot.Errors;
 | 
			
		||||
using Ocelot.Responses;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Authorisation
 | 
			
		||||
{
 | 
			
		||||
    using Infrastructure.Claims.Parser;
 | 
			
		||||
 | 
			
		||||
    public class ScopesAuthoriser : IScopesAuthoriser
 | 
			
		||||
    {
 | 
			
		||||
        private readonly IClaimsParser _claimsParser;
 | 
			
		||||
 | 
			
		||||
        public ScopesAuthoriser(IClaimsParser claimsParser)
 | 
			
		||||
        {
 | 
			
		||||
            _claimsParser = claimsParser;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Response<bool> Authorise(ClaimsPrincipal claimsPrincipal, List<string> routeAllowedScopes)
 | 
			
		||||
        {
 | 
			
		||||
            if (routeAllowedScopes == null || routeAllowedScopes.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return new OkResponse<bool>(true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, JwtClaimTypes.Scope);
 | 
			
		||||
 | 
			
		||||
            if (values.IsError)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<bool>(values.Errors);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var userScopes = values.Data;
 | 
			
		||||
 | 
			
		||||
            List<string> matchesScopes = routeAllowedScopes.Intersect(userScopes).ToList();
 | 
			
		||||
 | 
			
		||||
            if (matchesScopes == null || matchesScopes.Count == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return new ErrorResponse<bool>(new List<Error>
 | 
			
		||||
                {
 | 
			
		||||
                     new ScopeNotAuthorisedError(
 | 
			
		||||
                         $"no one user scope: '{string.Join(",", userScopes)}' match with some allowed scope: '{string.Join(",", routeAllowedScopes)}'")
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return new OkResponse<bool>(true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Net.Http;
 | 
			
		||||
using Ocelot.Values;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
 | 
			
		||||
namespace Ocelot.Configuration.Builder
 | 
			
		||||
{
 | 
			
		||||
@@ -11,7 +12,7 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
        private string _downstreamPathTemplate;
 | 
			
		||||
        private string _upstreamTemplate;
 | 
			
		||||
        private string _upstreamTemplatePattern;
 | 
			
		||||
        private string _upstreamHttpMethod;
 | 
			
		||||
        private List<HttpMethod> _upstreamHttpMethod;
 | 
			
		||||
        private bool _isAuthenticated;
 | 
			
		||||
        private List<ClaimToThing> _configHeaderExtractorProperties;
 | 
			
		||||
        private List<ClaimToThing> _claimToClaims;
 | 
			
		||||
@@ -66,11 +67,13 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
            _upstreamTemplatePattern = input;
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
        public ReRouteBuilder WithUpstreamHttpMethod(string input)
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder WithUpstreamHttpMethod(List<string> input)
 | 
			
		||||
        {
 | 
			
		||||
            _upstreamHttpMethod = input;
 | 
			
		||||
            _upstreamHttpMethod = (input.Count == 0) ? new List<HttpMethod>() : input.Select(x => new HttpMethod(x.Trim())).ToList();
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder WithIsAuthenticated(bool input)
 | 
			
		||||
        {
 | 
			
		||||
            _isAuthenticated = input;
 | 
			
		||||
@@ -143,7 +146,6 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
            return this;
 | 
			
		||||
        }
 | 
			
		||||
       
 | 
			
		||||
 | 
			
		||||
        public ReRouteBuilder WithLoadBalancerKey(string loadBalancerKey)
 | 
			
		||||
        {
 | 
			
		||||
            _loadBalancerKey = loadBalancerKey;
 | 
			
		||||
@@ -180,7 +182,7 @@ namespace Ocelot.Configuration.Builder
 | 
			
		||||
            return new ReRoute(
 | 
			
		||||
                new PathTemplate(_downstreamPathTemplate), 
 | 
			
		||||
                new PathTemplate(_upstreamTemplate), 
 | 
			
		||||
                new HttpMethod(_upstreamHttpMethod), 
 | 
			
		||||
                _upstreamHttpMethod, 
 | 
			
		||||
                _upstreamTemplatePattern, 
 | 
			
		||||
                _isAuthenticated, 
 | 
			
		||||
                _authenticationOptions,
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ namespace Ocelot.Configuration.File
 | 
			
		||||
    {
 | 
			
		||||
        public FileReRoute()
 | 
			
		||||
        {
 | 
			
		||||
            UpstreamHttpMethod = new List<string>();
 | 
			
		||||
            AddHeadersToRequest = new Dictionary<string, string>();
 | 
			
		||||
            AddClaimsToRequest = new Dictionary<string, string>();
 | 
			
		||||
            RouteClaimsRequirement = new Dictionary<string, string>();
 | 
			
		||||
@@ -18,7 +19,7 @@ namespace Ocelot.Configuration.File
 | 
			
		||||
 | 
			
		||||
        public string DownstreamPathTemplate { get; set; }
 | 
			
		||||
        public string UpstreamPathTemplate { get; set; }
 | 
			
		||||
        public string UpstreamHttpMethod { get; set; }
 | 
			
		||||
        public List<string> UpstreamHttpMethod { get; set; }
 | 
			
		||||
        public FileAuthenticationOptions AuthenticationOptions { get; set; }
 | 
			
		||||
        public Dictionary<string, string> AddHeadersToRequest { get; set; }
 | 
			
		||||
        public Dictionary<string, string> AddClaimsToRequest { get; set; }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ namespace Ocelot.Configuration
 | 
			
		||||
    {
 | 
			
		||||
        public ReRoute(PathTemplate downstreamPathTemplate, 
 | 
			
		||||
            PathTemplate upstreamPathTemplate, 
 | 
			
		||||
            HttpMethod upstreamHttpMethod, 
 | 
			
		||||
            List<HttpMethod> upstreamHttpMethod, 
 | 
			
		||||
            string upstreamTemplatePattern, 
 | 
			
		||||
            bool isAuthenticated, 
 | 
			
		||||
            AuthenticationOptions authenticationOptions, 
 | 
			
		||||
@@ -64,7 +64,7 @@ namespace Ocelot.Configuration
 | 
			
		||||
        public PathTemplate DownstreamPathTemplate { get; private set; }
 | 
			
		||||
        public PathTemplate UpstreamPathTemplate { get; private set; }
 | 
			
		||||
        public string UpstreamTemplatePattern { get; private set; }
 | 
			
		||||
        public HttpMethod UpstreamHttpMethod { get; private set; }
 | 
			
		||||
        public List<HttpMethod> UpstreamHttpMethod { get; private set; }
 | 
			
		||||
        public bool IsAuthenticated { get; private set; }
 | 
			
		||||
        public bool IsAuthorised { get; private set; }
 | 
			
		||||
        public AuthenticationOptions AuthenticationOptions { get; private set; }
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ namespace Ocelot.Configuration.Validator
 | 
			
		||||
    {
 | 
			
		||||
        public Response<ConfigurationValidationResult> IsValid(FileConfiguration configuration)
 | 
			
		||||
        {
 | 
			
		||||
            var result = CheckForDupliateReRoutes(configuration);
 | 
			
		||||
            var result = CheckForDuplicateReRoutes(configuration);
 | 
			
		||||
 | 
			
		||||
            if (result.IsError)
 | 
			
		||||
            {
 | 
			
		||||
@@ -97,25 +97,41 @@ namespace Ocelot.Configuration.Validator
 | 
			
		||||
            return new ConfigurationValidationResult(false, errors);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private ConfigurationValidationResult CheckForDupliateReRoutes(FileConfiguration configuration)
 | 
			
		||||
        {
 | 
			
		||||
            var hasDupes = configuration.ReRoutes
 | 
			
		||||
                   .GroupBy(x => new { x.UpstreamPathTemplate, x.UpstreamHttpMethod }).Any(x => x.Skip(1).Any());
 | 
			
		||||
        private ConfigurationValidationResult CheckForDuplicateReRoutes(FileConfiguration configuration)
 | 
			
		||||
        {         
 | 
			
		||||
            var duplicatedUpstreamPathTemplates = new List<string>();
 | 
			
		||||
 | 
			
		||||
            if (!hasDupes)
 | 
			
		||||
            var distinctUpstreamPathTemplates = configuration.ReRoutes.Select(x => x.UpstreamPathTemplate).Distinct();
 | 
			
		||||
            
 | 
			
		||||
            foreach (string upstreamPathTemplate in distinctUpstreamPathTemplates)
 | 
			
		||||
            {
 | 
			
		||||
                var reRoutesWithUpstreamPathTemplate = configuration.ReRoutes.Where(x => x.UpstreamPathTemplate == upstreamPathTemplate);
 | 
			
		||||
 | 
			
		||||
                var hasEmptyListToAllowAllHttpVerbs = reRoutesWithUpstreamPathTemplate.Where(x => x.UpstreamHttpMethod.Count() == 0).Any();
 | 
			
		||||
                var hasDuplicateEmptyListToAllowAllHttpVerbs = reRoutesWithUpstreamPathTemplate.Where(x => x.UpstreamHttpMethod.Count() == 0).Count() > 1;
 | 
			
		||||
                var hasSpecificHttpVerbs = reRoutesWithUpstreamPathTemplate.Where(x => x.UpstreamHttpMethod.Count() > 0).Any();
 | 
			
		||||
                var hasDuplicateSpecificHttpVerbs = reRoutesWithUpstreamPathTemplate.SelectMany(x => x.UpstreamHttpMethod).GroupBy(x => x.ToLower()).SelectMany(x => x.Skip(1)).Any();
 | 
			
		||||
 | 
			
		||||
                if (hasDuplicateEmptyListToAllowAllHttpVerbs || hasDuplicateSpecificHttpVerbs || (hasEmptyListToAllowAllHttpVerbs && hasSpecificHttpVerbs))
 | 
			
		||||
                {
 | 
			
		||||
                    duplicatedUpstreamPathTemplates.Add(upstreamPathTemplate);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (duplicatedUpstreamPathTemplates.Count() == 0)
 | 
			
		||||
            {
 | 
			
		||||
                return new ConfigurationValidationResult(false);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                var errors = duplicatedUpstreamPathTemplates
 | 
			
		||||
                    .Select(d => new DownstreamPathTemplateAlreadyUsedError(string.Format("Duplicate DownstreamPath: {0}", d)))
 | 
			
		||||
                    .Cast<Error>()
 | 
			
		||||
                    .ToList();
 | 
			
		||||
 | 
			
		||||
            var dupes = configuration.ReRoutes.GroupBy(x => new { x.UpstreamPathTemplate, x.UpstreamHttpMethod })
 | 
			
		||||
                               .Where(x => x.Skip(1).Any());
 | 
			
		||||
                return new ConfigurationValidationResult(true, errors);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var errors = dupes
 | 
			
		||||
                .Select(d => new DownstreamPathTemplateAlreadyUsedError(string.Format("Duplicate DownstreamPath: {0}", d.Key.UpstreamPathTemplate)))
 | 
			
		||||
                .Cast<Error>()
 | 
			
		||||
                .ToList();
 | 
			
		||||
 | 
			
		||||
            return new ConfigurationValidationResult(true, errors);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private ConfigurationValidationResult CheckForReRoutesRateLimitOptions(FileConfiguration configuration)
 | 
			
		||||
 
 | 
			
		||||
@@ -144,7 +144,8 @@ namespace Ocelot.DependencyInjection
 | 
			
		||||
            services.TryAddSingleton<IRemoveOutputHeaders, RemoveOutputHeaders>();
 | 
			
		||||
            services.TryAddSingleton<IOcelotConfigurationProvider, OcelotConfigurationProvider>();
 | 
			
		||||
            services.TryAddSingleton<IClaimToThingConfigurationParser, ClaimToThingConfigurationParser>();
 | 
			
		||||
            services.TryAddSingleton<IAuthoriser, ClaimsAuthoriser>();
 | 
			
		||||
            services.TryAddSingleton<IClaimsAuthoriser, ClaimsAuthoriser>();
 | 
			
		||||
            services.TryAddSingleton<IScopesAuthoriser, ScopesAuthoriser>();
 | 
			
		||||
            services.TryAddSingleton<IAddClaimsToRequest, AddClaimsToRequest>();
 | 
			
		||||
            services.TryAddSingleton<IAddHeadersToRequest, AddHeadersToRequest>();
 | 
			
		||||
            services.TryAddSingleton<IAddQueriesToRequest, AddQueriesToRequest>();
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ namespace Ocelot.DownstreamRouteFinder.Finder
 | 
			
		||||
        {
 | 
			
		||||
            var configuration = await _configProvider.Get();
 | 
			
		||||
 | 
			
		||||
            var applicableReRoutes = configuration.Data.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod.Method.ToLower(), upstreamHttpMethod.ToLower(), StringComparison.CurrentCultureIgnoreCase));
 | 
			
		||||
            var applicableReRoutes = configuration.Data.ReRoutes.Where(r => r.UpstreamHttpMethod.Count == 0 || r.UpstreamHttpMethod.Select(x => x.Method.ToLower()).Contains(upstreamHttpMethod.ToLower()));
 | 
			
		||||
 | 
			
		||||
            foreach (var reRoute in applicableReRoutes)
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
@@ -70,7 +70,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
 | 
			
		||||
 | 
			
		||||
        private bool CharactersDontMatch(char characterOne, char characterTwo)
 | 
			
		||||
        {
 | 
			
		||||
            return characterOne != characterTwo;
 | 
			
		||||
            return char.ToLower(characterOne) != char.ToLower(characterTwo);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private bool ContinueScanningUrl(int counterForUrl, int urlLength)
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
        InstructionNotForClaimsError,
 | 
			
		||||
        UnauthorizedError,
 | 
			
		||||
        ClaimValueNotAuthorisedError,
 | 
			
		||||
        ScopeNotAuthorisedError,
 | 
			
		||||
        UserDoesNotHaveClaimError,
 | 
			
		||||
        DownstreamPathTemplateContainsSchemeError,
 | 
			
		||||
        DownstreamPathNullOrEmptyError,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
namespace Ocelot.Infrastructure.Claims.Parser
 | 
			
		||||
{
 | 
			
		||||
    using Errors;
 | 
			
		||||
    using Responses;
 | 
			
		||||
    using System.Collections.Generic;
 | 
			
		||||
    using System.Linq;
 | 
			
		||||
    using System.Security.Claims;
 | 
			
		||||
    using Errors;
 | 
			
		||||
    using Responses;
 | 
			
		||||
 | 
			
		||||
    public class ClaimsParser : IClaimsParser
 | 
			
		||||
    {
 | 
			
		||||
@@ -37,6 +37,17 @@
 | 
			
		||||
            return new OkResponse<string>(value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public Response<List<string>> GetValuesByClaimType(IEnumerable<Claim> claims, string claimType)
 | 
			
		||||
        {
 | 
			
		||||
            List<string> values = new List<string>();
 | 
			
		||||
 | 
			
		||||
            values.AddRange(claims.Where(x => x.Type == claimType).Select(x => x.Value).ToList());
 | 
			
		||||
 | 
			
		||||
            return new OkResponse<List<string>>(values);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        private Response<string> GetValue(IEnumerable<Claim> claims, string key)
 | 
			
		||||
        {
 | 
			
		||||
            var claim = claims.FirstOrDefault(c => c.Type == key);
 | 
			
		||||
 
 | 
			
		||||
@@ -7,5 +7,6 @@
 | 
			
		||||
    public interface IClaimsParser
 | 
			
		||||
    {
 | 
			
		||||
        Response<string> GetValue(IEnumerable<Claim> claims, string key, string delimiter, int index);
 | 
			
		||||
        Response<List<string>> GetValuesByClaimType(IEnumerable<Claim> claims, string claimType);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -45,7 +45,7 @@
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Twitter" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Authentication.MicrosoftAccount" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Authentication" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.0.2" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="1.1.1" />
 | 
			
		||||
    <PackageReference Include="CacheManager.Core" Version="0.9.2" />
 | 
			
		||||
@@ -53,7 +53,7 @@
 | 
			
		||||
    <PackageReference Include="CacheManager.Microsoft.Extensions.Logging" Version="0.9.2" />
 | 
			
		||||
    <PackageReference Include="Consul" Version="0.7.2.1" />
 | 
			
		||||
    <PackageReference Include="Polly" Version="5.0.3" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4" Version="1.0.1" />
 | 
			
		||||
    <PackageReference Include="IdentityServer4" Version="1.5.1" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="1.1.1" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ namespace Ocelot.Responder
 | 
			
		||||
 | 
			
		||||
            if (errors.Any(e => e.Code == OcelotErrorCode.UnauthorizedError 
 | 
			
		||||
                || e.Code == OcelotErrorCode.ClaimValueNotAuthorisedError
 | 
			
		||||
                || e.Code == OcelotErrorCode.ScopeNotAuthorisedError
 | 
			
		||||
                || e.Code == OcelotErrorCode.UserDoesNotHaveClaimError
 | 
			
		||||
                || e.Code == OcelotErrorCode.CannotFindClaimError))
 | 
			
		||||
            {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user