Open MartinKuhne opened 5 years ago
For now you probably need to override the controller template and add this manually.
Or use "Controller Base Class Name" to extend it. Thankfully it is partial. <3
Is that going to work when the [Authorize]
attribute needs to be applied to the action and not just the controller, since the action methods generated by NSwag currently are not partial. The controller is partial, so you can create a partial class file for the controller and decorate that with whatever authentication process you want; but it won't work if, for instance, you have a read
scope on your GET
endpoints and a write
scope on your POST
endpoints.
For now you probably need to override the controller template and add this manually.
So I should look at, for instance, creating a custom Controller.Methods.Annotations.liquid
template, since that already seems to be wired up in Controller.liquid
? How do I then access the security sections that have been defined for the endpoint in the OpenAPI specification?
I've got as far as this for my template:
{% if operation.RequiresAuthentication -%}
{% for requirement in operation.Security -%}
[Microsoft.AspNetCore.Authorization.Authorize(AuthenticationSchemes = "{{ requirement.Key}}", Roles = "{{ requirement.Values | join: "," }}")]
{% endfor -%}
{% endif -%}
which gets rendered as:
[Microsoft.AspNetCore.Authorization.Authorize(AuthenticationSchemes = "", Roles = "")]
[Microsoft.AspNetCore.Authorization.Authorize(AuthenticationSchemes = "", Roles = "")]
So it seems Liquid doesn't know how to handle rendering dictionaries (or more correctly, doesn't know how to handle KeyValuePair<string, string>
). Does this mean that I need to modify CSharpOperationModel
to expose something that Liquid can handle?
I eventually worked out the solution to my problem. The working template for Controller.Method.Annotations.liquid
in my custom templates folder is now as follows:
{% if operation.RequiresAuthentication -%}
{% for security in operation.Security -%}
{% for requirement in security -%}
[Microsoft.AspNetCore.Authorization.Authorize(AuthenticationSchemes = "{{ requirement[0] }}", Roles = "{{ requirement[1] | join: "," }}")]
{% endfor -%}
{% endfor -%}
{% endif -%}
which in my case, will result in an output like this:
[Microsoft.AspNetCore.Authorization.Authorize(AuthenticationSchemes = "Bearer", Roles = "Employee:Write")]
[Microsoft.AspNetCore.Mvc.HttpPost, Microsoft.AspNetCore.Mvc.Route("employees/{employeeId}/payroll-details", Name = "Employees_PostPayroll")]
public System.Threading.Tasks.Task PostPayroll([Microsoft.AspNetCore.Mvc.ModelBinding.BindRequired] System.Guid employeeId, [Microsoft.AspNetCore.Mvc.FromBody] [Microsoft.AspNetCore.Mvc.ModelBinding.BindRequired] CreateEmployeePayrollDetailCommand body, System.Threading.CancellationToken cancellationToken)
{
// etc
}
which is a thing of beauty in my eyes :-)
@MartinKuhne did you ever get this working to your satisfaction?
I have an openAPI3 document as per https://swagger.io/docs/specification/authentication/
.csproj:
Question: How can I get the [Authorize] attribute generated on the generated controller?