mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-11-04 10:35:28 +08:00 
			
		
		
		
	* testing issue on train * check multiple claims of the same type for authorisation
This commit is contained in:
		@@ -20,22 +20,22 @@ namespace Ocelot.Authorisation
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            foreach (var required in routeClaimsRequirement)
 | 
					            foreach (var required in routeClaimsRequirement)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var value = _claimsParser.GetValue(claimsPrincipal.Claims, required.Key, string.Empty, 0);
 | 
					                var values = _claimsParser.GetValuesByClaimType(claimsPrincipal.Claims, required.Key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (value.IsError)
 | 
					                if (values.IsError)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return new ErrorResponse<bool>(value.Errors);
 | 
					                    return new ErrorResponse<bool>(values.Errors);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (value.Data != null)
 | 
					                if (values.Data != null)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    var authorised = value.Data == required.Value;
 | 
					                    var authorised = values.Data.Contains(required.Value);
 | 
				
			||||||
                    if (!authorised)
 | 
					                    if (!authorised)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        return new ErrorResponse<bool>(new List<Error>
 | 
					                        return new ErrorResponse<bool>(new List<Error>
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            new ClaimValueNotAuthorisedError(
 | 
					                            new ClaimValueNotAuthorisedError(
 | 
				
			||||||
                                $"claim value: {value.Data} is not the same as required value: {required.Value} for type: {required.Key}")
 | 
					                                $"claim value: {values.Data} is not the same as required value: {required.Value} for type: {required.Key}")
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -235,6 +235,66 @@ namespace Ocelot.AcceptanceTests
 | 
				
			|||||||
               .BDDfy();
 | 
					               .BDDfy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_fix_issue_240()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					           var configuration = new FileConfiguration
 | 
				
			||||||
 | 
					           {
 | 
				
			||||||
 | 
					               ReRoutes = new List<FileReRoute>
 | 
				
			||||||
 | 
					                   {
 | 
				
			||||||
 | 
					                       new FileReRoute
 | 
				
			||||||
 | 
					                       {
 | 
				
			||||||
 | 
					                           DownstreamPathTemplate = "/",
 | 
				
			||||||
 | 
					                           DownstreamHostAndPorts = new List<FileHostAndPort>
 | 
				
			||||||
 | 
					                           {
 | 
				
			||||||
 | 
					                               new FileHostAndPort
 | 
				
			||||||
 | 
					                               {
 | 
				
			||||||
 | 
					                                   Host = "localhost",
 | 
				
			||||||
 | 
					                                   Port = 51876,
 | 
				
			||||||
 | 
					                               }
 | 
				
			||||||
 | 
					                           },
 | 
				
			||||||
 | 
					                           DownstreamScheme = "http",
 | 
				
			||||||
 | 
					                           UpstreamPathTemplate = "/",
 | 
				
			||||||
 | 
					                           UpstreamHttpMethod = new List<string> { "Get" },
 | 
				
			||||||
 | 
					                           AuthenticationOptions = new FileAuthenticationOptions
 | 
				
			||||||
 | 
					                           {
 | 
				
			||||||
 | 
					                               AuthenticationProviderKey = "Test"
 | 
				
			||||||
 | 
					                           },
 | 
				
			||||||
 | 
					                           RouteClaimsRequirement =
 | 
				
			||||||
 | 
					                           {
 | 
				
			||||||
 | 
					                               {"Role", "User"}
 | 
				
			||||||
 | 
					                           }
 | 
				
			||||||
 | 
					                       }
 | 
				
			||||||
 | 
					                   }
 | 
				
			||||||
 | 
					           };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var users = new List<TestUser>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                new TestUser
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Username = "test",
 | 
				
			||||||
 | 
					                    Password = "test",
 | 
				
			||||||
 | 
					                    SubjectId = "registered|1231231",
 | 
				
			||||||
 | 
					                    Claims = new List<Claim>
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        new Claim("Role", "AdminUser"), 
 | 
				
			||||||
 | 
					                        new Claim("Role", "User")
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					           this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888", "api", AccessTokenType.Jwt, users))
 | 
				
			||||||
 | 
					               .And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 200, "Hello from Laura"))
 | 
				
			||||||
 | 
					               .And(x => _steps.GivenIHaveAToken("http://localhost:51888"))
 | 
				
			||||||
 | 
					               .And(x => _steps.GivenThereIsAConfiguration(configuration))
 | 
				
			||||||
 | 
					               .And(x => _steps.GivenOcelotIsRunning(_options, "Test"))
 | 
				
			||||||
 | 
					               .And(x => _steps.GivenIHaveAddedATokenToMyRequest())
 | 
				
			||||||
 | 
					               .When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
 | 
				
			||||||
 | 
					               .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
 | 
				
			||||||
 | 
					               .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
 | 
				
			||||||
 | 
					               .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
 | 
					        private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            _servicebuilder = new WebHostBuilder()
 | 
					            _servicebuilder = new WebHostBuilder()
 | 
				
			||||||
@@ -335,7 +395,75 @@ namespace Ocelot.AcceptanceTests
 | 
				
			|||||||
            _identityServerBuilder.Start();
 | 
					            _identityServerBuilder.Start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _steps.VerifyIdentiryServerStarted(url);
 | 
					            _steps.VerifyIdentiryServerStarted(url);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType, List<TestUser> users)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            _identityServerBuilder = new WebHostBuilder()
 | 
				
			||||||
 | 
					                .UseUrls(url)
 | 
				
			||||||
 | 
					                .UseKestrel()
 | 
				
			||||||
 | 
					                .UseContentRoot(Directory.GetCurrentDirectory())
 | 
				
			||||||
 | 
					                .UseIISIntegration()
 | 
				
			||||||
 | 
					                .UseUrls(url)
 | 
				
			||||||
 | 
					                .ConfigureServices(services =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    services.AddLogging();
 | 
				
			||||||
 | 
					                    services.AddIdentityServer()
 | 
				
			||||||
 | 
					                        .AddDeveloperSigningCredential()
 | 
				
			||||||
 | 
					                        .AddInMemoryApiResources(new List<ApiResource>
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            new ApiResource
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                Name = apiName,
 | 
				
			||||||
 | 
					                                Description = "My API",
 | 
				
			||||||
 | 
					                                Enabled = true,
 | 
				
			||||||
 | 
					                                DisplayName = "test",
 | 
				
			||||||
 | 
					                                Scopes = new List<Scope>()
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    new Scope("api"),
 | 
				
			||||||
 | 
					                                    new Scope("api.readOnly"),
 | 
				
			||||||
 | 
					                                    new Scope("openid"),
 | 
				
			||||||
 | 
					                                    new Scope("offline_access"),
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                                ApiSecrets = new List<Secret>()
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    new Secret
 | 
				
			||||||
 | 
					                                    {
 | 
				
			||||||
 | 
					                                        Value = "secret".Sha256()
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
 | 
					                                UserClaims = new List<string>()
 | 
				
			||||||
 | 
					                                {
 | 
				
			||||||
 | 
					                                    "CustomerId", "LocationId", "UserType", "UserId", "Role"
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        .AddInMemoryClients(new List<Client>
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            new Client
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                ClientId = "client",
 | 
				
			||||||
 | 
					                                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
 | 
				
			||||||
 | 
					                                ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
 | 
				
			||||||
 | 
					                                AllowedScopes = new List<string> { apiName, "api.readOnly", "openid", "offline_access" },
 | 
				
			||||||
 | 
					                                AccessTokenType = tokenType,
 | 
				
			||||||
 | 
					                                Enabled = true,
 | 
				
			||||||
 | 
					                                RequireClientSecret = false,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        .AddTestUsers(users);
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Configure(app =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    app.UseIdentityServer();
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .Build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _identityServerBuilder.Start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _steps.VerifyIdentiryServerStarted(url);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public void Dispose()
 | 
					        public void Dispose()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,7 +27,25 @@ namespace Ocelot.UnitTests.Authorization
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
 | 
					            this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    new Claim("UserType", "registered")
 | 
					                    new Claim("UserType", "registered"),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }))))
 | 
				
			||||||
 | 
					                .And(x => x.GivenARouteClaimsRequirement(new Dictionary<string, string>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    {"UserType", "registered"}
 | 
				
			||||||
 | 
					                }))
 | 
				
			||||||
 | 
					                .When(x => x.WhenICallTheAuthoriser())
 | 
				
			||||||
 | 
					                .Then(x => x.ThenTheUserIsAuthorised())
 | 
				
			||||||
 | 
					                .BDDfy();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Fact]
 | 
				
			||||||
 | 
					        public void should_authorise_user_multiple_claims_of_same_type()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.Given(x => x.GivenAClaimsPrincipal(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    new Claim("UserType", "guest"),
 | 
				
			||||||
 | 
					                    new Claim("UserType", "registered"),
 | 
				
			||||||
                }))))
 | 
					                }))))
 | 
				
			||||||
                .And(x => x.GivenARouteClaimsRequirement(new Dictionary<string, string>
 | 
					                .And(x => x.GivenARouteClaimsRequirement(new Dictionary<string, string>
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user