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

Webauthn script not loaded on localhost due to Content Security Policy violation #355

Open
natalian98 opened this issue Nov 12, 2024 · 9 comments
Labels
bug Something isn't working frontend This is a UI issue

Comments

@natalian98
Copy link
Contributor

natalian98 commented Nov 12, 2024

The passwordless login method is broken in the latest login ui version.
To reproduce:

  1. Run the docker compose with login ui image >v0.17.0, create a hydra client and run grafana.
  2. Go to localhost:2345, log in with the test user.
  3. Go to localhost:4455/ui/setup_passkey. Insert any key name and click on Add. The console will display the following errors:
Refused to load the script 'http://localhost:4433/.well-known/ory/webauthn.js' because it violates the following Content Security Policy directive: "script-src 'self' 'unsafe-inline' 'unsafe-eval'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.

framework-2c16ac744b6cdea6.js:9 Uncaught TypeError: r.__oryWebAuthnRegistration is not a function
    at onClick (127-3320e06beedeceb7.js:1:2103)
    at Object.eU (framework-2c16ac744b6cdea6.js:9:14908)
    at eH (framework-2c16ac744b6cdea6.js:9:15062)
    at framework-2c16ac744b6cdea6.js:9:33368
    at re (framework-2c16ac744b6cdea6.js:9:33467)
    at rn (framework-2c16ac744b6cdea6.js:9:33881)
    at framework-2c16ac744b6cdea6.js:9:39337
    at oN (framework-2c16ac744b6cdea6.js:9:96304)
    at eF (framework-2c16ac744b6cdea6.js:9:14046)
    at ro (framework-2c16ac744b6cdea6.js:9:35172)

Due to this error, the webauthn.js script is not loaded and the QR code pop-up is not shown.

This seems to be caused by #299 (I tried removing the changes it introduced and the script was loaded correctly).

@natalian98 natalian98 added the bug Something isn't working label Nov 12, 2024
Copy link

Thank you for reporting us your feedback!

The internal ticket has been created: https://warthogs.atlassian.net/browse/IAM-1187.

This message was autogenerated

@nsklikas
Copy link
Contributor

This is expected to happen because the policy on https://github.com/canonical/identity-platform-login-ui/blob/main/pkg/ui/handlers.go#L38 defines that content should only be fetched from self and ubuntu.com. AFAICT specifying self does not allow for resources from different ports, so you can't fetch the script from kratos which runs on a different port. On our dev/staging environment all apis are served from the same origin, which is why this works.

IMO there are 2 ways to fix this:

  1. Add a configuration option that either deactivates the CSP (or makes it looser for localhost)
  2. We stop using eval on the frontend, as https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#controlling_resource_loading states in Inline JavaScript, using unsafe eval is the source of all evil:

Warning: Developers should avoid 'unsafe-inline', because it defeats much of the purpose of having a CSP. Inline JavaScript is one of the most common XSS vectors, and one of the most basic goals of a CSP is to prevent its uncontrolled use.

@natalian98
Copy link
Contributor Author

Thanks a lot for the analysis @nsklikas, that seems to be the reason because the passwordless login is only broken with localhost but works on PS6 with v0.18.1 deployed.

As a temporary workaround, this line can be commented out while testing webauthn on localhost.

@edlerd could you address these 2 points?

  1. Add a configuration option that either deactivates the CSP (or makes it looser for localhost)
  2. We stop using eval on the frontend, as https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#controlling_resource_loading states in Inline JavaScript, using unsafe eval is the source of all evil:

Warning: Developers should avoid 'unsafe-inline', because it defeats much of the purpose of having a CSP. Inline JavaScript is one of the most common XSS vectors, and one of the most basic goals of a CSP is to prevent its uncontrolled use.

@natalian98 natalian98 added the frontend This is a UI issue label Nov 12, 2024
@natalian98 natalian98 changed the title Webauthn script not loaded due to Content Security Policy violation Webauthn script not loaded on localhost due to Content Security Policy violation Nov 12, 2024
@edlerd
Copy link
Contributor

edlerd commented Nov 12, 2024

  1. Add a configuration option that either deactivates the CSP (or makes it looser for localhost)

The CSP is backend controlled, the frontend can't possibly change it. @BarcoMasile can you come up with a good solution? I would advise not to deactivate the CSP, that seems like a security risk to me.

  1. We stop using eval on the frontend, as https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#controlling_resource_loading states in Inline JavaScript, using unsafe eval is the source of all evil:

If I remember correctly, the kratos passkeys implementation depends on using eval. The js code including the GPG key is loaded dynamically and there is no way to get this to work without eval.

@edlerd
Copy link
Contributor

edlerd commented Nov 13, 2024

  1. Add a configuration option that either deactivates the CSP (or makes it looser for localhost)

The CSP is backend controlled, the frontend can't possibly change it. @BarcoMasile can you come up with a good solution? I would advise not to deactivate the CSP, that seems like a security risk to me.

Maybe the easiest way forward is to adjust the dev setup to use a proxy in the same way production does. This has the advantage of developing and testing on an infrastructure that is much more like the real deployment.

@natalian98
Copy link
Contributor Author

I would advise not to deactivate the CSP, that seems like a security risk to me.

We don't want to fully deactivate it, just loosen for localhost for dev and testing purposes, perhaps as a config option.

If I remember correctly, the kratos passkeys implementation depends on using eval. The js code including the GPG key is loaded dynamically and there is no way to get this to work without eval.

I don't recall that, passkeys support was added before the security policy was introduced in #299.

Maybe the easiest way forward is to adjust the dev setup to use a proxy in the same way production does. This has the advantage of developing and testing on an infrastructure that is much more like the real deployment.

That could be a solution, but I'm not sure we want to add another piece to the dev setup. We'll discuss that.

@BarcoMasile
Copy link
Contributor

@edlerd @natalian98 @nsklikas
I agree that the way to go is to have a "dev config" that we use for local development, and a "prod config" for real deployment.
We don't have that already. Usually web frameworks use the concept of a "profile", to distinguish between setups like the ones mentioned.
I'd say let's patch this with an ugly if, and have in our backlog a task to initialize this kind of setup.
Agree?

@edlerd
Copy link
Contributor

edlerd commented Nov 13, 2024

I'd say let's patch this with an ugly if, and have in our backlog a task to initialize this kind of setup.

Though this is an easy fix, I see the downside of leaking complexity from the development environment into production code.

@edlerd
Copy link
Contributor

edlerd commented Nov 22, 2024

3. We stop using eval on the frontend, as https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP#controlling_resource_loading states in Inline JavaScript, using unsafe eval is the source of all evil:

If I remember correctly, the kratos passkeys implementation depends on using eval. The js code including the GPG key is loaded dynamically and there is no way to get this to work without eval.

Had some time to check the details on this today. We do not use eval any more. This was limited down to json parsing. So we need to allow to use received data as arguments. This is mandatory for webauthn, to have the object with the keys that is an input argument for the __oryWebAuthnLogin and __oryWebAuthnRegistration functions. Both that come as js from kratos directly via the script that is mentioned in the original post above.

TL;DR: I think we can remove unsafe-eval from the CSP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working frontend This is a UI issue
Projects
None yet
Development

No branches or pull requests

4 participants