mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 14:02:49 +08:00
got identity server access token acceptance test working, created factory for choosing auth handlers, a creator for making the auth handlers, some general refactoring...next step is injecting the config for the auth handler creator in some way or just passing it in
This commit is contained in:
parent
34bac7e0d4
commit
320b442526
@ -0,0 +1,16 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Authentication
|
||||
{
|
||||
public class AuthenticationHandler
|
||||
{
|
||||
public AuthenticationHandler(string provider, RequestDelegate handler)
|
||||
{
|
||||
Provider = provider;
|
||||
Handler = handler;
|
||||
}
|
||||
|
||||
public string Provider { get; private set; }
|
||||
public RequestDelegate Handler { get; private set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Library.Infrastructure.Responses;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Authentication
|
||||
{
|
||||
/// <summary>
|
||||
/// Cannot unit test things in this class due to use of extension methods
|
||||
/// </summary>
|
||||
public class AuthenticationHandlerCreator : IAuthenticationHandlerCreator
|
||||
{
|
||||
public Response<RequestDelegate> CreateIdentityServerAuthenticationHandler(IApplicationBuilder app)
|
||||
{
|
||||
var builder = app.New();
|
||||
|
||||
builder.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||
{
|
||||
//todo sort these options out
|
||||
Authority = "http://localhost:51888",
|
||||
ScopeName = "api",
|
||||
|
||||
RequireHttpsMetadata = false
|
||||
});
|
||||
|
||||
builder.UseMvc();
|
||||
|
||||
var authenticationNext = builder.Build();
|
||||
|
||||
return new OkResponse<RequestDelegate>(authenticationNext);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Ocelot.Library.Infrastructure.Errors;
|
||||
using Ocelot.Library.Infrastructure.Responses;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Authentication
|
||||
{
|
||||
public class AuthenticationProviderFactory : IAuthenticationProviderFactory
|
||||
{
|
||||
private readonly IAuthenticationHandlerCreator _creator;
|
||||
|
||||
public AuthenticationProviderFactory(IAuthenticationHandlerCreator creator)
|
||||
{
|
||||
_creator = creator;
|
||||
}
|
||||
|
||||
public Response<AuthenticationHandler> Get(string provider, IApplicationBuilder app)
|
||||
{
|
||||
var handler = _creator.CreateIdentityServerAuthenticationHandler(app);
|
||||
|
||||
if (!handler.IsError)
|
||||
{
|
||||
return new OkResponse<AuthenticationHandler>(new AuthenticationHandler(provider, handler.Data));
|
||||
}
|
||||
|
||||
return new ErrorResponse<AuthenticationHandler>(new List<Error>
|
||||
{
|
||||
new UnableToCreateAuthenticationHandlerError($"Unable to create authentication handler for {provider}")
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Library.Infrastructure.Responses;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Authentication
|
||||
{
|
||||
public interface IAuthenticationHandlerCreator
|
||||
{
|
||||
Response<RequestDelegate> CreateIdentityServerAuthenticationHandler(IApplicationBuilder app);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Ocelot.Library.Infrastructure.Responses;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Authentication
|
||||
{
|
||||
public interface IAuthenticationProviderFactory
|
||||
{
|
||||
Response<AuthenticationHandler> Get(string provider, IApplicationBuilder app);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
using Ocelot.Library.Infrastructure.Errors;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Authentication
|
||||
{
|
||||
public class UnableToCreateAuthenticationHandlerError : Error
|
||||
{
|
||||
public UnableToCreateAuthenticationHandlerError(string message)
|
||||
: base(message, OcelotErrorCode.UnableToCreateAuthenticationHandlerError)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
UnableToFindDownstreamRouteError,
|
||||
CannotAddDataError,
|
||||
CannotFindDataError,
|
||||
UnableToCompleteRequestError
|
||||
UnableToCompleteRequestError,
|
||||
UnableToCreateAuthenticationHandlerError
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@ -7,6 +8,11 @@ using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||
using Ocelot.Library.Infrastructure.Errors;
|
||||
using Ocelot.Library.Infrastructure.Repository;
|
||||
using Ocelot.Library.Infrastructure.Responses;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Ocelot.Library.Infrastructure.Authentication;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Middleware
|
||||
{
|
||||
@ -16,13 +22,15 @@ namespace Ocelot.Library.Infrastructure.Middleware
|
||||
private RequestDelegate _authenticationNext;
|
||||
private readonly IScopedRequestDataRepository _scopedRequestDataRepository;
|
||||
private readonly IApplicationBuilder _app;
|
||||
private readonly IAuthenticationProviderFactory _authProviderFactory;
|
||||
|
||||
public AuthenticationMiddleware(RequestDelegate next, IApplicationBuilder app,
|
||||
IScopedRequestDataRepository scopedRequestDataRepository)
|
||||
IScopedRequestDataRepository scopedRequestDataRepository, IAuthenticationProviderFactory authProviderFactory)
|
||||
: base(scopedRequestDataRepository)
|
||||
{
|
||||
_next = next;
|
||||
_scopedRequestDataRepository = scopedRequestDataRepository;
|
||||
_authProviderFactory = authProviderFactory;
|
||||
_app = app;
|
||||
}
|
||||
|
||||
@ -38,25 +46,17 @@ namespace Ocelot.Library.Infrastructure.Middleware
|
||||
|
||||
if (IsAuthenticatedRoute(downstreamRoute.Data.ReRoute))
|
||||
{
|
||||
//todo - build auth pipeline and then call normal pipeline if all good?
|
||||
//create new app builder
|
||||
var builder = _app.New();
|
||||
//set up any options for the authentication
|
||||
var jwtBearerOptions = new JwtBearerOptions
|
||||
var authenticationNext = _authProviderFactory.Get(downstreamRoute.Data.ReRoute.AuthenticationProvider, _app);
|
||||
|
||||
if (!authenticationNext.IsError)
|
||||
{
|
||||
AutomaticAuthenticate = true,
|
||||
AutomaticChallenge = true,
|
||||
RequireHttpsMetadata = false,
|
||||
};
|
||||
//set the authentication middleware
|
||||
builder.UseJwtBearerAuthentication(jwtBearerOptions);
|
||||
//use mvc so we hit the catch all authorised controller
|
||||
builder.UseMvc();
|
||||
//then build it
|
||||
_authenticationNext = builder.Build();
|
||||
//then call it
|
||||
await _authenticationNext(context);
|
||||
//check if the user is authenticated
|
||||
await authenticationNext.Data.Handler.Invoke(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPipelineError(authenticationNext.Errors);
|
||||
}
|
||||
|
||||
if (context.User.Identity.IsAuthenticated)
|
||||
{
|
||||
await _next.Invoke(context);
|
||||
|
@ -43,7 +43,6 @@ namespace Ocelot.Library.Infrastructure.Middleware
|
||||
{
|
||||
await _responder.CreateErrorResponse(context, 500);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4,6 +4,10 @@ using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace Ocelot.Library.Infrastructure.Responder
|
||||
{
|
||||
/// <summary>
|
||||
/// Cannot unit test things in this class due to methods not being implemented
|
||||
/// on .net concretes used for testing
|
||||
/// </summary>
|
||||
public class HttpContextResponder : IHttpResponder
|
||||
{
|
||||
public async Task<HttpContext> CreateResponse(HttpContext context, HttpResponseMessage response)
|
||||
|
@ -27,7 +27,8 @@
|
||||
"Microsoft.AspNetCore.Authentication.Facebook": "1.0.0",
|
||||
"Microsoft.AspNetCore.Authentication.Twitter": "1.0.0",
|
||||
"Microsoft.AspNetCore.Authentication.MicrosoftAccount": "1.0.0",
|
||||
"Microsoft.AspNetCore.Authentication": "1.0.0"
|
||||
"Microsoft.AspNetCore.Authentication": "1.0.0",
|
||||
"IdentityServer4.AccessTokenValidation": "1.0.1-rc2"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
|
@ -7,6 +7,7 @@ using Microsoft.Extensions.Configuration.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Ocelot.Library.Infrastructure.Authentication;
|
||||
using Ocelot.Library.Infrastructure.Configuration;
|
||||
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||
@ -41,6 +42,7 @@ namespace Ocelot
|
||||
{
|
||||
services.AddOptions();
|
||||
services.AddMvc();
|
||||
services.AddMvcCore().AddAuthorization().AddJsonFormatters();
|
||||
|
||||
services.Configure<YamlConfiguration>(Configuration);
|
||||
services.AddAuthentication();
|
||||
@ -55,6 +57,8 @@ namespace Ocelot
|
||||
services.AddSingleton<IHttpResponder, HttpContextResponder>();
|
||||
services.AddSingleton<IRequestBuilder, HttpRequestBuilder>();
|
||||
services.AddSingleton<IErrorsToHttpStatusCodeMapper, ErrorsToHttpStatusCodeMapper>();
|
||||
services.AddSingleton<IAuthenticationProviderFactory, AuthenticationProviderFactory>();
|
||||
services.AddSingleton<IAuthenticationHandlerCreator, AuthenticationHandlerCreator>();
|
||||
|
||||
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
|
||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Encodings.Web;
|
||||
using IdentityServer4.Models;
|
||||
using IdentityServer4.Services.InMemory;
|
||||
@ -11,6 +12,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Newtonsoft.Json;
|
||||
using Ocelot.Library.Infrastructure.Configuration.Yaml;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
@ -21,17 +23,17 @@ namespace Ocelot.AcceptanceTests
|
||||
{
|
||||
public class AuthenticationTests : IDisposable
|
||||
{
|
||||
private TestServer _server;
|
||||
private HttpClient _client;
|
||||
private TestServer _ocelotServer;
|
||||
private HttpClient _ocelotClient;
|
||||
private HttpResponseMessage _response;
|
||||
private readonly string _configurationPath;
|
||||
private StringContent _postContent;
|
||||
private IWebHost _builder;
|
||||
private IWebHost _ocelotBbuilder;
|
||||
|
||||
// Sadly we need to change this when we update the netcoreapp version to make the test update the config correctly
|
||||
private double _netCoreAppVersion = 1.4;
|
||||
private HttpClient _idServerClient;
|
||||
private TestServer _idServer;
|
||||
private BearerToken _token;
|
||||
private IWebHost _identityServerBuilder;
|
||||
|
||||
public AuthenticationTests()
|
||||
{
|
||||
@ -39,7 +41,7 @@ namespace Ocelot.AcceptanceTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_401_using_jwt()
|
||||
public void should_return_401_using_identity_server_access_token()
|
||||
{
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888"))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
||||
@ -63,6 +65,33 @@ namespace Ocelot.AcceptanceTests
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_201_using_identity_server_access_token()
|
||||
{
|
||||
this.Given(x => x.GivenThereIsAnIdentityServerOn("http://localhost:51888"))
|
||||
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", 201, string.Empty))
|
||||
.And(x => x.GivenIHaveAToken("http://localhost:51888"))
|
||||
.And(x => x.GivenThereIsAConfiguration(new YamlConfiguration
|
||||
{
|
||||
ReRoutes = new List<YamlReRoute>
|
||||
{
|
||||
new YamlReRoute
|
||||
{
|
||||
DownstreamTemplate = "http://localhost:51876/",
|
||||
UpstreamTemplate = "/",
|
||||
UpstreamHttpMethod = "Post",
|
||||
Authentication = "JwtBearerAuthentication"
|
||||
}
|
||||
}
|
||||
}))
|
||||
.And(x => x.GivenTheApiGatewayIsRunning())
|
||||
.And(x => x.GivenIHaveAddedATokenToMyRequest())
|
||||
.And(x => x.GivenThePostHasContent("postContent"))
|
||||
.When(x => x.WhenIPostUrlOnTheApiGateway("/"))
|
||||
.Then(x => x.ThenTheStatusCodeShouldBe(HttpStatusCode.Created))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenThePostHasContent(string postcontent)
|
||||
{
|
||||
_postContent = new StringContent(postcontent);
|
||||
@ -73,10 +102,10 @@ namespace Ocelot.AcceptanceTests
|
||||
/// </summary>
|
||||
private void GivenTheApiGatewayIsRunning()
|
||||
{
|
||||
_server = new TestServer(new WebHostBuilder()
|
||||
_ocelotServer = new TestServer(new WebHostBuilder()
|
||||
.UseStartup<Startup>());
|
||||
|
||||
_client = _server.CreateClient();
|
||||
_ocelotClient = _ocelotServer.CreateClient();
|
||||
}
|
||||
|
||||
private void GivenThereIsAConfiguration(YamlConfiguration yamlConfiguration)
|
||||
@ -96,7 +125,7 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
private void GivenThereIsAServiceRunningOn(string url, int statusCode, string responseBody)
|
||||
{
|
||||
_builder = new WebHostBuilder()
|
||||
_ocelotBbuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
@ -112,12 +141,12 @@ namespace Ocelot.AcceptanceTests
|
||||
})
|
||||
.Build();
|
||||
|
||||
_builder.Start();
|
||||
_ocelotBbuilder.Start();
|
||||
}
|
||||
|
||||
private void GivenThereIsAnIdentityServerOn(string url)
|
||||
{
|
||||
var builder = new WebHostBuilder()
|
||||
_identityServerBuilder = new WebHostBuilder()
|
||||
.UseUrls(url)
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
@ -126,41 +155,51 @@ namespace Ocelot.AcceptanceTests
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddDeveloperIdentityServer()
|
||||
.AddInMemoryClients(new List<Client> {
|
||||
new Client
|
||||
{
|
||||
ClientId = "test",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> { new Secret("test".Sha256()) },
|
||||
AllowedScopes = new List<string> { "api1" },
|
||||
AllowAccessToAllScopes = true,
|
||||
AccessTokenType = AccessTokenType.Jwt,
|
||||
Enabled = true
|
||||
|
||||
} })
|
||||
.AddInMemoryScopes(new List<Scope> { new Scope
|
||||
{
|
||||
Name = "api1",
|
||||
Name = "api",
|
||||
Description = "My API",
|
||||
Enabled = true
|
||||
|
||||
}})
|
||||
.AddInMemoryClients(new List<Client> {
|
||||
new Client
|
||||
{
|
||||
ClientId = "client",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
ClientSecrets = new List<Secret> { new Secret("secret".Sha256()) },
|
||||
AllowedScopes = new List<string> { "api" },
|
||||
AccessTokenType = AccessTokenType.Jwt,
|
||||
Enabled = true,
|
||||
RequireClientSecret = false
|
||||
} })
|
||||
.AddInMemoryUsers(new List<InMemoryUser> { new InMemoryUser
|
||||
{
|
||||
Username = "test", Password = "test", Enabled = true, Subject = "asdads"
|
||||
Username = "test",
|
||||
Password = "test",
|
||||
Enabled = true,
|
||||
Subject = "asdads"
|
||||
}});
|
||||
})
|
||||
.Configure(app =>
|
||||
{
|
||||
app.UseIdentityServer();
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_idServer = new TestServer(builder);
|
||||
_idServerClient = _idServer.CreateClient();
|
||||
_identityServerBuilder.Start();
|
||||
|
||||
var response = _idServerClient.GetAsync($"{url}/.well-known/openid-configuration").Result;
|
||||
VerifyIdentiryServerStarted(url);
|
||||
|
||||
}
|
||||
|
||||
private void VerifyIdentiryServerStarted(string url)
|
||||
{
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
var response = httpClient.GetAsync($"{url}/.well-known/openid-configuration").Result;
|
||||
response.EnsureSuccessStatusCode();
|
||||
var content = response.Content.ReadAsStringAsync().Result;
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenIHaveAToken(string url)
|
||||
@ -168,21 +207,32 @@ namespace Ocelot.AcceptanceTests
|
||||
var tokenUrl = $"{url}/connect/token";
|
||||
var formData = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("client_id", "test"),
|
||||
new KeyValuePair<string, string>("client_secret", "test".Sha256()),
|
||||
new KeyValuePair<string, string>("scope", "api1"),
|
||||
new KeyValuePair<string, string>("client_id", "client"),
|
||||
new KeyValuePair<string, string>("client_secret", "secret"),
|
||||
new KeyValuePair<string, string>("scope", "api"),
|
||||
new KeyValuePair<string, string>("username", "test"),
|
||||
new KeyValuePair<string, string>("password", "test"),
|
||||
new KeyValuePair<string, string>("grant_type", "password")
|
||||
};
|
||||
var content = new FormUrlEncodedContent(formData);
|
||||
var response = _idServerClient.PostAsync(tokenUrl, content).Result;
|
||||
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
var response = httpClient.PostAsync(tokenUrl, content).Result;
|
||||
response.EnsureSuccessStatusCode();
|
||||
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenIHaveAddedATokenToMyRequest()
|
||||
{
|
||||
_ocelotClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
|
||||
}
|
||||
|
||||
private void WhenIPostUrlOnTheApiGateway(string url)
|
||||
{
|
||||
_response = _client.PostAsync(url, _postContent).Result;
|
||||
_response = _ocelotClient.PostAsync(url, _postContent).Result;
|
||||
}
|
||||
|
||||
private void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
|
||||
@ -192,11 +242,22 @@ namespace Ocelot.AcceptanceTests
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_idServerClient?.Dispose();
|
||||
_idServer?.Dispose();
|
||||
_builder?.Dispose();
|
||||
_client.Dispose();
|
||||
_server.Dispose();
|
||||
_ocelotBbuilder?.Dispose();
|
||||
_ocelotClient?.Dispose();
|
||||
_ocelotServer?.Dispose();
|
||||
_identityServerBuilder?.Dispose();
|
||||
}
|
||||
|
||||
class BearerToken
|
||||
{
|
||||
[JsonProperty("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
[JsonProperty("expires_in")]
|
||||
public int ExpiresIn { get; set; }
|
||||
|
||||
[JsonProperty("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,4 +2,4 @@ ReRoutes:
|
||||
- DownstreamTemplate: http://localhost:51879/
|
||||
UpstreamTemplate: /
|
||||
UpstreamHttpMethod: Get
|
||||
Authentication: IdentityServer
|
||||
Authentication: IdentityServer.AccessToken
|
||||
|
@ -0,0 +1,88 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Library.Infrastructure.Authentication;
|
||||
using Ocelot.Library.Infrastructure.Errors;
|
||||
using Ocelot.Library.Infrastructure.Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Authentication
|
||||
{
|
||||
public class AuthenticationProviderFactoryTests
|
||||
{
|
||||
private readonly IAuthenticationProviderFactory _authenticationProviderFactory;
|
||||
private readonly Mock<IApplicationBuilder> _app;
|
||||
private readonly Mock<IAuthenticationHandlerCreator> _creator;
|
||||
|
||||
private string _provider;
|
||||
private Response<AuthenticationHandler> _result;
|
||||
|
||||
public AuthenticationProviderFactoryTests()
|
||||
{
|
||||
_app = new Mock<IApplicationBuilder>();
|
||||
_creator = new Mock<IAuthenticationHandlerCreator>();
|
||||
_authenticationProviderFactory = new AuthenticationProviderFactory(_creator.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_identity_server_access_token_provider()
|
||||
{
|
||||
this.Given(x => x.GivenTheProviderIs("IdentityServer.AccessToken"))
|
||||
.And(x => x.GivenTheCreatorReturns())
|
||||
.When(x => x.WhenIGetFromTheFactory())
|
||||
.Then(x => x.ThenTheHandlerIsReturned("IdentityServer.AccessToken"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_cannot_create_handler()
|
||||
{
|
||||
this.Given(x => x.GivenTheProviderIs("IdentityServer.AccessToken"))
|
||||
.And(x => x.GivenTheCreatorReturnsAnError())
|
||||
.When(x => x.WhenIGetFromTheFactory())
|
||||
.Then(x => x.ThenAnErrorResponseIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheCreatorReturnsAnError()
|
||||
{
|
||||
_creator
|
||||
.Setup(x => x.CreateIdentityServerAuthenticationHandler(It.IsAny<IApplicationBuilder>()))
|
||||
.Returns(new ErrorResponse<RequestDelegate>(new List<Error>
|
||||
{
|
||||
new UnableToCreateAuthenticationHandlerError($"Unable to create authentication handler for xxx")
|
||||
}));
|
||||
}
|
||||
|
||||
private void GivenTheCreatorReturns()
|
||||
{
|
||||
_creator
|
||||
.Setup(x => x.CreateIdentityServerAuthenticationHandler(It.IsAny<IApplicationBuilder>()))
|
||||
.Returns(new OkResponse<RequestDelegate>(x => Task.CompletedTask));
|
||||
}
|
||||
|
||||
private void GivenTheProviderIs(string provider)
|
||||
{
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
private void WhenIGetFromTheFactory()
|
||||
{
|
||||
_result = _authenticationProviderFactory.Get(_provider, _app.Object);
|
||||
}
|
||||
|
||||
private void ThenTheHandlerIsReturned(string expected)
|
||||
{
|
||||
_result.Data.Provider.ShouldBe(expected);
|
||||
}
|
||||
|
||||
private void ThenAnErrorResponseIsReturned()
|
||||
{
|
||||
_result.IsError.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Library.Infrastructure.Authentication;
|
||||
using Ocelot.Library.Infrastructure.DownstreamRouteFinder;
|
||||
using Ocelot.Library.Infrastructure.Middleware;
|
||||
using Ocelot.Library.Infrastructure.Repository;
|
||||
@ -21,6 +22,7 @@ namespace Ocelot.UnitTests.Middleware
|
||||
public class AuthenticationMiddlewareTests : IDisposable
|
||||
{
|
||||
private readonly Mock<IScopedRequestDataRepository> _scopedRepository;
|
||||
private readonly Mock<IAuthenticationProviderFactory> _authFactory;
|
||||
private readonly string _url;
|
||||
private readonly TestServer _server;
|
||||
private readonly HttpClient _client;
|
||||
@ -31,10 +33,11 @@ namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
_url = "http://localhost:51879";
|
||||
_scopedRepository = new Mock<IScopedRequestDataRepository>();
|
||||
|
||||
_authFactory = new Mock<IAuthenticationProviderFactory>();
|
||||
var builder = new WebHostBuilder()
|
||||
.ConfigureServices(x =>
|
||||
{
|
||||
x.AddSingleton(_authFactory.Object);
|
||||
x.AddSingleton(_scopedRepository.Object);
|
||||
})
|
||||
.UseUrls(_url)
|
||||
|
Loading…
x
Reference in New Issue
Block a user