Adds two acceptance tests that checks two scenarios:

- Get 401 when we do a request to api with a token issued to other api
- Get 403 when we do a request to scope not allowed
This commit is contained in:
Juan Carlos Santana Herrera 2017-05-17 15:06:21 +01:00
parent 89375111fc
commit 30a5227e1e
2 changed files with 167 additions and 17 deletions

View File

@ -51,18 +51,18 @@ namespace Ocelot.AcceptanceTests
UpstreamHttpMethod = new List<string> { "Post" }, UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
Provider = "IdentityServer", Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl, ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false, RequireHttps = false,
ApiName = "api", ApiName = "api",
ApiSecret = "secret" ApiSecret = "secret"
} }
} }
} }
}; };
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt)) this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning()) .And(x => _steps.GivenOcelotIsRunning())
@ -89,18 +89,18 @@ namespace Ocelot.AcceptanceTests
UpstreamHttpMethod = new List<string> { "Post" }, UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
Provider = "IdentityServer", Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl, ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false, RequireHttps = false,
ApiName = "api", ApiName = "api",
ApiSecret = "secret" ApiSecret = "secret"
} }
} }
} }
}; };
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Reference)) this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Reference))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning()) .And(x => _steps.GivenOcelotIsRunning())
@ -127,18 +127,18 @@ namespace Ocelot.AcceptanceTests
UpstreamHttpMethod = new List<string> { "Get" }, UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
Provider = "IdentityServer", Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl, ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false, RequireHttps = false,
ApiName = "api", ApiName = "api",
ApiSecret = "secret" ApiSecret = "secret"
} }
} }
} }
}; };
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt)) this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura")) .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -150,6 +150,84 @@ namespace Ocelot.AcceptanceTests
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_return_response_401_using_identity_server_with_token_requested_for_other_api()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = _downstreamServicePath,
DownstreamPort = _downstreamServicePort,
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>(),
Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false,
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveATokenForApi2(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Unauthorized))
.BDDfy();
}
[Fact]
public void should_return_response_403_using_identity_server_with_scope_not_allowed()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = _downstreamServicePath,
DownstreamPort = _downstreamServicePort,
DownstreamHost = _downstreamServiceHost,
DownstreamScheme = _downstreamServiceScheme,
UpstreamPathTemplate = "/",
UpstreamHttpMethod = new List<string> { "Get" },
AuthenticationOptions = new FileAuthenticationOptions
{
AllowedScopes = new List<string>{ "api", "openid", "offline_access" },
Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false,
ApiName = "api",
ApiSecret = "secret"
}
}
}
};
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 200, "Hello from Laura"))
.And(x => _steps.GivenIHaveATokenForApiReadOnlyScope(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.And(x => _steps.GivenIHaveAddedATokenToMyRequest())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.Forbidden))
.BDDfy();
}
[Fact] [Fact]
public void should_return_201_using_identity_server_access_token() public void should_return_201_using_identity_server_access_token()
{ {
@ -168,18 +246,18 @@ namespace Ocelot.AcceptanceTests
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
Provider = "IdentityServer", Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl, ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false, RequireHttps = false,
ApiName = "api", ApiName = "api",
ApiSecret = "secret" ApiSecret = "secret"
} }
} }
} }
}; };
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Jwt)) this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Jwt))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -208,18 +286,18 @@ namespace Ocelot.AcceptanceTests
UpstreamHttpMethod = new List<string> { "Post" }, UpstreamHttpMethod = new List<string> { "Post" },
AuthenticationOptions = new FileAuthenticationOptions AuthenticationOptions = new FileAuthenticationOptions
{ {
AllowedScopes = new List<string>(), AllowedScopes = new List<string>(),
Provider = "IdentityServer", Provider = "IdentityServer",
ProviderRootUrl = _identityServerRootUrl, ProviderRootUrl = _identityServerRootUrl,
RequireHttps = false, RequireHttps = false,
ApiName = "api", ApiName = "api",
ApiSecret = "secret" ApiSecret = "secret"
} }
} }
} }
}; };
this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", AccessTokenType.Reference)) this.Given(x => x.GivenThereIsAnIdentityServerOn(_identityServerRootUrl, "api", "api2", AccessTokenType.Reference))
.And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty)) .And(x => x.GivenThereIsAServiceRunningOn(_downstreamServiceUrl, 201, string.Empty))
.And(x => _steps.GivenIHaveAToken(_identityServerRootUrl)) .And(x => _steps.GivenIHaveAToken(_identityServerRootUrl))
.And(x => _steps.GivenThereIsAConfiguration(configuration)) .And(x => _steps.GivenThereIsAConfiguration(configuration))
@ -252,7 +330,7 @@ namespace Ocelot.AcceptanceTests
_servicebuilder.Start(); _servicebuilder.Start();
} }
private void GivenThereIsAnIdentityServerOn(string url, string apiName, AccessTokenType tokenType) private void GivenThereIsAnIdentityServerOn(string url, string apiName, string api2Name, AccessTokenType tokenType)
{ {
_identityServerBuilder = new WebHostBuilder() _identityServerBuilder = new WebHostBuilder()
.UseUrls(url) .UseUrls(url)
@ -276,6 +354,32 @@ namespace Ocelot.AcceptanceTests
Scopes = new List<Scope>() Scopes = new List<Scope>()
{ {
new Scope("api"), 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"
}
},
new ApiResource
{
Name = api2Name,
Description = "My second API",
Enabled = true,
DisplayName = "second test",
Scopes = new List<Scope>()
{
new Scope("api2"),
new Scope("api2.readOnly"),
new Scope("openid"), new Scope("openid"),
new Scope("offline_access") new Scope("offline_access")
}, },
@ -299,7 +403,7 @@ namespace Ocelot.AcceptanceTests
ClientId = "client", ClientId = "client",
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
ClientSecrets = new List<Secret> {new Secret("secret".Sha256())}, ClientSecrets = new List<Secret> {new Secret("secret".Sha256())},
AllowedScopes = new List<string> { apiName, "openid", "offline_access" }, AllowedScopes = new List<string> { apiName, api2Name, "api.readOnly", "openid", "offline_access" },
AccessTokenType = tokenType, AccessTokenType = tokenType,
Enabled = true, Enabled = true,
RequireClientSecret = false RequireClientSecret = false

View File

@ -199,6 +199,52 @@ namespace Ocelot.AcceptanceTests
} }
} }
public void GivenIHaveATokenForApiReadOnlyScope(string url)
{
var tokenUrl = $"{url}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "client"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "api.readOnly"),
new KeyValuePair<string, string>("username", "test"),
new KeyValuePair<string, string>("password", "test"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
}
public void GivenIHaveATokenForApi2(string url)
{
var tokenUrl = $"{url}/connect/token";
var formData = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("client_id", "client"),
new KeyValuePair<string, string>("client_secret", "secret"),
new KeyValuePair<string, string>("scope", "api2"),
new KeyValuePair<string, string>("username", "test"),
new KeyValuePair<string, string>("password", "test"),
new KeyValuePair<string, string>("grant_type", "password")
};
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var response = httpClient.PostAsync(tokenUrl, content).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
response.EnsureSuccessStatusCode();
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
}
}
public void GivenIHaveAnOcelotToken(string adminPath) public void GivenIHaveAnOcelotToken(string adminPath)
{ {
var tokenUrl = $"{adminPath}/connect/token"; var tokenUrl = $"{adminPath}/connect/token";