Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS issue in oauth2 authorizationCode flow #6081

Open
aldredb opened this issue Jun 4, 2020 · 23 comments · May be fixed by #8493
Open

CORS issue in oauth2 authorizationCode flow #6081

aldredb opened this issue Jun 4, 2020 · 23 comments · May be fixed by #8493

Comments

@aldredb
Copy link

aldredb commented Jun 4, 2020

Q&A (please complete the following information)

  • OS: [e.g. macOS] macOS
  • Browser: [e.g. chrome, safari] Safari
  • Version: [e.g. 22] 13.1
  • Method of installation: [e.g. npm, dist assets] npm
  • Swagger-UI version: [e.g. 3.10.0] 3.24.3
  • Swagger/OpenAPI version: [e.g. Swagger 2.0, OpenAPI 3.0] OpenAPI 3.0.2

Content & configuration

Example Swagger/OpenAPI definition:

  securitySchemes:
    oauth:
      type: oauth2
      flows: 
        authorizationCode:
          authorizationUrl: https://XX/authorization 
          tokenUrl: https://XX/token
          scopes: 
            registrar: can register

Swagger-UI configuration options:

ui.initOAuth({
    clientId: "XXX",
    clientSecret: "XXX",
    appName: "apitemplate",
    scopeSeparator: " ",
    useBasicAuthenticationWithAccessCodeGrant: 'true',
  })

Describe the bug you're encountering

I used the authorization_code grant flow to receive my grant code, however, during token retrieval i received error: Auth ErrorTypeError: Origin http://localhost:8080 is not allowed by Access-Control-Allow-Origin.

Screenshots

image

image

@laurynasr
Copy link

The authorization server needs to be set up to allow CORS for this to work. However, even with an authorization server set up for CORS this sometimes fails because it unnecessarily adds "X-Requested-With" header to Token endpoint call, and that "upgrades" the request to require preflight. And as Token request is generally a simple request, some authorization servers don't handle preflight at all.
The "X-Requested-With" header was added with this change: 937c8f6

@aldredb
Copy link
Author

aldredb commented Jun 4, 2020

Unfortunately i don't have control over the authorization server..It's a managed service which I leveraged. Are there any workarounds that can be done?

@hkosova
Copy link
Contributor

hkosova commented Jun 16, 2020

@aldredb you can use requestInterceptor to proxy requests through a CORS proxy. See the example here: #1888 (comment)

@BeChaRem
Copy link

@hkosova What about laurynasr comment about removing the X-Requested-With header? This break CORS for us.

Looking at OIDC library on github neither appauth-js or oidc-client-js need preflight for this. It's all done with simple request.

@SpoonMeiser
Copy link

The original problem that the X-Requested-With header was added for (the browser does the wrong thing if you enter incorrect details) seems less of a problem than not being able to authenticate at all.

I'd argue that the header should be removed, or at least made configurable so that people who have issues with CORS can disable it.

@SpoonMeiser
Copy link

In particular, PR #4934 concerns an oauth2 server that returns a header of WWW-Authenticate: Basic ... - "basic" here seems incorrect; is a bug with the server rather than swagger-ui? If so, I think this change should be reversed, and maybe a test added that the request from authorizeRequest complies with a simple request that won't trigger preflight.

@SpoonMeiser
Copy link

@aldredb @BeChaRem can you check whether the changes in this branch on my fork fix the problem for you?

https://github.com/SpoonMeiser/swagger-ui/tree/fix-cors-issue

Turns out that it doesn't fix the problem I'm having, but these changes add a test that the request is a "simple" request, so might be worth making a PR if it fixes someone's problem.

@BeChaRem
Copy link

It fix the issue for us. No preflight and a successful call to the token endpoint.

@jstallm
Copy link

jstallm commented Nov 17, 2020

It fix the issue for us. No preflight and a successful call to the token endpoint.

What exactly resolved the issue for you?

@BeChaRem
Copy link

It fix the issue for us. No preflight and a successful call to the token endpoint.

What exactly resolved the issue for you?

Removing the "X-Requested-With": "XMLHttpRequest" Headers for the Token request as seen in SpoonMeiser commit.

@jstallm
Copy link

jstallm commented Nov 19, 2020

It fix the issue for us. No preflight and a successful call to the token endpoint.

What exactly resolved the issue for you?

Removing the "X-Requested-With": "XMLHttpRequest" Headers for the Token request as seen in SpoonMeiser commit.

Ok. Thank you. How exactly can I reference @SpoonMeiser fork as a nuget package?

@BeChaRem
Copy link

I don't know. I pulled his branch and tested locally to confirms the fix. I didn't go farther than that.

@jstallm
Copy link

jstallm commented Nov 19, 2020

I don't know. I pulled his branch and tested locally to confirms the fix. I didn't go farther than that.

How exactly did you test locally? How did you reference a local version of swaggerUI without a nuget reference?

The reason I dont believe this is a solution is because I am encountering the exact same issue and have used a Chrome extension to remove the X-Requested-With header. Even after removing the header using the extension, it still has the same error message. Therefore, its hard for me to validate this is in fact the solution.

@BeChaRem
Copy link

SwaggerUI have a standalone page in ./dist when you build it.

