Skip to content

Commit

Permalink
[ODS-6011] Validate Content-Type for Oauth endpoints (#844)
Browse files Browse the repository at this point in the history
* Added validation middleware

* Integrated validation middleware
  • Loading branch information
simpat-jesus authored Oct 6, 2023
1 parent cf94afa commit 57627ec
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,11 @@ void RegisterMiddleware()
.AsSelf()
.SingleInstance();

builder.RegisterType<OAuthContentTypeValidationMiddleware>()
.As<IMiddleware>()
.AsSelf()
.SingleInstance();

builder.RegisterType<RequestResponseDetailsLoggerMiddleware>()
.As<IMiddleware>()
.WithParameter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,8 @@ public static IApplicationBuilder UseEdFiApiAuthentication(this IApplicationBuil

public static IApplicationBuilder UseRequestResponseDetailsLogger(this IApplicationBuilder builder)
=> builder.UseMiddleware<RequestResponseDetailsLoggerMiddleware>();

public static IApplicationBuilder UseOAuthContentTypeValidation(this IApplicationBuilder builder)
=> builder.UseMiddleware<OAuthContentTypeValidationMiddleware>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
// Licensed to the Ed-Fi Alliance under one or more agreements.
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using System;
using System.Threading.Tasks;
using log4net;
using Microsoft.AspNetCore.Http;

namespace EdFi.Ods.Api.Middleware
{
public class OAuthContentTypeValidationMiddleware : IMiddleware
{
private readonly ILog _logger = LogManager.GetLogger(typeof(OAuthContentTypeValidationMiddleware));

public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (context.Request.Path.ToString().Contains("oauth", StringComparison.OrdinalIgnoreCase))
{
if (!context.Request.Headers.ContainsKey("Content-Type"))
{
context.Response.StatusCode = StatusCodes.Status415UnsupportedMediaType;
await context.Response.WriteAsync("Content-Type header is missing.");
return;
}
}

await next.Invoke(context);
}
}
}
2 changes: 2 additions & 0 deletions Application/EdFi.Ods.Api/Startup/OdsStartupBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ public void Configure(
// Process headers and query string arguments for correlation ids, and add to log messages
app.UseRequestCorrelation();

app.UseOAuthContentTypeValidation();

var apiSettings = apiSettingsOptions.Value;

if (!string.IsNullOrEmpty(apiSettings.PathBase))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// SPDX-License-Identifier: Apache-2.0
// Licensed to the Ed-Fi Alliance under one or more agreements.
// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0.
// See the LICENSE and NOTICES files in the project root for more information.

using System.IO;
using System.Threading.Tasks;
using EdFi.Ods.Api.Middleware;
using FakeItEasy;
using Microsoft.AspNetCore.Http;
using NUnit.Framework;
using Shouldly;

namespace EdFi.Ods.Tests.EdFi.Ods.Api.Middleware
{
[TestFixture]
public class OAuthContentTypeValidationMiddlewareTests
{
private OAuthContentTypeValidationMiddleware _middleware;

[SetUp]
public void Setup()
{
_middleware = new OAuthContentTypeValidationMiddleware();
}

[Test]
public async Task Middleware_Returns_BadRequest_When_Content_Type_Is_Missing_For_OAuth_Request()
{
// Arrange
var context = new DefaultHttpContext();
context.Request.Path = "/oauth/token";
context.Response.Body = new MemoryStream();
var next = A.Fake<RequestDelegate>();

// Act
await _middleware.InvokeAsync(context, next);

// Assert
context.Response.Body.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(context.Response.Body);
var streamText = await reader.ReadToEndAsync();
streamText.ShouldBe("Content-Type header is missing.");
context.Response.StatusCode.ShouldBe(415);
}

[Test]
public async Task Middleware_Passes_Through_When_Content_Type_Is_Present_For_OAuth_Request()
{
// Arrange
var context = new DefaultHttpContext();
context.Request.Path = "/oauth/token";
context.Request.ContentType = "application/json";
var next = A.Fake<RequestDelegate>();

// Act
await _middleware.InvokeAsync(context, next);

// Assert
A.CallTo(() => next(context)).MustHaveHappened();
}

[Test]
public async Task Middleware_Passes_Through_For_Non_OAuth_Request()
{
// Arrange
var context = new DefaultHttpContext();
context.Request.Path = "/data/v3/ed-fi/localEducationAgencies";
var next = A.Fake<RequestDelegate>();

// Act
await _middleware.InvokeAsync(context, next);

// Assert
A.CallTo(() => next(context)).MustHaveHappened();
}
}
}

0 comments on commit 57627ec

Please sign in to comment.