-
Notifications
You must be signed in to change notification settings - Fork 491
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
Add ERC: Single Sign-On for Account Discovery #99
Changes from all commits
559c658
5b41011
7f595c8
057b915
ffcb995
bfb8f44
9b57954
8d12541
8cdf8d2
b1867bc
9ab54c1
fa0dc00
00637a5
4177534
db51ce8
9c9a582
f54218d
8ba9f7f
2878e73
c529934
e039598
d452225
e9c13a2
166ede7
7fd3915
926678a
cec1720
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
--- | ||
eip: 7555 | ||
title: Single Sign-On for Account Discovery | ||
description: Discover accounts using a signing key that do not use the secp256k1 curve. | ||
author: Alexander Müller (@alexmmueller), Gregory Markou (@GregTheGreek), Willem Olding (@Wollum), Belma Gutlic (@morrigan), Marin Petrunić (@mpetrunic), Pedro Gomes (@pedrouid) | ||
discussions-to: https://ethereum-magicians.org/t/erc-7555-single-sign-on-for-account-discovery/16536 | ||
status: Draft | ||
type: Standards Track | ||
category: ERC | ||
created: 2023-11-10 | ||
requires: 4337 | ||
--- | ||
|
||
## Abstract | ||
This proposal establishes a standardized interface and functionality for applications to discover user accounts besides the readily available EOA. Specifically discovering normal accounts and smart accounts that may have been deployed or configured using a signing key that is not the standard Ethereum secp256k1 curve. The objective is to ensure uniformity of address retrieval across applications, and domains. | ||
|
||
## Motivation | ||
The recent progress in account abstraction has led to significantly increased flexibility enabling use cases such as multi-signature transactions, social recovery, contract/account whitelisting, session keys and much more. However, with increased flexibility there comes an increased complexity. One area of increased complexity is account fragmentation -both at the EOA and smart account level - following from the inability to correctly identify all existing addresses by a user. In this EIP we present a potential solution that aims to unify the discovery and handling of such accounts. | ||
|
||
Prior to [ERC-4337](./eip-4337.md), the standard approach to interacting with a smart contract account required a valid signature from a keypair using secp256k1. Since ERC-4337, alternative signing options have become popular, such as passkey, yubikey or ios/android secure enclaves, which do not conform to the secp256k1 curve, and require a paymaster to submit the transaction on the users behalf. Since providers implement additional logic into the key generation process (shamir, mpc, secure enclave, etc) alternative signers have no uniform way for a user to produce the same externally-owned account adresses, or smart account addresses across different applications. | ||
|
||
Secure hardware devices such as native passkeys, or yubikeys generate a unique keypair per domain. The implication is for application developers that natively integrate authentication methods such as those, will never be able to recover a uniform keypair. Practically, if we have the following scenario where there are two applications: a mobile app (App A), and a web based application (App B). If both implement a solution such as passkey, App A and App B would recover two different keys. This poses a hurdle to the user who would expect to have the same address across services (much like they would using a hardware wallet, or other wallets). | ||
|
||
With the introduction of 4337, this problem is amplified. An application that wants its users to leverage 4337 (to abstract keys away, and generally improve the onboarding experience) will not be able to detect if a user has an existing smart account deployed. This will lead to the developer (or third party service providing the onboarding experience) to deploy a smart account on behalf of the user at the given address scoped to the apps domain. | ||
|
||
Not being able to correctly identify existing accounts owned by a user will lead to account fragmentation. The fragmentation, as described early, exists because applications will identify them as a new user, and not one whom may already have an account. Leading to a single user having many unassociated accounts, with assets scattered amongst them, and no way to unify them. | ||
|
||
This standard aims to achieve: | ||
1. Standard way for applications to request a users signing address. | ||
2. Standard way for applications to provide single sign-on (SSO) functionality for alternative signing methods. | ||
3. Standard way for applications to disclose smart accounts that have been created through their own service. | ||
|
||
This standard **does not** aim to achieve: | ||
1. How a user can sign messages across domains. | ||
2. How a provider generates a keypair for a user. | ||
3. How an application handles the user interface logic. | ||
|
||
|
||
## Specification | ||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174. | ||
|
||
GregTheGreek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
### Definitions | ||
- **Smart account** - An ERC-4337 compliant smart contract account that has a modular architecture. | ||
- **Domain** - A string of text acting as an identification to a server or wesbite (eg: `ethereum.org` or `ABCDE12345.com.example.app`). | ||
- **EOA** - Accounts that are controlled by a single private key. | ||
- **Provider** - A third party service provider that is able to authenticate a user and produce a keypair for the user. | ||
|
||
### Redirects | ||
An application looking to authenticate a user must navigate the user to a given provider's URI based on the `URI Request Syntax`. The application must implement a valid redirect URI for the callback in order to receive a valid response. | ||
|
||
#### Available Routes | ||
- `/auth/`: The route used to authenticate a user, and request credentials. | ||
- `/sendTransaction/`: The route used to send a transaction payload for a user to sign. This is more of a convenient method to allow applications to do both authentication, and plugin registration within a single redirect, instead of requiring the user to perform two redirects. | ||
|
||
### Schema | ||
The `smart_account_address` should be returned in the CAIP-10 format. | ||
GregTheGreek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#### Auth Route | ||
##### Request Schema | ||
```= swagger | ||
parameters: | ||
- in: query | ||
name: redirect_uri | ||
schema: | ||
type: string | ||
description: The uri that the provider should redirect back to. | ||
- in: query | ||
name: chain_id | ||
schema: | ||
type: string | ||
description: The chain_id of a given network. | ||
``` | ||
##### Response Schema | ||
```= swagger | ||
parameters: | ||
- in: query | ||
name: smart_account_address | ||
schema: | ||
type: string | ||
description: The on-chain address for a given smart account, formatted using CAIP-10 | ||
``` | ||
|
||
##### Request Syntax | ||
```= swagger | ||
https://<PROVIDER_URI>/auth/? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry if this is addressed elsewhere but where does the dapp get the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's undefined per this spec, it would be sourced from something external such as walletconnect directly applying it OR CAIP-275 |
||
redirect_uri=<YOUR_REDIRECT_URI> | ||
&chain_id=<CHAIN_ID> | ||
``` | ||
##### Response Syntax | ||
```= swagger | ||
https://<YOUR_REDIRECT_URI>/auth/? | ||
smart_account_address=<SMART_ACCOUNT_ADDRESS> | ||
``` | ||
|
||
#### sendTransaction Route | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do you need a separate route for getting [or in the case of multisig initiating?] a signature? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely a toss up - I think it can all be achieved within this one specific instance |
||
##### Request Schema | ||
```= swagger | ||
parameters: | ||
- in: query | ||
name: redirect_uri | ||
schema: | ||
type: string | ||
description: The uri that the provider should redirect back to. | ||
- in: query | ||
name: chain_id | ||
schema: | ||
type: string | ||
description: The chain_id of a given network. | ||
- in: query | ||
name: transaction | ||
schema: | ||
type: string | ||
description: The RLP encoded transaction that needs to be signed | ||
GregTheGreek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
##### Response Schema | ||
```= swagger | ||
parameters: | ||
- in: query | ||
name: smart_account_address | ||
GregTheGreek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
schema: | ||
type: string | ||
description: The on-chain address for a given smart account, formatted using CAIP-10 | ||
- in: query | ||
name: tx_hash | ||
schema: | ||
type: string | ||
description: The hash of the transaction | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. for a 4337 account, is this the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and in the case of a multisig or something that wasn't expected to be completed immediately, how shoudl the provider respond here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm this is a bit of a gap, do you have a suggestion here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can think about it but nothing obvious jumps to mind unf. Def think the latter should be handled, potentially would just say have two optional return params ( |
||
``` | ||
|
||
##### Request Syntax | ||
```= swagger | ||
https://<PROVIDER_URI>/sendTransaction/? | ||
redirect_uri=<YOUR_REDIRECT_URI> | ||
&chain_id=<CHAIN_ID> | ||
&transaction=<TRANSACTION_DATA> | ||
``` | ||
##### Response Syntax | ||
```= swagger | ||
https://<YOUR_REDIRECT_URI>/sendTransaction/? | ||
smart_account_address=<SMART_ACCOUNT_ADDRESS> | ||
&tx_hash=<TX_HASH> | ||
``` | ||
|
||
## Rationale | ||
### Redirects | ||
Taking inspiration from how SSO functions in the web today. We implement a similar redirect pattern, consisting of a simple request/response. | ||
|
||
#### Application | ||
##### Initial Request | ||
An application would redirect a user to a specified provider, only passing along the callback url information. This is to ensure the providers website can remain stateless, and not rely on web requests. | ||
##### Response from provider | ||
When a user is redirected to the application, it can parse the response for a signer address, and associated smart account address. | ||
|
||
#### Provider | ||
Upon a user navigating to the provider website, the provider would parse the redirect url and authenticate the user. The authentication method does not matter, such that it can produce a valid public address, and recover any smart accounts that may have been deployed through the provider. | ||
|
||
## Backwards Compatibility | ||
|
||
No backward compatibility issues found. | ||
|
||
## Reference Implementation | ||
Using `location.replace()` vs `location.href` is up to the application to decide how they wish the experience to be handled. | ||
|
||
Sample URI Request | ||
```= | ||
https://eth-sso.ethereum.org/auth?redirect_uri=http://myapp.com/eth-sso/callback/&chain_id=1 | ||
``` | ||
Sample Response | ||
```= | ||
http://myapp.com/callback/?smart_account_address=0xb...c | ||
``` | ||
|
||
Application logic | ||
```javascript= | ||
// https://myapp.com | ||
// User triggered authentication function | ||
function auth() { | ||
window.location.replace("https://eth-sso.ethereum.org/auth?redirect_uri=myapp.com&chain_id=1/eth-sso/callback/"); | ||
}; | ||
|
||
// App level routing logic (generic router) | ||
route("/eth-sso/callback/", function() { | ||
let params = (new URL(document.location)).searchParams; | ||
let smartAccountAddress = params.get("smart_account_address"); | ||
}); | ||
``` | ||
|
||
Provider Logic | ||
```javascript= | ||
// eg: https://eth-sso.ethereum.org/auth | ||
route("/eth-sso/callback/", function("/auth") { | ||
let params = (new URL(document.location)).searchParams; | ||
let redirectUrl = params.get("redirect_uri"); | ||
// Authenticate the user (eg: with passkeys) | ||
let address = "..."; | ||
// Get smart account if available | ||
let smartAccountAddress = getSmartAccount(address); | ||
window.location.replace(`http://${redirectUrl}/?smart_account_address=${smartAccountAddress}`); | ||
}); | ||
``` | ||
|
||
## Security Considerations | ||
|
||
<!-- Needs discussion. --> | ||
Check warning on line 204 in ERCS/erc-7555.md GitHub Actions / EIP WalidatorHTML comments are only allowed while `status` is one of: `Draft`, `Withdrawn`
|
||
- Is there a concern that a user can spoof another persons address, and that could be malicious? For example, circumventing the provider, and manually calling the redirect_url with a chosen address. A way around this would be having the user actually sign a challenge message, perhaps leveraging SIWE. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. afaik SIWE doesn't support eip 6492 atm which seems potentially problematic for 4337 accounts having said that, I don't see how manually calling the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure, was set as an open question last time I had a group call about this |
||
|
||
The absence of wildcard support in the redirect URI is intended to protect users from nested open redirect vulnerabilities. Allowing wildcards could enable attackers to redirect users to different pages under the supported wildcard, creating a vulnerability to open redirects. | ||
|
||
## Copyright | ||
|
||
Copyright and related rights waived via [CC0](../LICENSE.md). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's really just any smart contract accounts right? (e.g. this could be used to connect to a safe without going through WalletConnect iiuc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most likely yes, but leaving the door open for future innovation here.