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

Fix CORS with cookies #576

Closed
tobiasdiez opened this issue Oct 26, 2021 · 6 comments
Closed

Fix CORS with cookies #576

tobiasdiez opened this issue Oct 26, 2021 · 6 comments
Labels
p5: urgent For example breaking bugs affecting most users, should be released ASAP status: blocked Blocked by an issue / missing feature of a dependency, or by another issue type: bug Something isn't working type: decision-record type: developer experience

Comments

@tobiasdiez
Copy link
Member

As reported by @mohit038, it is currently not possible to authenticate with the API via a cross-origin request. The session cookie is included in the response from the API but then is ignored by the browser (i.e. not sent back in the next request).

Most likely, the problem is that we have Access-Control-Allow-Origin: * which doesn't work with credentials as described here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin. In this document, the recommend to take the Origin of the callee as the allowed origin. See also https://stackoverflow.com/questions/46288437/set-cookies-for-cross-origin-requests.

And finally there might be issues during development as localhost may need special handling: https://stackoverflow.com/questions/1134290/cookies-on-localhost-with-explicit-domain/1188145#1188145

@mohit038 You said you already tried a lot of different stuff to make this work. Can you shortly comment on if you tried also explicitly setting the "Allow-Origin" option, and if that didn't worked what else you tried in this combination.

@tobiasdiez tobiasdiez added type: bug Something isn't working type: developer experience p5: urgent For example breaking bugs affecting most users, should be released ASAP labels Oct 26, 2021
@tobiasdiez
Copy link
Member Author

Before changing this, we should think about how other services would interact with JabRefOnline in the first place and consider options like OAuth.

Then for now a quick-fix would be to have a special handling for calls from "localhost" when the server is in development mode.

@mohit038-zz
Copy link
Contributor

mohit038-zz commented Oct 27, 2021

we should think about how other services would interact with JabRefOnline in the first place and consider options like OAuth.

I think OAuth uses tokens for auth.

If you also tried explicitly setting the "Allow-Origin" option, and if that didn't work, what else did you try in this combination.

I've tried enabling the cors for localhost:3000 with the credentials set to true. I've also tried to change the cookie setting to make it work with cross-origin ( samesite=none, secure = true). But it didn't work.
Cookie:
cookie: {
secure: true,
httpOnly: true,
sameSite: 'none',
maxAge: 0.5 * 31556952 * 1000,
},

Cors:
app.use(cors({ origin: 'https://localhost:3000', credentials: true }))
async function startServer() { await server.start() server.applyMiddleware({ app, path: '/', cors: false }) }

I came across this article: https://docs.microsoft.com/en-us/office/dev/add-ins/develop/itp-and-third-party-cookies.

According to this article, "When developing Office Add-ins on Mac, access to third-party cookies is blocked by the macOS Big Sur SDK. This is because WKWebView ITP is enabled by default on the Safari browser, and WKWebView blocks all third-party cookies. Office on Mac version 16.44 or later is integrated with the macOS Big Sur SDK."

This could be an issue related MacOs, so could you please try on windows?
If it works on windows then I can try to set up a virtual machine.

And I think word online use iframe, and iframe does not store third-party cookies. So the only option we are left with is to run both addin and jabref on the same origin. Which is pretty complex, but I think we can set up a reverse proxy with Nginx and that is what I'm currently trying.

@tobiasdiez
Copy link
Member Author

Oh man, turned out I had to read quite a bit to catch up with the recommended auth strategies.

First of all, OAuth2 is indeed the recommended standard. In particular the "device code" flow may be helpful for auth with JabRef Desktop since then people don't need to enter their auths in the desktop app. I'll open a new issue for the OAuth stuff. But for the word addin this is not helpful at all for the following reason. Oauth's process looks as follows:
image
So, yes, it is using tokens to authenticate with the "resource server". But, and this wasn't clear to me at the beginning as well, is that the exchange of the authorization grant and the access token (step 3+4) is happening in the backend. So in detail it looks as follows:

  • After the user logged in and granted the application access to its profile, the auth provider redirects the users browser back to the application page with the "grant" as a url parameter.
  • The web app backend, gets this grant and calls the auth provider to exchange it for an access token (using its "client_secret"). Then attaches the access token to the user request (say by storing it in a secure http-only cookie).

So in this case you need a very slim backend (often called backend-for-frontend) that does the exchange grant > access token. To advantage is that the access token is never stored in plain text on the users side. Otherwise you would need to store it say in localStorage or something, which can be exploited.

This leaves us with the option of a) creating such a slim backend for the office addin or b) add a reverse proxy to put the office add-in on the same domain as the jabref online api. The first option is overkill in my opinion and the second looked like a lot of work. But it turns out that we don't need to worry about this at all since Azure provides a nice workaround. When you setup a Static Web app, you can link it with an existing Azure Functions instance and azure will provide an automatic proxy from say officeadd.jabref.org/api to www.jabref.org/api. See https://docs.microsoft.com/en-us/azure/static-web-apps/functions-bring-your-own. This also works locally by running

swa start ./output-folder --api-location http://localhost:7071

where the api-location is the running azure functions instance (i.e. jabref online api), see https://docs.microsoft.com/en-us/azure/static-web-apps/local-development.

So as a path forward I propose:

@mohit038 What do you think?

@tobiasdiez
Copy link
Member Author

tobiasdiez commented Jul 22, 2022

After reading a bit more, I came up with the following model:

  • An API www.jabref.org/api for all Jabref-provided services. This API uses session-cookies as authentication and disallows any cross-domain requests. For the Office add-in (and any other similar service in the future), we have two options:

    • a) Host the Office add-in at office.jabref.org, and add a proxy from office.jabref.org/api to www.jabref.org/api. On Azure, we can host both the main website and the office addin as static websites, with a shared azure function instance (and azure proxies automatically /api to the azure function instance). Depending on the domain set in the session cookie, users have to login again in the office addin or are automatically logged-in.
    • b) Host the Office add-in directly at www.jabref.org/office (which probably means that we have to proxy /office to the correct Azure instance). Then users are automatically logged-in in the office addin, as the session cookie is shared.

    I tend to use option a) as it seems to be the one which requires the least config / manual code.

  • In the future, an API api.jabref.org is added for third parties. In this case, it is important that authorization is implemented it in a way that requires user consent (e.g OAuth). Thus, an Auth-Bearer-Token is used instead of session cookie and cors are allowed from all origins.

@tobiasdiez
Copy link
Member Author

tobiasdiez commented Jul 22, 2022

Some progress is in #1242, but it currently doesn't work on Azure due to Azure/static-web-apps#108? or Azure/static-web-apps#588. Probably can be fixed via using a bring-your-own function app #1343.

Similar issue:

@tobiasdiez tobiasdiez added status: blocked Blocked by an issue / missing feature of a dependency, or by another issue type: decision-record labels Sep 15, 2022
@tobiasdiez
Copy link
Member Author

The first part of #576 (comment) is now implemented: The main website is a static web app that is connected to a bring-your-own-function-app. Linking to the office website is still missing, but let's track this in the office add-in repo. Moreover, let's see if there is indeed need for an api.jabref.org endpoint for external services

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
p5: urgent For example breaking bugs affecting most users, should be released ASAP status: blocked Blocked by an issue / missing feature of a dependency, or by another issue type: bug Something isn't working type: decision-record type: developer experience
Projects
None yet
Development

No branches or pull requests

2 participants