-
Notifications
You must be signed in to change notification settings - Fork 1
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
First steps #1
base: development
Are you sure you want to change the base?
First steps #1
Conversation
Unused dependencies (8)
|
When the CI passes I can test from mobile. The video looks like a pretty solid proof of concept though. |
I just tried a permit claim after reading this pull. I think it could be nice to make a simple typescript module that will self contain a couple of capabilities:
"Signing in" would be using the on device biometric. I imagine the user only needs to do this once every so often, and then permit claims can be super seamless. But if deterministic key generation is shaky then we will definitely need to use SAFE and all that infrastructure. I hope that we can deterministically and reliably generate a signing key per device as a first checkpoint of this tech as it seems significantly simpler. As a second checkpoint we can design the system to incentivize rotating keys, and making use of sponsored transactions (these require SAFE) @Keyrxng rfc |
I'm confident we can and that we're a few strokes away from it. If the package bundles signing in and caching then it'd be just the webauthn create/request/verify logic, GitHub sign in, an exported button and some localStorage calls. Credentials are scoped to the domain they are being registered at so should it be generic in that sense and tie the credential only to the invoking domain or should I aim to create a credential from this package which is discoverable across other
The re-auth in the video I'm sure was only because I had been spamming login/logout for the last few minutes, if that's what this comment is based on. But yeah it is possible with both OAuth and WebAuthn to not have to re-auth every time. following the premise in the first comment, they'd auth once via GitHub on
So right now the system should be aiming to make no use of SAFE? The first impl should create an EOA using our key derivation process and that is the 'user account', am I understanding you right there? If I am then are you suggesting too that the new module not contain any GitHub sign in logic and be just webauthn/keygen/caching? |
I think the first checkpoint is necessary to achieve for the second checkpoint. So for now perhaps it makes sense to get the standalone on-device signer part working before worrying about adding them to a SAFE (and associating the SAFE with a GitHub login.) |
Updated the video in the first comment, No creation just
I've had the faucet setup on Amoy and I'm sure the testnet is having a bad day today, I managed to get a few funding txs through but haven't managed more than one in the last hour of trying. As it stands, we have a deterministic EOA generated using a 12 word seed phrase made up of 12 different data points. 3 of which come from the org salt, two of them are the same value but a different representation of it. We are able to fund the newly created EOA with the faucet immediately upon creation (although this obviously is not the way it should be), we'll store the address in the DB and the user is able to use the With this the basics are covered. Now it's a case of migrating this UI to a NextJS build and running everything on the server that we can. Then it's a matter of ensuring that things are as secure as I think that they are. Beyond that is minor sorts of things such as;
While it's not out-of-the-question, it's likely preferable to avoid having to draw up smart contracts to facilitate things or to increase the security of ops isn't it? |
Exciting research and to see this! You shouldn't need the sign in with GitHub button. This is out of scope until we start working with SAFEs (see my previous comment) Instead just focus on creating the identity exclusively with webauthn. Each device should have separate signing keys so there no need to link any of them together using the GitHub user as the common link.
Why do we need org salt etc? Doesn't seem like the most lean approach.
Let's generate individual private keys instead of mnemonics. Individual keys are easier to work with. I only think that mnemonics are a useful concept in the context of onboarding to one's first wallet (like metamask) After that I always generate private keys instead. It's less overhead when writing scripts and such.
Cool and interesting. However with sponsored transactions we might not need to implement this But seems that the hard work is done already? If so then perhaps we can skip on the sponsored transactions idea?
Always focus on streamlining. It makes this feel a ton more futuristic for demos and presentations.
Focus on streamlining. Security considerations should be minimal. Especially for permit claims there's really no stakes.
We can worry about this later but I don't have a vision for this currently. If you require more entropy (I don't think this is necessary but I'll write this down here anyways) you can consider making an optional password as a salt. Although it would be much nicer to login to a wallet only after a face id biometric from my phone instead of dealing with passwords etc. |
Removing GitHub auth strips us of entropy, side-steps an advised best practice and weakens the security of the derived EOA. @rndquu's comment highlights points of failure when using just the credential information to derive the EOA.
const authEntropies = [
`${displayName}-${id.toString()}-${name}`,
`${userOauth.id}-${userOauth.ca}-${userOauth.iid}`,
`${cred.id}-${cred.type}-${cred.rawId}`,
`${wordlist.getWord(orgSaltIndexes[0])}-${wordlist.getWord(orgSaltIndexes[1])}-${wordlist.getWord(orgSaltIndexes[2])}`
] It adds a third layer of entropy that a bad actor would need to hack to break the algorithm.
If we remove GitHub, the user needs to decide Row 1, as we can't identify them. This makes adding a password easier if we decide to go that route, but it makes things less streamlined and less secure because we'd need this input every time and we probably should not store it in the browser.
The EOA mnemonic will never be exported or exposed; we'll work only with PKs but treat our seed entropy as a 12 "word" mnemonic. This can be simplified by buffering all data points and hashing them instead of turning each into a word. I felt following the mnemonic standard is generally a good idea as it's the Web3 wallet standard, but it might be extra steps without added benefit.
For the first iteration, we should use the faucet. We don't have the infrastructure for sponsored transactions, nor are AA solutions mature enough yet, this way we can get a decent beta test going with V1. This approach also allows supporting funding on many chains easily, even after having a dedicated Safe sponsored transactions flow. Cloning the relayer onto other chains is straightforward; the only issue is testnet gas to test them but if it works on one chain, it'll work on any OpenZeppelin Defender supported chain. Keeping them all topped up could be automated with Defender as well. Once SafeSDK releases passkey integration, we can have the EOA deploy a safe, bind the passkey to the safe, and stop using the EOA, depending on the SafeSDK passkey feature details, making moving into V2 seamless.
The most streamlined approach is also the most secure in my eyes considering rows 1 and 3 of the auth entropy. With OAuth:
Without OAuth:
|
If we only need to login once with GitHub then maybe it is the best approach. Anyways I wasn't too concerned about security because each device should have its own fingerprint and that's pretty impossible to guess, I assume. |
You are right they couldn't outright guess and are very unlikely to brute force it, if you mean the credential ID etc. But the ID is not bulletproof as it can be MITD'ed and is potentially hackable through the user keychain storage through simswap, account hacked etc we are relying on the user adhering to good security practices like only using trusted networks, good account security and hygiene habits which is too fragile imo.
The last project I built with Supabase auth/Nextjs I had indefinite sessions logged in until you physically logged out which we should advise I think but allow them the choice I guess |
Couldn't we handle everything client side without GitHub? If it's all generated on device etc then no man in the middle is possible. Fully on device is my vision.
Again if handled on device and no key exports allowed none of this is possible.
I wouldn't allow logging out. There's no benefit to it. One device should have one signing key. |
All-in-all, yes it's possible but then we need to get creative and use methods like fingerprinting which was shown to be less accurate than what we need it to be. Or other methods but each one is going to have it's list of cons and why not build with security in mind considering if one single account is hacked the reliability of the DAO and it's services sinks At the bottom are some comments taken from the docs, obviously there are hundreds of other things to consider as well. The docs are extensive and the configurability produces lots of possibilities and ways to get things done so I've linked just what I felt was immediately relevant without overdoing it. Things are geared towards preventing the credential from being accessed or used be another RP as well as the credential being resistant to doxxing someone. This is of no consequence to us, what matters is what data is potentially obtainable by any bad actor that makes up the seed for an EOA. If this is weak then everything else sort of falls flat so the more redundancy we add to this the better. Alternatively, implement WebAuthn to-spec with a username/password flow and produce a truly random wallet seed then store that private key/seed in the database exposed only after being fully webauthn'd. Which is more akin to a traditional user system and we only need to protect the database entry for this user. But it also centralizes things significantly which is has it's own downsides
MITM is still possible most notably during registration ceremonies but it's more than that. A lot of information is still potentially leakable so finding secure entropy becomes a problem if only using info obtainable from what the users authenticator returns On-device uses the secure credential (privateKey) keypair to sign data sent by the client in order to return a credential with This is the intended flow of the WebAuthn API and apparently so long as the registration ceremony is handled securely then future auth ceremonies are MITM-resistant. But keep in mind, that may not be true for our use-case depending on what we use for entropy from the credential. Because we are not storing these types of info and are relying on a derivation alg to generate our user system we need entropy from multiple locations that is independently verifiable to be our user, preferably that is itself an auth ceremony of some kind i.e username, password or OAuth which we can correlate to a user so we can identify them in order to create the credential and to derive their EOA. The docs mention improved UX via local storage of the credential ID but that's only beneficial if you have a backend to query that publicKey against and have a traditional user system. We want to limit exposing that ID as much as possible.
The security concern for us is how easy is it to break the pk algorithm? Passkeys are inherently secure if done right i.e for a hacker to log into a traditional account they need to perform great feats to bypass biometrics etc and those traditional accounts are bound to their domain i.e X, or whatever and if used on a 3rd party site they go through OAuth and run the WebAuthn flow. Our concern really is how easy is it to obtain the data used as entropy? Using easily and commonly exposed passkey IDs, name, displayName, or anything returned really from the authenticator alone is far too brittle. If it's user input it's likely easy to socially engineer or brute force. A hacker bypasses the inherent passkey protections if they are able to intercept an ID because it's a data point and it's not many steps from here to having EOA access (if they can breach our salt security) https://www.w3.org/TR/webauthn/#sctn-sample-registration
https://www.w3.org/TR/webauthn/#sctn-sample-authentication
https://www.w3.org/TR/webauthn/#sctn-security-considerations
https://www.w3.org/TR/webauthn/#sctn-privacy-attacks
|
One solution:
We can consider sponsoring these key rotations, but we might need to have a "master key" added to everybody's SAFEs to reset the signers. It can pay for the key rotation transactions. It might seem a little convoluted but the end result is that signing transactions will be totally seamless for the user. No prompts/confirmations/modals for permit claims. |
If we don't want the user having to confirm anything, delegate proposals are out of the question unless we do have that master key to auth incoming proposals or have the infrastructure to build their EOA tied to their credentials and confirm incoming txs with their owner key (we'd need to listen to all our users Safes, unless they confirm via a Safe UI (afaik)) I was thinking something along these lines:
Two is the only route where we avoid having to deal with entropy all together but the security concern then shifts onto securing the db and acc data.
I understand the vision clearly. Frictionless, streamlined UI with complete blockchain abstraction meaning no prompts, confirmations, or dealing with gas or funds. One is more attractive to me personally than two but it makes adding multiple passkeys for the same EOA difficult because we don't have a point of reference for the original. You'd want to be able to login with GitHub on your mac then on your blackberry and be able to access the same Safe. Unless you can share your passkey between devices like icloud this becomes a problem. Unless we store the user's credential in P.S I think Gnosis-sponsored 5x-per-day or whatever it was is only via official Safe UIs. In our case we'll likely need to be the sponsor, may be wrong here. https://help.safe.global/en/collections/9830-safe-mobile https://help.safe.global/en/articles/40799-what-is-a-delegate-key
https://help.safe.global/en/articles/40829-how-signer-keys-are-stored
https://safe-transaction-mainnet.safe.global/ (API)
As far as I can tell given the current state of Safe, a signing key is a "delegate key" and is supposed to be used for proposing transactions that are then confirmed by the owner key via an official Safe UI or via a non-delegate confirmation. Additionally, the signature threshold must be > 1 otherwise I assume that delegate key is going to actually propose and execute the tx, which is the same as just using the owner key. https://docs.safe.global/sdk/protocol-kit Adding an owner key seems to be more inline with what we need so it can actually confirm proposals but I think this may only be possible for iOS. If that master key is used in all accounts doesn't that create another huge security issue and to overcome this we'd need another keypair algorithm? I don't think that's the way to go either.
Because fingerprinting, at least the package we looked at, was 40-60% accurate I don't think it's accurate enough to produce reliable results and it's a lesser passkey as they are always going to be device-bound, more reliable and more secure. So any fingerprinting other than passkeys should not be used in my opinion.
That implies the EOA that deploys the Safe is derived purely from the GitHub login data. Subsequent attempts to derive this EOA would always require logging in or having that immediately available (so no localStorage allowed). And without WebAuthn to-spec it makes using it pretty useless if it's not used for entropy for the EOA because why even request it if we are not verifying or using it? |
I feel the length of my comments are beyond a joke and must be starting to annoy people. Is that the case, should I stop writing as much info or is it a good thing to have a lot of context? I'm trying to get the relevant context across I have and it's hard to do considering the depth of what's involved but tell me to stfu if I'm over doing it and I'll reign it in |
@0x4007 CI needs fixed in regards to OAuth because the allowed urls or redirect urls do not include a wildcard so that it allows auth on PR previews. Right now it redirects only to the official I'm mistaken I'm thinking of Auth0, GitHub only allow one redirect url and I don't think you can use wildcards. I could also point things to my supabase instance and setup my github app for OAuth and merge this so I have a fixed url to redirect to |
It might be easy to reverse engineer how they do it by looking at how the transaction is crafted on chain.
Writing is an art. Maximize signal to noise for any ubiquity communications. Share a ton of relevant context with your counterparties. I didn't do the deep research on authentication technologies so it's optimal to share only the absolute essentials. I wouldn't be able to add value to anything beyond essentials. I don't need to know implementation details of all that you researched. I only need to know tradeoffs. |
Some potentially useful technologies: |
To summarize webauthn and EOA creation is fully implemented. We have server-side transactions fully abstracted away from the user. The faucet was a performance issue but with the new plugin that's resolved and will be removed
|
Pushing at this point to see if CI will allow for proper testing and because using the up to date
safe-sdk
needs some node package workarounds.https://w3c.github.io/webauthn/#rp-id
By this logic registering the credential on
safe.ubq.fi
will allow it to be used onubq.fi
notpay.ubq.fi
. So maybe the domain for this UI needs to be an extension ofpay.ubq.fi
?Although looking at effective domains it seems that it would boil down to the domain > hostname so this will need tested.
pay.ubq.fi
we just request the credential and either A) use that credential to interact with the SAFE directly B) Use the credential to create a throwaway signer which, if possible, should be able to claim a permit into the SAFE.Basic QA showing account generation and persistence through
localstorage
only, no request logic implemented yetoauth-webauthn-pk.mp4