Skip to content
16 changes: 16 additions & 0 deletions src/Ocelot/Middleware/OcelotPipelineConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ public class OcelotPipelineConfiguration
/// <value>A <see cref="Func{T1, T2, T3}"/> delegate object.</value>
public Func<HttpContext, Func<Task>, Task> AuthenticationMiddleware { get; set; }

/// <summary>
/// This is to allow the user to run any extra authentication after the Ocelot authentication kicks in.
/// </summary>
/// <value>
/// A <see cref="Func{HttpContext, TFunc, Task}"/> delegate object.
/// </value>
public Func<HttpContext, Func<Task>, Task> AfterAuthenticationMiddleware { get; set; }

/// <summary>This is to allow the user to run any extra authorization before the Ocelot authorization kicks in.</summary>
/// <value>A <see cref="Func{T1, T2, T3}"/> delegate object.</value>
public Func<HttpContext, Func<Task>, Task> PreAuthorizationMiddleware { get; set; }
Expand All @@ -33,6 +41,14 @@ public class OcelotPipelineConfiguration
/// <value>A <see cref="Func{T1, T2, T3}"/> delegate object.</value>
public Func<HttpContext, Func<Task>, Task> AuthorizationMiddleware { get; set; }

/// <summary>
/// This is to allow the user to run any extra authorization after the Ocelot authorization kicks in.
/// </summary>
/// <value>
/// A <see cref="Func{HttpContext, TFunc, Task}"/> delegate object.
/// </value>
public Func<HttpContext, Func<Task>, Task> AfterAuthorizationMiddleware { get; set; }

/// <summary>This allows the user to completely override Ocelot's <see cref="Headers.Middleware.ClaimsToHeadersMiddleware"/>.</summary>
/// <value>A <see cref="Func{T1, T2, T3}"/> delegate object.</value>
public Func<HttpContext, Func<Task>, Task> ClaimsToHeadersMiddleware { get; set; }
Expand Down
6 changes: 6 additions & 0 deletions src/Ocelot/Middleware/OcelotPipelineExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ public static RequestDelegate BuildOcelotPipeline(this IApplicationBuilder app,
// We allow the Ocelot middleware to be overriden by whatever the user wants.
app.UseIfNotNull<AuthenticationMiddleware>(configuration.AuthenticationMiddleware);

// Allow After authentication logic. The idea being people might want to run something custom after what is built in.
app.UseIfNotNull(configuration.AfterAuthenticationMiddleware);

// The next thing we do is look at any claims transforms in case this is important for authorization
app.UseMiddleware<ClaimsToClaimsMiddleware>();

Expand All @@ -101,6 +104,9 @@ public static RequestDelegate BuildOcelotPipeline(this IApplicationBuilder app,
// We allow the Ocelot middleware to be overriden by whatever the user wants.
app.UseIfNotNull<AuthorizationMiddleware>(configuration.AuthorizationMiddleware);

// Allow after authorization logic. The idea being people might want to run something custom after what is built in.
app.UseIfNotNull(configuration.AfterAuthorizationMiddleware);

// Now we can run the ClaimsToHeadersMiddleware: we allow the Ocelot middleware to be overriden by whatever the user wants.
app.UseIfNotNull<ClaimsToHeadersMiddleware>(configuration.ClaimsToHeadersMiddleware);

Expand Down
48 changes: 48 additions & 0 deletions test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,54 @@ public void Should_fix_issue_237()
.BDDfy();
}

[Fact]
public void Should_call_after_http_authentication_middleware()
{
var pipelineConfiguration = new OcelotPipelineConfiguration
{
AfterAuthenticationMiddleware = async (ctx, next) =>
{
_counter++;
await next.Invoke();
},
};
var port = PortFinder.GetRandomPort();
var route = GivenRoute(port);
var configuration = GivenConfiguration(route);

this.Given(x => x.GivenThereIsAServiceRunningOnPath(port, string.Empty))
.And(x => GivenThereIsAConfiguration(configuration))
.And(x => GivenOcelotIsRunning(pipelineConfiguration))
.When(x => WhenIGetUrlOnTheApiGateway("/"))
.Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => x.ThenTheCounterIs(1))
.BDDfy();
}

[Fact]
public void Should_call_after_authorization_middleware()
{
var pipelineConfiguration = new OcelotPipelineConfiguration
{
AfterAuthorizationMiddleware = async (ctx, next) =>
{
_counter++;
await next.Invoke();
},
};
var port = PortFinder.GetRandomPort();
var route = GivenRoute(port);
var configuration = GivenConfiguration(route);

this.Given(x => x.GivenThereIsAServiceRunningOnPath(port, string.Empty))
.And(x => GivenThereIsAConfiguration(configuration))
.And(x => GivenOcelotIsRunning(pipelineConfiguration))
.When(x => WhenIGetUrlOnTheApiGateway("/"))
.Then(x => ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => x.ThenTheCounterIs(1))
.BDDfy();
}

private void GivenOcelotIsRunningWithMiddlewareBeforePipeline<T>(Func<object, Task> middleware)
{
var builder = TestHostBuilder.Create()
Expand Down
Loading