Feature/fix #240 (#243)

* testing issue on train

* check multiple claims of the same type for authorisation
This commit is contained in:
Tom Pallister 2018-02-21 20:53:46 +00:00 committed by GitHub
parent 1e48a97294
commit 9f7478c91f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 153 additions and 7 deletions

View File

@ -20,22 +20,22 @@ namespace Ocelot.Authorisation
{
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)
{
return new ErrorResponse<bool>(new List<Error>
{
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}")
});
}
}

View File

@ -235,6 +235,66 @@ namespace Ocelot.AcceptanceTests
.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)
{
_servicebuilder = new WebHostBuilder()
@ -335,7 +395,75 @@ namespace Ocelot.AcceptanceTests
_identityServerBuilder.Start();
_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()

View File

@ -27,7 +27,25 @@ namespace Ocelot.UnitTests.Authorization
{
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>
{