Skip to content

Mixed content issues due to XHR over HTTP made from HTTPS page #1670

Closed

Description

@dalbani

If the schemes parameter is configured (and not empty) for an API, Swagger UI picks the first [1] [2] scheme value up for API requests.
For example:

{
    "swagger": "2.0",
    "schemes": [
        "http",
        "https"
    ]
}

As a consequence, all requests will be made over HTTP.

This cause "mixed content issues" when Swagger UI is served/hosted via HTTPS and yet makes regular HTTP requests, as explained above.

[1] https://github.com/swagger-api/swagger-js/blob/master/lib/client.js#L274
[2] https://github.com/swagger-api/swagger-js/blob/master/lib/client.js#L290

Activity

  1. ponelat commented on Oct 14, 2015

    @ponelat
    Contributor

    @dalbani I think this is a bug, because there does seem to be a check on window.location (to see if we need to use https)... https://github.com/swagger-api/swagger-js/blob/master/lib/client.js#L272

    Do you have a failing case? If you have the time, please feel free to create a Pull Request. Otherwise, we can put this in the backlog (to investigate and fix).

  2. dalbani commented on Oct 14, 2015

    @dalbani
    ContributorAuthor

    Indeed, it's in swagger-js that lies the problem (as shown in the 2 links I provided in the bug report).
    But I wasn't sure what was the most appropriate place for the fix.
    I mean, is swagger-js supposed to have to anything to do with browser-related window.location stuff?
    Maybe passing some kind of hint (e.g. rather use HTTPS than HTTP) would be more logical?

  3. ponelat commented on Oct 14, 2015

    @ponelat
    Contributor

    well... we could put https above http in the spec (hackish 😉)
    Since swagger-js does http requests, it can know about window.location. And since the only problem I can envision is when ...

    a browser on HTTPS requesting HTTP.
    Would we need to hint which schema to use? Any other use cases?

  4. dalbani commented on Oct 14, 2015

    @dalbani
    ContributorAuthor

    Since swagger-js does http requests, it can know about window.location.

    Well, I couldn't find a single reference to the browser-specific window or document variables in swagger-js source code.
    And this is fine with me, because you can't assume that the JS runtime will always be a browser.
    Therefore my idea of some kind of hint passed by the caller (Swagger UI).

  5. fehguy commented on Oct 15, 2015

    @fehguy
    Contributor

    Yes, we cannot rely on window to be an object since swagger-js is used in node & browser-less environments.

    There are two options on this that come to mind.

    First, always prefer requests over https. This is probably the easiest to implement and least controversial.

    Second, allow swagger-ui to pass a hint as to which to use. That the index.html can use the window object to get the protocol.

    So, I suspect that choosing https when both http, https are available is probably the right choice. But you can certainly have a method which requires http even if the top-level allows http, https. That will trigger the same error.

  6. dalbani commented on Oct 15, 2015

    @dalbani
    ContributorAuthor

    Indeed, preferring HTTPS over HTTP is the simplest solution. But are we sure that HTTPS is supported in all environments where swagger-js is running? I suppose so, I'm kind of thinking out loud :-)

    And what about ws vs wss? How do Swagger UI handles WebSocket at the moment by the way?
    If an API is defined with "schemes": [ "http", "https", "ws", "wss" ], how should this be globally handled by Swagger UI/JS?

  7. IanRogers-LShift commented on May 11, 2016

    @IanRogers-LShift

    We're deploying java using swagger annotations into Amazon AWS - https is terminated by the AWS load-balancer and the server is running in http. So swagger.json has "schemes" : [ "http" ], even though the browser is in https...

    So IMHO the UI should default to whatever scheme it used to get the swagger.json file. This can be passed in as an (optional) parameter to swagger-js.

  8. fehguy commented on May 11, 2016

    @fehguy
    Contributor

    Well, that would be ignoring the spec, which isn't a good idea. If you're deploying the schemes to something else, consider either leaving it off (it's optional) or setting the scheme in javascript like such:

    window.swaggerUi.api.setSchemes(['https'])
    

    Which will override the spec value.

  9. IanRogers-LShift commented on May 11, 2016

    @IanRogers-LShift

    well, I want to use the packaged UI (from https://github.com/smoketurner/dropwizard-swagger in fact) and the simplest java annotations.

    I guess I want to force the java annotations to set no scheme at all so the UI is forced to use the one it knows about... But a lot of people are going to be bitten by this.

  10. IanRogers-LShift commented on May 11, 2016

    @IanRogers-LShift

    swagger-api/swagger-client#665 only checks the ui hint if the scheme setting is empty. I guess this is the way it's going to be.

  11. fehguy commented on May 11, 2016

    @fehguy
    Contributor

    Yes, that's my suggestion, just leave the schemes empty

  12. dalbani commented on May 11, 2016

    @dalbani
    ContributorAuthor

    just leave the schemes empty

    I don't understand the logic of the suggestion.
    The goal here is be able to combine those 3 aspects:

    1. "schemes": [ "http", "https" ], because that's how the endpoints are accessible
    2. the browser using the most appropriate protocol (e.g. https if present in schemes and used by the main document)
    3. any other consumer of the Swagger definition using the most appropriate protocol

    If schemes is left empty, I can't see how those non-browser consumers could figure out which protocol to use.
    It's not as if schemes doesn't serve a purpose, right?

  13. 18 remaining items

  14. Bert-R commented on Jan 12, 2017

    @Bert-R

    That's strange. Our Swagger spec is served over https and it starts this way:

    swagger: '2.0'
    info:
      title: Yona app service API
      description: The API of the service backing the Yona app
      version: 1.0.0
    schemes:
      - http
      - https
    basePath: /
    produces:
      - application/json
    paths:
      /users/:
    

    Still, all Curl requests use http:

    curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' --header 'Yona-Password: abc' -d '{ \ 
       "firstName": "Richard", \ 
       "lastName": "Quin", \ 
       "mobileNumber": "+31612345678", \ 
       "nickname": "RQ" \ 
     }' 'http://beta.prd.yona.nu/users/'
    

    Any idea what's wrong?

  15. webron commented on Jan 12, 2017

    @webron
    Contributor

    You're using the online petstore demo to host your own documentation?

  16. Bert-R commented on Jan 12, 2017

    @Bert-R

    No, to occasionally use it. Normally works like a charm.

  17. fehguy commented on Jan 12, 2017

    @fehguy
    Contributor

    @webron why not? Is it unreliable?

  18. webron commented on Jan 12, 2017

    @webron
    Contributor

    Oh, people should use it as much as they want, but we don't guarantee an SLA, and I wouldn't want to give users of a commercial product a link such as https://petstore.swagger.io?url=.... But for general testing? Sure.

  19. Bert-R commented on Jan 12, 2017

    @Bert-R

    That's what we do. Any idea why it doesn't work with https?

  20. fehguy commented on Jan 12, 2017

    @fehguy
    Contributor

    Ah just a minute. There was a bug in swagger-js that was just fixed yesterday. Swagger-UI doesn't have the swagger-js-2.1.31 yet, but will today. So @Bert-R it's possible that the calls will work but curl is reported incorrectly. See here for details:

    swagger-api/swagger-client#931
    swagger-api/swagger-client#903

  21. Bert-R commented on Jan 12, 2017

    @Bert-R

    OK, I'll check back tomorrow. Thanks!

  22. Bert-R commented on Jan 14, 2017

    @Bert-R

    I tried it again and this is the status:

    • GET works. The UI shows that curl uses http, but apparently handles the redirect to https
    • POST does not work.

    You can try that here http://petstore.swagger.io/?url=https%3A%2F%2Fbeta.prd.yona.nu%2Fswagger%2Fswagger-spec.yaml#!/Admin/post_admin_requestUserOverwrite

    Type anything in the mobile number field and hit Try It Out. That should return you a 400 (assuming you won't guess a valid mobile number :) )

  23. fehguy commented on Jan 23, 2017

    @fehguy
    Contributor

    @Bert-R I set the scheme for your api to https in my console and all was fine:

    swaggerUi.api.setSchemes(['https'])
    

    If you change your definition from this:

    schemes:
      - http
      - https
    

    To this:

    schemes:
      - https
      - http
    

    then https will be selected first.

  24. added a commit that references this issue on Jan 24, 2017
  25. Bert-R commented on Jan 24, 2017

    @Bert-R

    @fehguy I tried that, but that doesn't work for me. Can you have another look?

  26. Bert-R commented on Feb 9, 2017

    @Bert-R

    @fehguy: After I switched the order of the schemes, the problem still exists. Can you please look into this once more?

  27. occasl commented on Feb 17, 2017

    @occasl

    I'm in the same situation. I tried the recommendation of switching the schemes and it still happens. The only thing that worked for me was to make find and replace in the swagger-ui html code, http://petstore.swagger.io/v2/swagger.json with the location of my swagger.json with HTTPS.

    However, this results in an annoying error message in the footer: Can't read from file https://partner.mycompany.com/reg-service/docs/swagger/swagger.json but that file is reachable. In spite of that, this is the lesser of two evils.

  28. Franklinxavier commented on Jan 25, 2023

    @Franklinxavier

    @Bert-R I set the scheme for your api to https in my console and all was fine:

    swaggerUi.api.setSchemes(['https'])
    

    If you change your definition from this:

    schemes:
      - http
      - https
    

    To this:

    schemes:
      - https
      - http
    

    then https will be selected first.

    How to set these schema using yml file or with any annotation in spring boot 3 ?

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions