Uploaded image for project: 'IGB'
  1. IGB
  2. IGBF-2490

Investigate: Fix implementation of requests to IGB endpoints to support safari etc.

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Done
    • Affects Version/s: None
    • Fix Version/s: None
    • Labels:
    • Story Points:
      5
    • Sprint:
      Summer 4: 14 Jul - 28 Jul, Summer 5: 3 Aug - 14 Aug, Summer 6: 17 Aug - 28 Aug

      Description

      Making requests to the IGB API is done over http and some browsers see a security issue with doing so under an overarching secured connection and classify this as Mixed Content. Safari, for instance, blocks these sorts of requests.

      Instead of making requests in this way, the window location can be changed using javascript, which initializes a new connection, circumventing the error. See my comment here for more details.

      Task: Update the requests in app store to use the method described above, in order to allow all browsers to interact with IGB.

      Update: Allow browsers that do not support http connections to localhost on a secure parent connection to connect to IGB over https.

        Attachments

          Issue Links

            Activity

            Hide
            ann.loraine Ann Loraine added a comment -

            Things needing fixing:

            • bar.js
            • galaxy.js
            • BioViz connect
            • AppStore
            Show
            ann.loraine Ann Loraine added a comment - Things needing fixing: bar.js galaxy.js BioViz connect AppStore
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited

            After looking through the app store code base for instances of requests to IGB, I learned that both POST and GET requests were being made, some expecting data, and others not.

            The method of making requests suggested in the description will work for GET requests that do not expect any data and receive responses with status 204, in which case the page url (and therefore content) does not change. Attempting a GET request to and endpoint that does provide data, however, will navigate the window away from the primary view and show the response content.

            Furthermore, the only way to make post requests using this method is to inject javascript into the pages window location which then makes a request at a new connection. This, however, as with making GET requests will not work well with requests that expect response data, which cannot be captured using this method.

            So, it seems that migration of the IGB API to SSL/TLS seems to be the only viable solution, especially considering complex applications like the app store and potential future ones that may rely on request versatility.

            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited After looking through the app store code base for instances of requests to IGB, I learned that both POST and GET requests were being made, some expecting data, and others not. The method of making requests suggested in the description will work for GET requests that do not expect any data and receive responses with status 204, in which case the page url (and therefore content) does not change. Attempting a GET request to and endpoint that does provide data, however, will navigate the window away from the primary view and show the response content. Furthermore, the only way to make post requests using this method is to inject javascript into the pages window location which then makes a request at a new connection. This, however, as with making GET requests will not work well with requests that expect response data, which cannot be captured using this method. So, it seems that migration of the IGB API to SSL/TLS seems to be the only viable solution, especially considering complex applications like the app store and potential future ones that may rely on request versatility.
            Hide
            ann.loraine Ann Loraine added a comment -

            Noted - thank you!

            Looks like NanoHTTPD has some documentation for how to do this: https://github.com/NanoHttpd/nanohttpd

            According to the above, we can create a key with:

            keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048 -ext SAN=DNS:localhost,IP:127.0.0.1  -validity 9999
            

            and then use it with:

            server.makeSecure(NanoHTTPD.makeSSLSocketFactory("/keystore.jks", "password".toCharArray()), null);
            

            To work with our current build-and-release system, we would need some kind of maven (or shell?) task that creates the key and ensures it gets packaged with IGB's "igb_exe.jar" so that it will be available to NanoHTTPD when it starts up.

            Looks like maven has a "keytool" plugin -https://www.mojohaus.org/keytool/keytool-maven-plugin/. However, this is only a wrapper for the "keytool" command, so I'm not sure it will work on every developer's machine. That is, it might fail on Windows machines that typically do not have this. Also, I'm not sure how Safari will react when it tries to connect to localhost over a secure connection and gets a self-signed certificate. And I'm not sure I can get a signing authority to sign a certificate for Web site https://127.0.0.1:PORT

            Perhaps another approach is to simply not use REST (http) at all for the IGB endpoint. Here is some simple example code of how this, from the IGB side: https://bitbucket.org/lorainelab/command-socket/src/master/

            I did a quick google search for "can javascript open a socket on localhost" and found this Stackoverflow entry: https://stackoverflow.com/questions/12407778/connecting-to-tcp-socket-from-browser-using-javascript.

            So maybe this can work.

            Philip Badzuh - please take a look at the above.

            Show
            ann.loraine Ann Loraine added a comment - Noted - thank you! Looks like NanoHTTPD has some documentation for how to do this: https://github.com/NanoHttpd/nanohttpd According to the above, we can create a key with: keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048 -ext SAN=DNS:localhost,IP:127.0.0.1 -validity 9999 and then use it with: server.makeSecure(NanoHTTPD.makeSSLSocketFactory( "/keystore.jks" , "password" .toCharArray()), null ); To work with our current build-and-release system, we would need some kind of maven (or shell?) task that creates the key and ensures it gets packaged with IGB's "igb_exe.jar" so that it will be available to NanoHTTPD when it starts up. Looks like maven has a "keytool" plugin - https://www.mojohaus.org/keytool/keytool-maven-plugin/ . However, this is only a wrapper for the "keytool" command, so I'm not sure it will work on every developer's machine. That is, it might fail on Windows machines that typically do not have this. Also, I'm not sure how Safari will react when it tries to connect to localhost over a secure connection and gets a self-signed certificate. And I'm not sure I can get a signing authority to sign a certificate for Web site https://127.0.0.1:PORT Perhaps another approach is to simply not use REST (http) at all for the IGB endpoint. Here is some simple example code of how this, from the IGB side: https://bitbucket.org/lorainelab/command-socket/src/master/ I did a quick google search for "can javascript open a socket on localhost" and found this Stackoverflow entry: https://stackoverflow.com/questions/12407778/connecting-to-tcp-socket-from-browser-using-javascript . So maybe this can work. Philip Badzuh - please take a look at the above.
            Hide
            ann.loraine Ann Loraine added a comment - - edited

            Also, please review https://www.baeldung.com/nanohttpd. (Baeldung has many outstanding "how-tos" for Java!)

            Note how nanohttpd has many features and makes supporting REST very straightforward. If we can use it and get the behaviors we want, we should.

            Show
            ann.loraine Ann Loraine added a comment - - edited Also, please review https://www.baeldung.com/nanohttpd . (Baeldung has many outstanding "how-tos" for Java!) Note how nanohttpd has many features and makes supporting REST very straightforward. If we can use it and get the behaviors we want, we should.
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment -

            After changing the version of nanohttpd in the root igb project pom and building, the dependency cannot be resolved. After checking the maven.bioviz, nexus, and apache repos used by IGB (I think these are the only ones), I have found that nanohttpd is being pulled from here. How should I go about updating nanohttpd from the current version (2.0.5) to 2.3.1? Would it be as simple as updating the jar, metadata, pom, and hash files in the directory linked to above? If so, how might I push the update to the repo?

            Please let me know, [~aloraine]. Thanks.

            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - After changing the version of nanohttpd in the root igb project pom and building, the dependency cannot be resolved. After checking the maven.bioviz, nexus, and apache repos used by IGB (I think these are the only ones), I have found that nanohttpd is being pulled from here . How should I go about updating nanohttpd from the current version (2.0.5) to 2.3.1? Would it be as simple as updating the jar, metadata, pom, and hash files in the directory linked to above? If so, how might I push the update to the repo? Please let me know, [~aloraine] . Thanks.
            Hide
            ann.loraine Ann Loraine added a comment - - edited

            See: https://mvnrepository.com/artifact/org.nanohttpd/nanohttpd/2.3.1
            According to this, the 2.3.1 artifact is available from maven central.
            To include it in a maven project, this should be added to the POM:

            <!-- https://mvnrepository.com/artifact/org.nanohttpd/nanohttpd -->
            <dependency>
                <groupId>org.nanohttpd</groupId>
                <artifactId>nanohttpd</artifactId>
                <version>2.3.1</version>
            </dependency
            

            In our project, the groupId is different. I think this may be because we are using a much older version of the artifact.

            For testing and prototyping purposes, I would recommend simply adding the above dependency to the parent POM as shown. To ensure that the sub-module you are focusing on can use, you would also need to add it in the correct way to the shared-lib-wrapper module.

            This would ensure that the newer version of the library gets included in the project and the old version of the library will be also be present. OSGi lets us include different versions of the same library in the code base, so this should be OK.

            Show
            ann.loraine Ann Loraine added a comment - - edited See: https://mvnrepository.com/artifact/org.nanohttpd/nanohttpd/2.3.1 According to this, the 2.3.1 artifact is available from maven central. To include it in a maven project, this should be added to the POM: <!-- https: //mvnrepository.com/artifact/org.nanohttpd/nanohttpd --> <dependency> <groupId>org.nanohttpd</groupId> <artifactId>nanohttpd</artifactId> <version>2.3.1</version> </dependency In our project, the groupId is different. I think this may be because we are using a much older version of the artifact. For testing and prototyping purposes, I would recommend simply adding the above dependency to the parent POM as shown. To ensure that the sub-module you are focusing on can use, you would also need to add it in the correct way to the shared-lib-wrapper module. This would ensure that the newer version of the library gets included in the project and the old version of the library will be also be present. OSGi lets us include different versions of the same library in the code base, so this should be OK.
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment -

            Great, thank you. I'll work on that.

            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - Great, thank you. I'll work on that.
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited

            Please see my changes at the branch below:
            https://bitbucket.org/pbadzuh/igb_pbdev/branch/IGBF-2490#diff

            These changes allow the bookmark and appstore IGB API endpoints to support https. The port for secured connections is simply one integer value greater than what is currently configured for http.

            In working on this issue, I have noted the following:

            • Browsers will block self-signed certificates, such as the one being currently used.
            • Making requests from the browser over the websocket protocol (ws://) on a secured overarching web connection results in a mixed content error, as with insecure http connections, so there doesn't seem to be any reason to use ws over http.

            Further work:

            • All client applications will need to be updated in order to utilize either http or https, based on browser limitations. The easiest method of doing this, as I see it, would be to attempt an http request first, and if a mixed content error is raised, reattempt the request using https. This would ensure maximal browser support.
            • In order to make IGB https work, clients can either download IGB's certificate (over some other secured connection e.g . from bioviz) and instruct users to manually add it to their keychains (macOS) or truststores (windows) OR users can be redirected to another IGB https endpoint (not yet implemented) by changing the browser's window location, which would result in a browser-specific error message prompting users to accept the insecure connection, at which point IGB's certificate would be automatically added to their truststore, and the IGB endpoint could be made to redirect the user back to the client application, after which point https requests to the IGB API should occur without error.
            • The first option involves more manual steps for the user, but will be presented as intentional (which I think would be better), whereas the second option would require a potentially offsetting warning page.
            • There may be some nuances, however. For example, adding the certificate to the keychain on macOS was not enough to get IGB https to work on firefox; firefox still demanded a manual confirmation from within its warning page - it seems to manage its certificates internally.

            Please let me know what you think about the current server-side implementation as well as the potential ways forward, client-side.

            Testing:

            • I have tested the IGB API endpoints over http and https and everything seems to be in good order.
            • To replicate, try hitting the endpoints as shown below, for example.
              HTTP:
              curl  http://127.0.0.1:7085/getSpeciesVersionList
              

              HTTPS:

              curl  --insecure https://127.0.0.1:7086/getSpeciesVersionList
              
            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited Please see my changes at the branch below: https://bitbucket.org/pbadzuh/igb_pbdev/branch/IGBF-2490#diff These changes allow the bookmark and appstore IGB API endpoints to support https. The port for secured connections is simply one integer value greater than what is currently configured for http. In working on this issue, I have noted the following: Browsers will block self-signed certificates, such as the one being currently used. Making requests from the browser over the websocket protocol (ws://) on a secured overarching web connection results in a mixed content error, as with insecure http connections, so there doesn't seem to be any reason to use ws over http. Further work: All client applications will need to be updated in order to utilize either http or https, based on browser limitations. The easiest method of doing this, as I see it, would be to attempt an http request first, and if a mixed content error is raised, reattempt the request using https. This would ensure maximal browser support. In order to make IGB https work, clients can either download IGB's certificate (over some other secured connection e.g . from bioviz) and instruct users to manually add it to their keychains ( macOS ) or truststores ( windows ) OR users can be redirected to another IGB https endpoint (not yet implemented) by changing the browser's window location, which would result in a browser-specific error message prompting users to accept the insecure connection, at which point IGB's certificate would be automatically added to their truststore, and the IGB endpoint could be made to redirect the user back to the client application, after which point https requests to the IGB API should occur without error. The first option involves more manual steps for the user, but will be presented as intentional (which I think would be better), whereas the second option would require a potentially offsetting warning page. There may be some nuances, however. For example, adding the certificate to the keychain on macOS was not enough to get IGB https to work on firefox; firefox still demanded a manual confirmation from within its warning page - it seems to manage its certificates internally. Please let me know what you think about the current server-side implementation as well as the potential ways forward, client-side. Testing: I have tested the IGB API endpoints over http and https and everything seems to be in good order. To replicate, try hitting the endpoints as shown below, for example. HTTP: curl http: //127.0.0.1:7085/getSpeciesVersionList HTTPS: curl --insecure https: //127.0.0.1:7086/getSpeciesVersionList
            Show
            nfreese Nowlan Freese added a comment - https://letsencrypt.org/docs/certificates-for-localhost/
            Show
            nfreese Nowlan Freese added a comment - https://stackoverflow.com/questions/61742279/safari-only-codesandbox-unable-to-get-data-from-localhost-server
            Hide
            nfreese Nowlan Freese added a comment -

            Testing Cytoscape on 13.1.2 on Mac.

            Looks like the Cytoscape app store is not able to communicate with Cytoscape through Safari.

            Show
            nfreese Nowlan Freese added a comment - Testing Cytoscape on 13.1.2 on Mac. Looks like the Cytoscape app store is not able to communicate with Cytoscape through Safari.
            Hide
            ann.loraine Ann Loraine added a comment -

            A couple of (minor) change requests:

            • If it is possible to do this without a ton of extra work, can you segregate the changes related to upgrading NanoHTTP to the latest version into a different branch and then submit a PR for just that? I'd like to merge that in first and test it in isolation.
            • I noticed there is a commit .gitignore. Please take a look. That should be committed separately as well.

            Once the above aspects are handled, I'd like to test topic branch installer that has only the changes related to supporting HTTPS.
            In parallel, I'd like to set up an App Store EC2 for testing that would run its own custom App Store code that hits the new "https" endpoint in IGB.
            We would then test the flow in tandem – App Store and IGB – at the same time to validate their communication.

            Show
            ann.loraine Ann Loraine added a comment - A couple of (minor) change requests: If it is possible to do this without a ton of extra work, can you segregate the changes related to upgrading NanoHTTP to the latest version into a different branch and then submit a PR for just that? I'd like to merge that in first and test it in isolation. I noticed there is a commit .gitignore. Please take a look. That should be committed separately as well. Once the above aspects are handled, I'd like to test topic branch installer that has only the changes related to supporting HTTPS. In parallel, I'd like to set up an App Store EC2 for testing that would run its own custom App Store code that hits the new "https" endpoint in IGB. We would then test the flow in tandem – App Store and IGB – at the same time to validate their communication.
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited

            I have separated the changes into two commits, as per your request, however, I don't think that creating a new branch for the updated version of the NanoHttpd library would provide any benefit over just submitting as is, since all of the original functionality has been preserved. I have simply extended the original endpoints to implement HTTPS in new classes. So you should still be able to test the original endpoints with the changes as they are now. Please let me know if you think that creating a new branch would still be useful.

            I have also made and attached a flow chart for a proposed client-side logic that could be used to utilize the new HTTPS endpoints, when needed. Please let me know what you think.

            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited I have separated the changes into two commits, as per your request, however, I don't think that creating a new branch for the updated version of the NanoHttpd library would provide any benefit over just submitting as is, since all of the original functionality has been preserved. I have simply extended the original endpoints to implement HTTPS in new classes. So you should still be able to test the original endpoints with the changes as they are now. Please let me know if you think that creating a new branch would still be useful. I have also made and attached a flow chart for a proposed client-side logic that could be used to utilize the new HTTPS endpoints, when needed. Please let me know what you think.
            Hide
            ann.loraine Ann Loraine added a comment -

            Small change request for the diagram:

            • Place replace phrase "client application" with "Web browser" or "IGB" (depending on what it should be.)

            Once this is done please move back to "Needs first level review"

            Show
            ann.loraine Ann Loraine added a comment - Small change request for the diagram: Place replace phrase "client application" with "Web browser" or "IGB" (depending on what it should be.) Once this is done please move back to "Needs first level review"
            Hide
            rweidenh Logan Weidenhammer (Inactive) added a comment -

            I reviewed the flowchart and briefly spoke with Philip about how this function would work, and we discussed our most forefront usability concerns. We agreed that, with the warning page, the most important consideration in the design will be giving the user enough instruction and confidence to work through this uncommon interaction.

            Show
            rweidenh Logan Weidenhammer (Inactive) added a comment - I reviewed the flowchart and briefly spoke with Philip about how this function would work, and we discussed our most forefront usability concerns. We agreed that, with the warning page, the most important consideration in the design will be giving the user enough instruction and confidence to work through this uncommon interaction.
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited

            I have added an updated version of the flow diagram, with some minor changes to make things more clear.

            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited I have added an updated version of the flow diagram, with some minor changes to make things more clear.
            Hide
            ann.loraine Ann Loraine added a comment -

            Thanks!

            Further clarification request:

            • Third box: "is evaluated" - who and what is doing the evaluating?

            There are two software programs here - IGB itself and the browser. And a user!

            Could you maybe modify the flow diagram to use active voice for what the software programs are doing?

            Or it could be faster (and less work for you!) to have a short zoom session where you walks us through it. We could include other(s) who might work on it, as well.

            Show
            ann.loraine Ann Loraine added a comment - Thanks! Further clarification request: Third box: "is evaluated" - who and what is doing the evaluating? There are two software programs here - IGB itself and the browser. And a user! Could you maybe modify the flow diagram to use active voice for what the software programs are doing? Or it could be faster (and less work for you!) to have a short zoom session where you walks us through it. We could include other(s) who might work on it, as well.
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited

            Requests must be browser-specific due to variable browser security constraints, so it is the browser that must implement the logic to determine over what scheme they are to be made - HTTP or HTTPS. The cookie I have proposed would be set and referenced by the browser.

            I have updated the diagram and would be glad to meet over zoom whenever convenient for everyone who is interested, if there are any further questions. Just let me know.

            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited Requests must be browser-specific due to variable browser security constraints, so it is the browser that must implement the logic to determine over what scheme they are to be made - HTTP or HTTPS. The cookie I have proposed would be set and referenced by the browser. I have updated the diagram and would be glad to meet over zoom whenever convenient for everyone who is interested, if there are any further questions. Just let me know.
            Hide
            ann.loraine Ann Loraine added a comment -

            I'm confused about the second-from-the-top green tile. I don't understand how "referrer" can ever be IGB trusted endpoint. I thought "referrer" mean: the page containing a link you click. When you click a link in a page, then that page becomes the "referrer" for the new request you make upon clicking the link.

            Maybe it would be clearer if you split the green tile into two? Seems like there are two decision points here. First is: "Is this browser Safari"? If yes, you go on to the next decision point. (This next decision point is the one I don't understand.)

            Show
            ann.loraine Ann Loraine added a comment - I'm confused about the second-from-the-top green tile. I don't understand how "referrer" can ever be IGB trusted endpoint. I thought "referrer" mean: the page containing a link you click. When you click a link in a page, then that page becomes the "referrer" for the new request you make upon clicking the link. Maybe it would be clearer if you split the green tile into two? Seems like there are two decision points here. First is: "Is this browser Safari"? If yes, you go on to the next decision point. (This next decision point is the one I don't understand.)
            Hide
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited

            Sorry, you are right - using the referrer header alone would not work. I have updated the diagram logic and have tried make it account for every condition that I could think of. Please review and let me know what you think.

            Show
            pbadzuh Philip Badzuh (Inactive) added a comment - - edited Sorry, you are right - using the referrer header alone would not work. I have updated the diagram logic and have tried make it account for every condition that I could think of. Please review and let me know what you think.
            Hide
            ann.loraine Ann Loraine added a comment -

            Design is sufficiently investigated. Moving to Done.

            Show
            ann.loraine Ann Loraine added a comment - Design is sufficiently investigated. Moving to Done.

              People

              • Assignee:
                pbadzuh Philip Badzuh (Inactive)
                Reporter:
                pbadzuh Philip Badzuh (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: