1

In a .NET Core project, I add a security definition (code at the bottom), which adds an Authorize button to the page and the user can enter the api key - everything works fine.

Is it possible to specify the api key in the URL so that Swagger automatically uses that instead of having to enter it? Like /swagger/index.html?authorization=0123456789 or something to that effect.

Existing code:

services.AddSwaggerGen(c => {
  ...
  c.AddSecurityDefinition("api key", new ApiKeyScheme() {
      Description = "Authorization query string expects API key",
      In = "query",
      Name = "authorization",
      Type = "apiKey"
  });

  var requirements = new Dictionary<string, IEnumerable<string>> {
      { "api key", new List<string>().AsEnumerable() }
  };
  c.AddSecurityRequirement(requirements);
});

Seems like the URL with authorization parameter should work, but it doesn't.

P.S. Using Swashbuckle 4.0.x

AngryHacker
  • 59,598
  • 102
  • 325
  • 594

1 Answers1

6

It is indeed possible, but you will have to override Swagger-UI's index page so you can plug your custom handler into onComplete callback.

  1. Grab latest index.html from Swashbuckle's source repo (ideally, get the matching version)
  2. Tweak configObject to add an OnComplete callback handler so it will call preauthorizeApiKey when the UI is ready
  3. Override IndexStream in UserSwaggerUI extension method to serve the custom html

I ended up having the following setup (some bits are omitted for brevity):

wwwroot/swashbuckle.html

<!-- your standard HTML here, nothing special -->
<script>
    // some boilerplate initialisation
    // Begin Swagger UI call region
    configObject.onComplete = () => {

        // get the authorization portion of the query string
        var urlParams = new URLSearchParams(window.location.search);
        if (urlParams.has('authorization')) {
            var apikey = urlParams.get('authorization');

            // this is the important bit, see documentation
            ui.preauthorizeApiKey('api key', apikey );// key name must match the one you defined in AddSecurityDefinition method in Startup.cs
       }
    }
    const ui = SwaggerUIBundle(configObject);
    window.ui = ui        
}
</script>

Startup.cs

    public void ConfigureServices(IServiceCollection services)
    {
        .........
        services.AddSwaggerGen(c => {
            c.SwaggerDoc("v1", new Info { Title = "You api title", Version = "v1" });
            c.AddSecurityDefinition("api key", new ApiKeyScheme() // key name must match the one you supply to preauthorizeApiKey call in JS
            {
                Description = "Authorization query string expects API key",
                In = "query",
                Name = "authorization",
                Type = "apiKey"
            });

            var requirements = new Dictionary<string, IEnumerable<string>> {
                { "api key", new List<string>().AsEnumerable() }
            };
            c.AddSecurityRequirement(requirements);
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseSwagger();
        app.UseSwaggerUI(c =>
        {
            c.IndexStream = () => File.OpenRead("wwwroot/swashbuckle.html"); // this is the important bit. see documentation https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README.md
            c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); // very standard Swashbuckle init
        });
        app.UseMvc();
    }

After you've done all that, calling the standard swagger URL with ?authorization=1234567890 should automatically authorize the page.

AngryHacker
  • 59,598
  • 102
  • 325
  • 594
timur
  • 14,239
  • 2
  • 11
  • 32