Steps I did to verify @SpoonMeiser branch:

  1. Clone his repo
  2. Checkout fix-cors-issue
  3. (Optionnal)Modify packages.json to serve on https instead of http
  4. Modify index.html for my own swagger.json file and openid config
      ui.initOAuth({
          clientId: "my-client-id",
          usePkceWithAuthorizationCodeGrant: true
        })
  1. npm install
  2. npm run build
  3. npm run start
  4. Verify that it works.

Only 1 GET request was done to the token endpoint. No pre-flight.
Request Headers

@jstallm
Copy link

jstallm commented Nov 19, 2020

1 workaround I have found for me is to use Chrome Extension and force the response header
Access-Control-Allow-Origin
to be
*

Even though I have a proxy that returns this same exact header, using a chrome extension to force modify the header strangely allows me to workaround the issue. For me, changing/modifying the X-Requested-With header did not resolve the issue.

@BeChaRem
Copy link

1 workaround I have found for me is to use Chrome Extension and force the response header
Access-Control-Allow-Origin
to be
*

Even though I have a proxy that returns this same exact header, using a chrome extension to force modify the header strangely allows me to workaround the issue. For me, changing/modifying the X-Requested-With header did not resolve the issue.

Our IdP reflect the origin, instead of replying with *. I don't know if this makes a difference.

access-control-allow-origin: https://localhost:44343

@jstallm
Copy link

jstallm commented Nov 19, 2020

1 workaround I have found for me is to use Chrome Extension and force the response header
Access-Control-Allow-Origin
to be
*
Even though I have a proxy that returns this same exact header, using a chrome extension to force modify the header strangely allows me to workaround the issue. For me, changing/modifying the X-Requested-With header did not resolve the issue.

Our IdP reflect the origin, instead of replying with *. I don't know if this makes a difference.

access-control-allow-origin: https://localhost:44343

I dont believe it makes a difference since I can workaround the issue by using https://localhost:44386 or *

The million dollar question for me is : Why exactly would using a chrome plugin to set the value of access-control-allow-origin to the exact same value as the server response change the outcome of how the browser treats the response?

There is no difference whatsoever in the value returned from the server or from the plugin. They are the same value! Diff shown below
image

So in summary: I experienced the exact same issue that the author of this issue experienced. My temporary workaround ( certainly not permanent since API developer/customers are not going to want to download a plugin just for using an API) is to use a chrome plugin to override the value of the response header "access-control-allow-origin" to either "*" or "https://localhost:44343" , which is the exact same value returned from the server response. Therefore, I dont believe a proxy is necessarily the solution.

@pfeigl
Copy link

pfeigl commented May 26, 2021

We are facing the same problem with an IdentityServer which does not support CORS for /conntect/token requests.

Most swagger implementations (we are using NSwag and Swashbuckle) do however support injecting custom javascript code into the swagger startup page.

With this we were able to workaround the issue by using this code

	window.fetch = function (fetch) {
        return function () {
            var req = arguments[1];
            if(req.headers["X-Requested-With"]) {
                delete req.headers["X-Requested-With"];
            }
            return fetch.apply(window, arguments);
        };
    }(window.fetch);

Hth someone else.

@Odraio
Copy link

Odraio commented Aug 31, 2021

We are facing the same problem with an IdentityServer which does not support CORS for /conntect/token requests.

Most swagger implementations (we are using NSwag and Swashbuckle) do however support injecting custom javascript code into the swagger startup page.

With this we were able to workaround the issue by using this code

	window.fetch = function (fetch) {
        return function () {
            var req = arguments[1];
            if(req.headers["X-Requested-With"]) {
                delete req.headers["X-Requested-With"];
            }
            return fetch.apply(window, arguments);
        };
    }(window.fetch);

Hth someone else.

This javascript solution does work, but what is the security risk of implementing this workaround?

@mitar
Copy link

mitar commented Jun 8, 2022

Backreference, gitlab.com's oauth implementation has the same issue: https://gitlab.com/gitlab-org/gitlab/-/issues/300077#note_975798994

@uladzimir-tryputska
Copy link

Gitlab is not going to adjust CORS behaviour. Is there a chance to adjust it in the swagger-ui? :)

@lion7
Copy link

lion7 commented Mar 20, 2023

Any chance to get #4934 reverted?
This header breaks the integration with Dex IDP which I'm currently using 😒.
While the above piece of JavaScript works just fine, it's a very ugly workaround.

@jwr3408
Copy link

jwr3408 commented Jul 17, 2023

Try this .NET package: AspNetCore.Proxy.

Add this code to your program.cs file after app.MapControllers().RequireAuthorization() and before app.Run()

  app.UseProxies(proxies =>
    {
        proxies.Map("oauth", proxy => proxy.UseHttp(ConfigSettings.TokenUrl,
            builder => builder.WithShouldAddForwardedHeaders(false)));
    });

here is my flows parameter:

 Flows = new OpenApiOAuthFlows()
                    {
                        ClientCredentials = new OpenApiOAuthFlow
                        {
                            TokenUrl = new Uri("/oauth", UriKind.Relative),
                            Scopes = new Dictionary<string, string>()
                        }
                    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet