0
votes

I have built an API that uses appid and apikey for authentication. It works fine when I'm calling the API from other applications using the appid and apikey, but I'm having problems using the API functions from the /swagger URL. I can type in an apikey at the top of the swagger UI, but I can't seem to enter the appid anywhere.

I've been looking at other similar questions and tried out what was suggested there.

I'm running Swashbuckle v5.6.0 on a .Net Framework 4.7.2 web API application.

I have added

c.ApiKey("apiKey")
  .Description("API Key Authentication") // first key
  .Name("Authorization")
  .In("header");
c.ApiKey("appId")
  .Description("API Key Authentication") // second key
  .Name("Authorization")
  .In("header");

to my GlobalConfiguration.Configuration.EnableSwagger(c =>

and

c.EnableApiKeySupport("apiKey", "header");
c.EnableApiKeySupport("appId", "header");

to my .EnableSwaggerUi(c =>

(both in SwaggerConfig.cs)

When I'm calling the API from another application I'm using a DelegatingHandler that adds the apiKey and appId to the authorization part of the header, so what's what I want to do when calling the functions from the swagger UI (eg http://my.api.com/myapi/swagger). I have seen that there is a way to get an Authorization button added to the swagger UI and when you click that button you can add stuff like appId, but how do I get that button in my swagger UI? Or is there another way of doing this?

Update 1

I figured out that I need to implement IOperationFilter, mostly because it says so right there in a comment in SwaggerConfig (d'oh!):

// you'll need to implement a custom IDocumentFilter and/or IOperationFilter to set these properties
// according to your specific authorization implementation
    public class AddRequiredAuthorizationHeaderParameter : IOperationFilter
    {
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            if (operation.parameters == null)
                operation.parameters = new List<Parameter>();

            operation.parameters.Add(new Parameter
            {
                name = "appId",
                @in = "header",
                type = "string",
                required = true,
                schema = new Schema { @ref = "amx"},
                description = "appID",

            });
        }
    }

With this I am able to add the appId key in the swagger UI when calling the function, and there's an apiKey field in the top so I figure that's all I need.

However, I can't seem to set the correct schema on the Authorization header (which you can see above I've tried to set to "amx" using schema = new Schema { @ref = "amx"}. When I do my request and then check my HttpAuthenticationContext.Request.Headers.Authorization.Scheme is not "amx" which I want, but the appID I type in when I do the call, so my authentication-process doesn't approve of it.

So now I'm just trying to figure out how to set the HttpAuthenticationContext.Request.Headers.Authorization.Scheme to "amx".

1

1 Answers

0
votes

I have now solved this. It's not pretty because I made a special check for when the call is from swagger.

The "appId" and "apiKey" values that I added (see question above), are retrievable from the HttpAuthentication object. HttpAuthentication .Request.Properties["MS_HttpContext"] contains a HttpContextWrapper whose .Items["MS_HttpRequestMessage"] contains a HttpRequestMessage and in that hashtable I can get my "appId" and "apiKey" with the .GetValues() function.