I can see a lot of ways to do it online but most of them are messy, for me I was using these two ways
Using scopes, I did one for mobile and another one for the website
var webScope = apiDescription.ActionDescriptor.GetFilterPipeline() .Select(filterInfo => filterInfo.Instance) .OfType<WebAuthorize>() .SelectMany(attr => attr.Roles.Split(',')) .Distinct(); var mobileScope = apiDescription.ActionDescriptor.GetFilterPipeline() .Select(filterInfo => filterInfo.Instance) .OfType<MobileAuthorize>() .SelectMany(attr => attr.Roles.Split(',')) .Distinct();
And it worked because I had two different ways in authorizing the api calls, as you can see I had a Mobile Authorize and a Web Authorize so my api calls would look something like this:
[HttpGet] [Route("something")] [WebAuthorize(Code = PermissionCode, Type =PermissionType)] public async Task<Dto> Getsomething() { return await unitOfWork.GetService<ISomething>().GetSomething(); }
Issues I face when using scopes is that all calls that have web authorize will share the same headers so for the special calls I used another way to add custom headers.
Using apiDescription.RelativePath, and I will check it if the relative path is equal to the api call I want to add that custom header, example:
[HttpPost] [Route("rename")] [InHouseAuthorize(Code = PermissionCode, Type =PermissionType)] public async Task<HttpResponseMessage> RenameDevice() { HttpRequestMessage request = Request ?? new HttpRequestMessage(); String deviceName = request.Headers.GetValues("deviceName").FirstOrDefault(); String deviceGuid = request.Headers.GetValues("deviceGuid").FirstOrDefault(); await unitOfWork.GetService<IDeviceService>().RenameDevice(deviceGuid, deviceName); await unitOfWork.Commit(); return new HttpResponseMessage(HttpStatusCode.OK); }
And then I would add to the AddRequiredHeaderParameter.cs the following
if (apiDescription.RelativePath.Contains("device/rename")) { operation.parameters.Add(new Parameter { name = "deviceGuid", @in = "header", description = "Add the Device Guid", type = "string", required = false }); operation.parameters.Add(new Parameter { name = "DeviceName", @in = "header", description = "Add the Device Name", type = "string", required = false }); }
At first this was convenient and good enough fix but things are turning ugly as I'm adding a lot of calls that need custom headers and if the same URL have a Get and Post then it will even get uglier.
I am searching for the best way to deal with this issue.
It's possible to use attribute [FromHeader] for web methods parameters (or properties in a Model class) which should be sent in custom headers. Something like this:
For me it looks like the easiest solution. At least it works fine for ASP.NET Core 2.1 and Swashbuckle.AspNetCore 2.5.0.