简体   繁体   中英

.Net Core Swashbuckle skip authorization header on redirects

In a .Net Core web API I integrated Swagger using Swashbuckle. The API is protected so one will need to authorize and login before doing some requests in the Swagger UI. This all works great.

Now one API call creates a presigned URL and returns an HTTP redirect to the file server (the presigned URL).

The problem is that Swagger UI sends the authorization header with the JWT token to the file server (MinIO). This causes the file server receiving two different authentication mechanisms and responds with invalid request.

Is there a way to influence how Swagger UI treats redirects or to not send the token on redirects?

I too came across this problem and realized that when fetch redirects to the presigned S3 URL you can't prevent it from sending the Authorization headers from your API.

Eventually I have able to get this working by using the responseInterceptor configuration argument for Swagger with a custom function that detects the bad request (400) response from S3 and then re-issues the fetch request with credentials: 'omit' .

Here is my custom response interceptor for Swagger:

// swagger-ui-extensions.js

function serializeHeaderValue(value) {
  const isMulti = value.includes(', ');
  return isMulti ? value.split(', ') : value;
}

function serializeHeaders(headers = {}) {
  return Array.from(headers.entries()).reduce((acc, [header, value]) => {
    acc[header] = serializeHeaderValue(value);
    return acc;
  }, {});
}

function myResponseInterceptor(response) {
  // NOTE: Additional checks should probably be added whether to re-issue the fetch. This was just an initial starting point.
  if (response.ok === false && response.status === 400 && response.headers['server'] === 'AmazonS3') {
    // Here is the important part, re-issue fetch but don't allow our Authentication header to flow
    response = fetch(response.url, { credentials: 'omit' })
      .then(nativeResponse => {
        // We can't return the native response because Swagger UI attempts to assign the header property (and potentially other properties
        // too) on the response. So return a serialized clone of the native response. FYI, this is the same exact logic from Swagger's fake
        // implementation of fetch.
        const getBody = nativeResponse.blob || nativeResponse.buffer;
        return getBody.call(nativeResponse).then(body => {
          return {
            ok: nativeResponse.ok,
            url: nativeResponse.url,
            status: nativeResponse.status,
            statusText: nativeResponse.statusText,
            headers: serializeHeaders(nativeResponse.headers),
            data: body
          };
        });
      });
  }
  return response;
}

Then I had to specify my custom myResponseInterceptor when initializing the Swagger UI in index.html

      // (other code omitted for brevity...)

      // Make sure to include your custom JS in the page
      // <script src="./swagger-ui-extensions.js"></script>

      // Specifying the custom responseInterceptor here...
      configObject.responseInterceptor = myResponseInterceptor;

      // Begin Swagger UI call region

      const ui = SwaggerUIBundle(configObject);

      ui.initOAuth(oauthConfigObject);

      // End Swagger UI call region

      window.ui = ui;

I was using ASP.NET Core and used these instructions to provide my own index.html for Swagger UI: https://github.com/domaindrivendev/Swashbuckle.AspNetCore#customize-indexhtml

After all that, this surprisingly worked and I was able to see the redirected response from S3 in Swagger.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM