gm,
as some of you may know, I’m running a social media website built on the Ethereum stack. For those who don’t, it’s https://kiwinews.xyz
In any case, a core UX concept is that we use temporary keys that we create in the browser, store in local storage, and use for confirmation-less signing when a user upvotes, submits a link, or leaves a comment.
Now, we’ve obviously done that to provide our users with a better UX so that they don’t have to sign each interaction on the side cumbersomely using their custody wallet.
The system works by delegating posting rights from your custody wallet, for example, managed by your Rainbow or Metamask wallet, to this temporary key in your local storage. We use a simple delegation protocol on Optimism. The user has to send a transaction that connects the keys onchain for the Kiwi News nodes to witness the connection.
All this said a problem that has significantly lowered users’ engagement is that they naturally use multiple different browsers and devices. For example, a user may use a mobile and desktop device. Hence, creating multiple local-storage-specific keys is necessary, and leading them to delegate these keys on Optimism is necessary, too. But this is problematic because it is far from a seamless user experience. If we have to lead the user to send multiple transactions on Optimism, even if they’re virtual free in terms of costs, they cost us engagement and churn. Asking users to send transactions is scary to them and a drop-off point, so we try to avoid it.
Hence, a while ago, I actually started to look into solutions that would make the local storage key less perishable, and I also became interested in finding a solution that would somehow easily synchronize keys between a user’s mobile and desktop device.
In fact, with Apple and Google’s campaign to establish Passkeys more, I became really interested in them. I found out that there is the “largeBlob” extension, which allows the developer to store a small payload in iCloud. This payload is only accessible to the user when they authorize themselves with FaceID to Apple using Passkeys. This is useful as it allows me to store a full Ethereum private key in the largeBlob and retrieve it from any Apple device the user has later on.
So I ended up implementing Passkeys into my app, and it is actually fairly usable on Apple devices. The user can back up the temporary key using the largeBlob extension, and then upon “Connecting their Wallet,” they can consider “Connecting with Passkeys,” which essentially prompts them to authenticate themselves and then downloads the Ethereum private key from iCloud using largeBlob.
Honestly, this was great because I actually don’t have much concerns about storing this temporary key on iCloud:
- The temporary keys in Kiwi News are technically revocable onchain, and so if they ever leak or there are safety concerns, we could ask users to revoke their delegation.
- These keys aren’t meant to hold any funds. Their purpose is strictly to post content on behalf of the custody wallet and so, for a user who’s willing to opt in, I think it’s totally fair to post them to iCloud. That said, Kiwi News can be used entirely with your Ethereum wallet and you never actually have to delegate to a temporary wallet, so using Passkeys is optional as of now.
So, with that out of the way, let me tell you the caveats to using Passkeys:
- Apple and Google are fighting about integrating the “largeBlob” extension. My reading is that Google wants to go forward with PRF instead of “largeBlob,” and so my understanding is that PRF won’t allow developers to store arbitrary data.
- While there seems to be momentum for RIP-7212 for secp256r1, using this curve for Kiwi News (which would be reasonable) would mean that the user still has to authorize themselves pretty frequently using FaceID when signing stuff (which isn’t really a good trade-off for a social media site).
- As of now, the Passkeys integration that we’ve done has terrible browser and OS support. It basically exclusively works for Safari on Mac and iOS devices. Chromium-based browsers don’t seem to work because of Google’s unwillingness to implement them. iOS 16 devices don’t work. And there is a mysterious bug that if users use 1Password on iOS to manage their Passkeys, it breaks our entire flow. That said, it is my assessment that this entire situation will take years and not months to be fixed, too, which may be time that we don’t have as a startup.
- Finally, I think for an Android and Mac user, Passkeys will never seamlessly work as Google and Apple have decided that their respective solutions will only ever work well “in their ecosystem.”
So having found out all of this through integrating with Passkeys, it has made me feel rather pessimistic about their future, so I started looking for alternatives.
To solve this problem for users, recently, I’ve started considering privy another time, and I found that they perfectly solve our use case. For the sake of simplicity, I’m going to refer to the specific solution as privy, although there are also alternatives such as web3auth or dynamic, which, to my knowledge, all provide roughly the same service. My layman’s understanding of its inner workings is that:
- Users can connect their wallets as usual, and privy takes care of sending the signature request, etc.
- But privy also allows to provision so-called “embedded wallets,” which are (on a UX-level) essentially equivalent to the temporary keys that Kiwi News currently stores in the browser’s local storage, except that privy encrypts these keys, stores them on their servers (or in an iframe, I’m not sure how it works exactly), but in any case, this allows a privy-using developer to generate an embedded wallet that can be synced across a user’s multiple devices and browsers.
While privy is often touted as a tool to onboard new users to crypto, I’m actually not interested in allowing a user to, for example, start trying my site with a Google-login or whatever, but, instead, I find it really useful that embedded wallets can be synced across devices!
So, to me, as having already spent months trying to come up with a reasonable solution for my users, and considering that this issue really kills engagement on the site, I find it now quite tempting to integrate with privy. This is because privy, as opposed to other solutions, seems to work independently of whether Apple and Google find a solution to the largeBlob conflict. privy’s embedded wallet synchronization doesn’t rely on browsers finishing to implement new features, it just relies on a user being able to sign through the SIWE process.
Now, this integration, however, obviously comes with a caveat, which is that it will allow privy to hold my users’ keys hostage. What do I mean by that?
If I lead all my users to create an embedded wallet with privy, and so their temporary key is now stored with privy servers, then for my site to function, I will have to continue integrating with privy - and if I ever want to migrate away, I’d have to ask all my users to send a transaction to Optimism to delegate a new key. So logically, this will also allow privy to charge us quite a bit in the future. And it makes us reliant on them to provide a safe and properly functioning service.
In fact, I think, as of now, this entire situation doesn’t even yet warrant writing an Ethereum Magicians post, but I feel like there is a greater pattern at play here where companies try to intentionally capture a user’s keys because they know that this will increase their app’s moat.
Without trying to sound too accusatory, I think you can also see this with Warpcast’s strategy to generate their own Ethereum key in the app, as this is done to lock down the user’s key and hence make it rather unlikely for the user to swap into other clients/apps with that key as importing and exporting of seed phrases isn’t recommended and a scary act. All of this increases the defensibility of building their app. It makes it harder for others to compete as users are being locked into the ecosystem/app.
So, looking at how privy works and that it makes it very unlikely that, with integrating it, I will give my users the capability to “exit” with their embedded wallets, I couldn’t help but wonder what open-source alternatives exist that also address all my concerns above.
It seems to me that, at least for a site like mine, which doesn’t need the keys to hold actual money, there don’t seem to be that many requirements that would complicate an integration.
Additionally, I feel like this use case is integral for anyone building crypto consumer use cases as temporary wallet keys must inevitably somehow be synced across devices and browsers, and since the more financial-minded self-custody wallets (and Google and Apple) don’t seem to be too interested in providing solutions here. Their interest is in locking down the keys and keeping them safe instead.
Hence I would love to connect and hear other’s thoughts on this!
I feel like I’m pretty much in the trenches here as I’m one of the few who have attempted to build an actual social consumer use case with the Ethereum wallet stack that doesn’t primarily deal with sending funds around.
So I’d be super happy if this post actually had an impact where it’d change the strategy of some wallet providers in the future, where they start to pay attention to these use cases to help users keep custody of their keys.
Or, in case I haven’t done my research, it’d be helpful if there was something like a privy that I could somehow self-administer so that I’m not giving up control of my users’ keys to give them a better user experience.