Skip to content

Commit

Permalink
Merge pull request #6 from AdastralGroup/feature/swagger-auth
Browse files Browse the repository at this point in the history
Implement Swagger Authentication
  • Loading branch information
ktwrd authored Nov 1, 2024
2 parents 8924426 + 51b059d commit 8142b18
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 6 deletions.
6 changes: 3 additions & 3 deletions Adastral.Cockatoo.Common/Settings/CockatooConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,7 +1139,7 @@ public class CockatooAspNetConfig
/// <summary>
/// Enable Swagger in Production (Restart Required)
/// </summary>
[XmlElement]
[XmlElement(nameof(SwaggerEnable))]
[InfisicalPath("/AspNET")]
[InfisicalKey("EnableSwagger")]
[DefaultValue(false)]
Expand All @@ -1150,7 +1150,7 @@ public class CockatooAspNetConfig
/// <summary>
/// Request Header to use when doing token authentication.
/// </summary>
[XmlElement]
[XmlElement(nameof(TokenHeader))]
[InfisicalPath("/AspNET")]
[InfisicalKey("TokenHeader")]
[DefaultValue("x-cockatoo-token")]
Expand All @@ -1160,7 +1160,7 @@ public class CockatooAspNetConfig
/// <summary>
/// Is Cockatoo running behind a Proxy or a Load Balancer?
/// </summary>
[XmlElement]
[XmlElement(nameof(BehindProxy))]
[InfisicalPath("/AspNET")]
[InfisicalKey("BehindProxy")]
[DefaultValue(false)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<ItemGroup>
<PackageReference Include="Sentry.AspNetCore" Version="4.12.0" />
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.6.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>

</Project>
79 changes: 79 additions & 0 deletions Adastral.Cockatoo.Services.WebApi/FileUploadFilter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace Adastral.Cockatoo.Services.WebApi;

public class FileUploadFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
var formParameters = context.ApiDescription.ParameterDescriptions
.Where(paramDesc => paramDesc.IsFromForm());
if(formParameters.Any())
{
// already taken care by swashbuckle. no need to add explicitly.
return;
}
if(operation.RequestBody != null)
{
// NOT required for form type
return;
}
if (context.ApiDescription.HttpMethod == HttpMethod.Post.Method)
{
var uploadFileMediaType = new OpenApiMediaType()
{
Schema = new OpenApiSchema()
{
Type = "object",
Properties =
{
["files"] = new OpenApiSchema()
{
Type = "array",
Items = new OpenApiSchema()
{
Type = "string",
Format = "binary",
Description = "Form File Upload"
},
Description = "Form File Upload"
}
},
Required = new HashSet<string>() { "files" },
Description = "Form File Upload"
}
};
var uploadStreamFileType = new OpenApiMediaType()
{
Schema = new OpenApiSchema()
{
Type = "string",
Format = "binary",
Description = "Binary File Upload"
}
};

operation.RequestBody = new OpenApiRequestBody
{
Content = new Dictionary<string, OpenApiMediaType>(){ {"multipart/form-data", uploadFileMediaType},
{"application/octet-stream", uploadStreamFileType} },
Required = true
};
}
}
}
internal static class MvcApiExplorerExtensions
{
internal static bool IsFromForm(this ApiParameterDescription apiParameter)
{
var source = apiParameter.Source;
var elementType = apiParameter.ModelMetadata?.ElementType;

return (source == BindingSource.Form || source == BindingSource.FormFile)
|| (elementType != null && typeof(IFormFile).IsAssignableFrom(elementType));
}
}
49 changes: 46 additions & 3 deletions Adastral.Cockatoo.WebApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Adastral.Cockatoo.Services.WebApi.Controllers;
using Adastral.Cockatoo.Services.WebApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Models;

namespace Adastral.Cockatoo.WebApi;

Expand Down Expand Up @@ -69,12 +70,54 @@ private static void InitializeWebApplication(CoreContext core, string[] args)
builder.Services.AddMvc(options =>
{
options.EnableEndpointRouting = false;
})
.AddApplicationPart(pluginAssembly);
}).AddApplicationPart(pluginAssembly);
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
// add swagger-related stuff
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition("basicAuth", new OpenApiSecurityScheme
{
Description = "Basic Authorization",
Name = "Authorization",
In = ParameterLocation.Header,
Scheme = "basic",
Type = SecuritySchemeType.Http
});
options.AddSecurityDefinition("tokenHeader", new OpenApiSecurityScheme
{
Description = "Cockatoo Token Header",
Name = core.Config.AspNET.TokenHeader,
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "basicAuth"
}
},
new string[] {}
},
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "tokenHeader"
}
},
new string[] {}
}
});
options.OperationFilter<FileUploadFilter>();
});
builder.Services.AddAuthorization();
var authBuilder = builder.Services.AddAuthentication(
options =>
Expand Down

0 comments on commit 8142b18

Please sign in to comment.