Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ public void processOpts() {
supportingFiles.add(new SupportingFile("Filters" + File.separator + "GeneratePathParamsValidationFilter.mustache",
packageFolder + File.separator + "Filters", "GeneratePathParamsValidationFilter.cs"));
}

supportingFiles.add(new SupportingFile("Authentication" + File.separator + "ApiAuthentication.mustache",packageFolder + File.separator + "Authentication", "ApiAuthentication.cs"));
}

public void setPackageGuid(String packageGuid) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace {{packageName}}.Authentication
{
public class ApiKeyRequirement : IAuthorizationRequirement
{
public IReadOnlyList<string> ApiKeys { get; set; }

public string PolicyName { get; set; }

public ApiKeyRequirement(IEnumerable<string> apiKeys, string policyName)
{
ApiKeys = apiKeys?.ToList() ?? new List<string>();
PolicyName = policyName;
}
}

public class ApiKeyRequirementHandler : AuthorizationHandler<ApiKeyRequirement>
{

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ApiKeyRequirement requirement)
{
SucceedRequirementIfApiKeyPresentAndValid(context, requirement);
return Task.CompletedTask;
}

private void SucceedRequirementIfApiKeyPresentAndValid(AuthorizationHandlerContext context, ApiKeyRequirement requirement)
{
{{#authMethods}}{{#isApiKey}}
{{#-first}}
if (context.Resource is AuthorizationFilterContext authorizationFilterContext)
{
var apiKey = "";
{{/-first}}
{{#isKeyInHeader}}
apiKey = authorizationFilterContext.HttpContext.Request.Headers["{{keyParamName}}"].FirstOrDefault();
{{/isKeyInHeader}}
{{#isKeyInQuery}}
apiKey = authorizationFilterContext.HttpContext.Request.Query["{{keyParamName}}"].FirstOrDefault();
{{/isKeyInQuery}}
{{#isKeyInCookie}}
apiKey = authorizationFilterContext.HttpContext.Request.Cookies["{{keyParamName}}"] ?? null;
{{/isKeyInCookie}}
if (requirement.PolicyName == "{{name}}" && apiKey != null && requirement.ApiKeys.Any(requiredApiKey => apiKey == requiredApiKey))
{
context.Succeed(requirement);
}
{{#-last}}
}
{{/-last}}
{{/isApiKey}}{{/authMethods}}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ using Newtonsoft.Json.Serialization;{{#useSwashbuckle}}
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using {{packageName}}.Filters;{{/useSwashbuckle}}
using {{packageName}}.Authentication;
using Microsoft.AspNetCore.Authorization;

namespace {{packageName}}
{
Expand Down Expand Up @@ -40,6 +42,22 @@ namespace {{packageName}}
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
{{#authMethods}}
{{#isApiKey}}
{{#-first}}
services.AddTransient<IAuthorizationHandler, ApiKeyRequirementHandler>();
services.AddAuthorization(authConfig =>
{
{{/-first}}
authConfig.AddPolicy("{{name}}",
policyBuilder => policyBuilder
.AddRequirements(new ApiKeyRequirement(new[] { "my-secret-key" },"{{name}}")));
{{#-last}}
});
{{/-last}}
{{/isApiKey}}
{{/authMethods}}

// Add framework services.
services
.AddMvc()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ namespace {{apiPackage}}
/// <param name="{{paramName}}">{{description}}</param>{{/allParams}}{{#responses}}
/// <response code="{{code}}">{{message}}</response>{{/responses}}
[{{httpMethod}}]
[Route("{{{basePathWithoutHost}}}{{{path}}}")]{{#hasAuthMethods}}{{#authMethods}}{{#isBasicBearer}}
[Route("{{{basePathWithoutHost}}}{{{path}}}")]{{#hasAuthMethods}}{{#authMethods}}{{#isApiKey}}
[Authorize(Policy = "{{name}}")]{{/isApiKey}}{{#isBasicBearer}}
[Authorize{{#hasScopes}}(Roles = "{{#scopes}}{{scope}}{{#hasMore}},{{/hasMore}}{{/scopes}}"){{/hasScopes}}]{{/isBasicBearer}}{{/authMethods}}{{/hasAuthMethods}}
[ValidateModelState]{{#useSwashbuckle}}
[SwaggerOperation("{{operationId}}")]{{#responses}}{{#dataType}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Org.OpenAPITools.Authentication
{
public class ApiKeyRequirement : IAuthorizationRequirement
{
public IReadOnlyList<string> ApiKeys { get; set; }

public string PolicyName { get; set; }

public ApiKeyRequirement(IEnumerable<string> apiKeys, string policyName)
{
ApiKeys = apiKeys?.ToList() ?? new List<string>();
PolicyName = policyName;
}
}

public class ApiKeyRequirementHandler : AuthorizationHandler<ApiKeyRequirement>
{

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ApiKeyRequirement requirement)
{
SucceedRequirementIfApiKeyPresentAndValid(context, requirement);
return Task.CompletedTask;
}

private void SucceedRequirementIfApiKeyPresentAndValid(AuthorizationHandlerContext context, ApiKeyRequirement requirement)
{

if (context.Resource is AuthorizationFilterContext authorizationFilterContext)
{
var apiKey = "";
apiKey = authorizationFilterContext.HttpContext.Request.Headers["api_key"].FirstOrDefault();
if (requirement.PolicyName == "api_key" && apiKey != null && requirement.ApiKeys.Any(requiredApiKey => apiKey == requiredApiKey))
{
context.Succeed(requirement);
}

}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public virtual IActionResult FindPetsByTags([FromQuery][Required()]List<string>
/// <response code="404">Pet not found</response>
[HttpGet]
[Route("/v2/pet/{petId}")]
[Authorize(Policy = "api_key")]
[ValidateModelState]
[SwaggerOperation("GetPetById")]
[SwaggerResponse(statusCode: 200, type: typeof(Pet), description: "successful operation")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public virtual IActionResult DeleteOrder([FromRoute][Required]string orderId)
/// <response code="200">successful operation</response>
[HttpGet]
[Route("/v2/store/inventory")]
[Authorize(Policy = "api_key")]
[ValidateModelState]
[SwaggerOperation("GetInventory")]
[SwaggerResponse(statusCode: 200, type: typeof(Dictionary<string, int?>), description: "successful operation")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
using Org.OpenAPITools.Filters;
using Org.OpenAPITools.Authentication;
using Microsoft.AspNetCore.Authorization;

namespace Org.OpenAPITools
{
Expand Down Expand Up @@ -49,6 +51,13 @@ public Startup(IConfiguration configuration)
/// <param name="services"></param>
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IAuthorizationHandler, ApiKeyRequirementHandler>();
services.AddAuthorization(authConfig =>
{
authConfig.AddPolicy("api_key",
policyBuilder => policyBuilder
.AddRequirements(new ApiKeyRequirement(new[] { "my-secret-key" },"api_key")));

// Add framework services.
services
.AddMvc()
Expand Down