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

Store and load credentials from secure storage #11

Open
alanshaw opened this issue Sep 12, 2022 · 9 comments
Open

Store and load credentials from secure storage #11

alanshaw opened this issue Sep 12, 2022 · 9 comments
Labels
P1 High: Likely tackled by core team if no one steps up packages/core status/blocked Unable to be worked further until needs are met

Comments

@alanshaw
Copy link
Member

No description provided.

@alanshaw alanshaw moved this to Todo in w3ui Sep 12, 2022
@alanshaw alanshaw changed the title store and load credentials from secure storage Store and load credentials from secure storage Sep 12, 2022
@alanshaw
Copy link
Member Author

Currently these are stored in localStorage.

@alanshaw alanshaw added packages/core P1 High: Likely tackled by core team if no one steps up status/blocked Unable to be worked further until needs are met and removed package/wallet-core labels Sep 28, 2022
@travis
Copy link
Member

travis commented Nov 17, 2022

Do we have any ideas about what secure storage solution we could use for this?

I've bumped into this particular issue many times in the past and as far as I know the only solutions that aren't vulnerable to XSS attacks (eg, from a compromised tracking script on the page) involve storing secrets in a server-side session associated with an httpOnly cookie (https://dev.to/rdegges/please-stop-using-local-storage-1i04 has a decent rundown of the issues here).

FWIW, the Solid folks had the same problem building their client - this thread has some good links and analysis of the underlying issue, but the TLDR is that the only really "secure" place to store secure credentials in the browser is in a closure in JavaScript accessible by the library code that uses it. In practice this means the web client needs to go from identifier (ie, email address) to credential on every page load or refresh. In Solid this means redirecting the user to their identity provider, which usually just verifies they are logged in/authorized and then redirects them right back - this happens pretty fast so in practice the user experience isn't too bad, and we might need to implement a similar pattern here.

Nota bene - this is only an issue for client-side-only apps - any application with a server-side component that can securely store credentials in a session identified by an httpOnly cookie doesn't need to worry about this as much - XSS attackers could definitely abuse APIs the browser code has access to, but since the core credentials are never sent to the browser they can't access them.

@travis
Copy link
Member

travis commented Nov 17, 2022

Worth mentioning that it's at least possible to make the argument that storing tokens in localStorage is fine as long as you are diligent about avoiding XSS vulnerabilities - this is a slightly awkward thing for us to do as a library author, as we'd need to convince all consumers of this library that they should just focus on avoiding XSS attacks, but it's at least part of The Discourse around this:

https://pragmaticwebsecurity.com/articles/oauthoidc/localstorage-xss.html

@jchris
Copy link
Contributor

jchris commented Nov 17, 2022

I think we want to use non extractable keypairs eg navigator.credentials -- this is what forces us to lean so heavily on cross device delegation workflows

@travis
Copy link
Member

travis commented Nov 17, 2022

ok sweet - I think that's a much better approach, tho one I have less familiarity with, will do some reading!

@travis
Copy link
Member

travis commented Nov 22, 2022

Thanks @gobengo! For posterity - I was partly wrong - IndexedDB has provided a mechanism (as demonstrated by the gist from saulshanabrook) to store private keys specifically in a non-extractable format for a while now - this is great!

It sounds like the roadmap here is to use the new RSA signer support in ucanto to generate and store a private key in IndexedDB rather than storing a string in localstorage for now, and figure out how to integrate Webauthn (ie, navigator.credentials) into that flow soon.

@gobengo
Copy link
Contributor

gobengo commented Nov 23, 2022

and figure out how to integrate Webauthn (ie, navigator.credentials) into that flow soon.

WebCrypto (with .extractable = false) + IndexedDB can probably take us very far. We'll only need WebAuthn when we need to integrate with external authenticators, e.g. touchid/faceid, yubikey, etc.

@travis
Copy link
Member

travis commented Nov 28, 2022

Yep agreed - the one Passkey-specific thing that might be pretty convenient for us is that afaik Passkey implementations from Apple, Microsoft and Google all sync private key material for a particular user between devices. Even without a standalone keyring website I think this could make it easier for us to add new "agent" keypairs to a user's "account."

That said, I think in the short and medium term we'll need to provide a first-class experience for users who don't have Passkeys, so it's probably worth building and polishing all of that before getting too far into external authenticator support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 High: Likely tackled by core team if no one steps up packages/core status/blocked Unable to be worked further until needs are met
Projects
None yet
Development

No branches or pull requests

4 participants