# Sign-in with Ethereum Proposal v0.2
## Introduction
User authentication on dapps generally make use of a custom message signature, and most dapps tend to implement their own user flows for authentication. Standardizing these flows helps to improve security across the ecosystem, as well as improve compatibility and extensibility.
Using a user's Ethereum account to authenticate also allows them to reuse their existing on-chain information with new applications, and allows users to have full control of their data. In many ways, this is similar to the design goals of OAuth2.0, except that data on Ethereum is decentralised and controlled by the user. Signing in with Ethereum allows users to use data that they manage, instead of relying on centralised providers.
We propose an OAuth2.0 compatible solution for Ethereum Sign-in that provides a secure standard for user authentication for dapps, as well as a way for web2 applications to leverage Ethereum's capabilities. The main challenge here is to extend the OAuth2.0 specification to accomodate for Ethereum's non-custodial properties, and to avoid reinventing the wheel for authentication since many of the security and usability issues have been addressed as the OAuth2.0 spec has evolved over the years.
## Project Goals & Deliverables
On completion, this project aims to create an open specification for a Sign-In with Ethereum to be easily adopted by both Web3 and Web2 applications. The specification should achieve the following:
- Provide a method of basic authentication to server resources from Ethereum accounts (with EOAs or SCWs in mind)
- Standardise a method to authenticate among Web3 applications
- Inherit features from the OAuth 2.0 specification
- Browser and native security considerations
- Duration/sessions of authorization
- Compatibility with existing OAuth implementations i.e work alongside other logins (e.g. Google, FB, etc...)
- Scope permissions to Ethereum based user identity and be extendable to other forms of on/offchain attestation
- Avoid feature bloat
- Non reliance on centralised servers and/or minor project infrastructure
Alongside the specification, the project aims to deliver a suite of libraries and examples that result in ready for easy usage and distribution among both Web3 and Web2 applications. This includes a package using OAuth for easy implementation by web2 services, and a Javascript library for the user-facing part of sign-in.
## Project Approach & Schedule
In order to push out a well crafted and well utilized specification we believe its important to take a collaborative approach to be as comprehensive as possible. We describe our intended approach:
| Step | Duration | Description |
| -------- | -------- | -------- |
| Draft of initial specification | N/A | Drafted as a starting point for conversations |
| Survey exisiting approaches and usecases | Week 0 - 2.5 | Explore projects whom have broached the topic prior. Survey applications whom already authenticate users via their own methods. |
| Working group review | Week 0 - 3 | EF, ENS and other interested participants to review the draft proposal for three weekly sessions. |
| Specification v0.1 finalisation | End of Week 3 | Proposed targeted deadline for the first version of the specification. Freeze to large changes in spec. |
| Specification Implementation | Week 4 - 7 | Main project vendor and other interest parties to implement pilot implementations |
| Pilot Specification Users | Week 6 - 8 | Push out to potential interested users in Web3 and Web2|
| Specification Review | Week 7 - 8 | Review of specification after implementation considerations. Final edits before release of v1.0 |
| Examples, documentation and vendor library polish | Week 8 - 9 | Review of specification after implementation considerations. Final edits before release of v1.0 |
| Handover | Week 9 - 10 |Handover of code/repositories, creation of intended maintenance plans moving forward |
<!-- Leonard: I don't think handover is relevant here, since this is an open source project -->
## Known existing practices
We outline some of the known ways that dapps today are handling user authentication.
### Reading Ethereum accounts from Web3 provider
Several dapps read the ethereum address from the web3 provider and assume that the returned address represents the user. This approach is not secure against client-side spoofing attacks, since a user can edit the provider in the browser console to return any account address. This approach can work for applications that do not rely on user identity to store sensitive information, but for other applications this can be an issue. For example, on auction sites, wrongly identifying the user might allow unauthorized access to bidding history.
### Signing a challenge
This is the most common, as well as the most secure, approach to user authentication. In general, the dapp generates a one-time human-readable challenge message and requests for a signature over this challenge (using personal_sign). This is safe against client-sided spoofing attacks. It is also safe against replay attacks since the challenge is short-lived and randomly generated. However, it leads to additional user screens and can be unintuitive to the user since this same interface is used for Ethereum transactions.
### Linking Ethereum account to existing OAuth / social logins
Another common approach is to have the user connect their Ethereum account first, and then link their Ethereum account to a traditional OAuth provider like Google / Facebook login. Subsequent authentications on the site rely on this OAuth provider for user identification. This is also secure, but requires additional account-linking steps for the user during onboarding. This approach is also highly compatible with popular account management solutions like Auth0 or Firebase, which developers are familiar with.
## Draft Solution
Our approach is to focus on extending the existing OAuth2.0 specifications to handle Ethereum message signing as a form of authentication. This approach ensures that our solutions are backward compatible with OAuth2.0 frameworks which helps with adoption, and also allows us to leverage the security and strengths of the OAuth2.0 specification without reinventing the wheel.
The two most common OAuth2.0 flows are the implicit flow and authorization code flow. We will be relying primarily on the OAuth2.0 implicit flow, since the authorization code flow requires the use of a centralised server to make authorisation requests and many dapps do not run on centralised servers.
For Ethereum Sign-in, since the user manages their own data, the `resource_server` role (eg. Google servers holding profile data) in OAuth2.0 needs to be replaced with either an on-chain or off-chain source of data. For on-chain data sources it can be stored either as ENS records or in smart contract wallets, and for off-chain data sources it can be kept in the user's browser context. We describe the required interfaces for data sources below.
Traditional OAuth2.0 frameworks often expect the token issuing authority to also provide a canonical well-known endpoint (eg. https://www.googleapis.com/oauth2/v3/certs) that contains a set of JSON Web Keys (JWK Set, RFC8414) to validate the issued token. In the case of Ethereum sign-in, no such centralised authority exists since the claims are self-signed. Instead, each issued token should contain sufficient information for self-verification and it is unique for each user. We describe a dynamically generated verification set using ENS reverse-lookups that is backward-compatible with existing OAuth2.0 frameworks.
### Summary of modifications to OAuth2.0 specifications (RFC6749, RFC8414)
- Modification of authorization server to be the Web3 provider (RFC6749)
- Replacing `resource_server` with user-managed data source (RFC6749)
- Modification of JWK Set to be dynamically generated via ENS reverse-lookup (RFC8414)
These modifications are minor changes and modified components serve the same purpose/role as they did previously in the OAuth model. Care should be taken in the implementation of the transport layer in these modifications since the OAuth threat model assumes TLS for some communications.
### Authentication model - OAuth2.0 implicit flow

Sign-in with Ethereum defines four roles. We describe them with reference to the OAuth specification's roles below:
- **User**: A user looking to authenticate and login to a Requesting Application. The `User` and the `Wallet Provider` that he/she uses are respectively the `resource_owner` and `resource_server` with reference to the OAuth specification.
- **Wallet Provider**: A wallet client that the User is using to manage his/her key. Exposes a provider interface defined in [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) which we wrap to include rotation of the JWT and signing algorithm. With reference to the OAuth specification, the Wallet Provider fufills the `authorization_server` and on authentication acts as the `resource_server`.
- **Requesting Application**: An application looking to identify a user and/or retrieve attestations of the user, similar to the `client` in the OAuth specification.
- **Data Source**: This can be both onchain sources of `User` data, e.g. ENS records, Proof of Humanity etc... or offchain attestations and encrypted blobs.
Below we detail the steps in the Authentication Model:
**1. Authorization request** - When the user is authenticating with the requesting application, the requesting application makes an authorization request to the wallet provider, and the wallet provider redirects the user to a sign-in page.
The user is then prompted to sign-in with an identity. This identity can be either an EOA or smart contract wallet address.
**2. Request for user scoped data** - included in the request can be a list of user scoped data, of which the provider is dependent on to retrieve mentioned scopes from relevant data sources. These sources can be onchain or offchain kept information e.g a `User`'s ENS Name
**3. Handling of user scoped data** - the provider then handles user scoped data, often decrypting mentioned data.
**4. Issuing signed token** - on consent the wallet provider generates and signs an access token issuing it to the `Requesting Application`.
**5. Token verification** - the user is authenticated after verification of the token. The JWK which is typically authenticated against in OAuth is adjusted for an Ethereum Address.
Authorization flow for smart contract wallets

When considering support for SCW we include 3 further steps. If the user identity is a smart contract wallet, the wallet provider must do a reverse lookup to ensure that the private key in the wallet matches the claimed smart contract wallet address, as required in signature validation standards like EIP-1271. Likewise during validation, the `Requesting Application` must do the same.
### Authentication request example
Drawing from OAuth, the `Requesting Application` constructs the request with the following fields:
- `response_type` - REQUIRED. Value MUST be set to "token", in compliance with the implicit grant flow
- `client_id` - REQUIRED. The client identifier is to be replaced with the `Requesting Application`'s `redirect_uri`. This is necessary in compliance with the implicit grant flow
- `redirect_uri` - OPTIONAL. `Requesting Application` may restate their `redirect_uri`.
- `scope` - OPTIONAL. Originally the scope of the access request the returned token has. Given that we have a non-reliance on servers and instead `Wallet Providers`, we extend the functionality of scope to include an initial information request outline further in [].
- `state` - REQUIRED. An opaque value used by the client to maintain state between the request and callback. The issuance of this challenge helps for preventing cross-site request forgery as described in [].
### Token Scope
To request for information owned by the `User`, the `Requesting Application` may include in their [] request in the `scope` as per OAuth. The value of the scope parameter is expressed as a list of space-delimited, case-sensitive strings. The strings are defined by the `Wallet Provider`. In compliance with OAuth we choose omit the standardisation of values in `scope` in this specification, but note that it maybe a recommended future extension for onchain identity requests such as a `User's` ENS name.
### Access token example
The OAuth specification leaves implementation of the signed JWT token specific to the implementer. Given that Sign-in with Ethereum is expected to have many more signing authorities (every user) relative to the intention of OAuth (`resource_owners` like Google, FB etc...) to protect `Requesting Application` server resources from abuse we recommend stricter guidelines on a valid access token for access to server resources.
- `sub`- REQUIRED. (Subject) To be used as the Ethereum Address to be verified against. Commonly used in OAuth as a user identifier.
- `aud`- REQUIRED. (Audience) Claim. The "aud" (audience) claim identifies the recipients that the JWT is intended for and must be the `redirect_uri`
- `exp` - REQUIRED. (Expiration Time) Claim The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The processing of the "exp" claim requires that the current date/time MUST be before the expiration date/time listed in the "exp" claim.
- `iat` - REQUIRED. (Issued At) Claim. The "iat" (issued at) claim identifies the time at which the JWT was issued.
- `data` - OPTIONAL. If scope was authorized, to provide an key scoped object of relevant data from the request
- `iss` - OPTIONAL. (Issuer) Claim. The `Wallet Provider` issuing the token, in text/name form or signaure representation. To be potentially usable as a form of attestation for the user. (i.e. a Metamask User) See considerations.
### Access token verification
Unlike traditional OAuth, the verifying authority for the token is not a centralised entity, but the user. Instead, the tokens either need to be self-verifying, or there needs to be a dynamically generated verification public key that is derived for each user. We describe both approaches below.
#### Self-verifying tokens
Because the claims made in the signed token are made by the user, for EOAs, the token's signature itself is sufficient to verify the user's identity. This can be done using ecverify to recover the user's EOA adddress, and checking if it matches the address in the token.
#### Reverse lookup on Ethereum
For smart contract wallets or other identities that do not directly use an EOA, it is necessary for there to be a reverse lookup mechanism to validate that the claimed smart contract wallet or identity is tied to the private key that was used to sign the token.
For example, smart contract wallets could provide an API to return a list of valid EOAs that can be used to do Ethereum Sign-in on behalf of the smart contract wallet. This API would be used for validation by the wallet provider during authentication, and would also be used by the requesting application to verify the token.
## Security considerations
There are multiple known attack vectors from traditional OAuth that apply to Ethereum Sign-in. Alongside new security considerations, we describe them below and provide best practices to address them.
### Spoofing attacks
A malicious phishing site can trick the user into initiating a login session on their site, and prompt a login to a legitimate site.
In the OAuth2.0 implicit flow, this problem is mitigated by ensuring that the redirect url is whitelisted, so the malicious phishing site can never receive the access token even if they successfully get the user to login. A similar approach can be taken by applications implementing Ethereum sign-in, such that the user token must contain a field with a url that corresponds to the application's list of authorised urls. The `Wallet Provider` implementing the sign-in must ensure that redirections are restricted only to the `redirect_uri` that has been signed by the user.
### Operation of token generation context
In OAuth, token generation and issuance is conducted on a context provided by the `authorization_server`. For example, in the case of Google OAuth and others this is a centralized webpage that they own, relying on the browser's domain level security for the process of the authentication.
In Sign-in with Ethereum's case, this context needs to either be:
1. Sufficiently decentralized (e.g. webpage hosted on IPFS)
2. An already user trusted context (e.g. managed by a user's wallet)
Our proposal proceeds with the latter solution.
### Preventing server spam due to large volume of signing authorities
Given that Sign-in with Ethereum is expected to have many more signing authorities (every user) relative to the intention of OAuth (`resource_owners` like Google, FB etc...) there maybe a need to have more stringent checks to accessing `Requesting Application`'s server resources.
A clear methodology to achieving a better sybil resistance is using attestation surrounding the user, perhaps through ownership of an ENS name, activity on Ethereum, or other "Proof of Human" representations for authentication.
### Token interception
The communication between parties in the OAuth implicit flows are assumed to be secured by TLS. Like-wise, client-to-server communications in the Ethereum Signin model also require TLS for security. However, we expect that some of communication might be done completely in the front-end (eg. the communication between the wallet provider and the requesting application), and in those cases it is important to ensure that the token data is not intercepted. Existing tools like WalletConnect's bridge server model can be used here to prevent token interception since the data is encrypted end-to-end.
## Extensions and future work
### Data privacy / verifiable credentials
In the flows above, the abstraction around the data source is to allow for future extensions that enable privacy-preserving zero-knowledge proofs on the user's data, and also to ensure that use-cases like off-chain storage of user data are supported. There are several well-established standards like Verifiable Credentials (https://www.w3.org/TR/vc-use-cases) that can be used here. We consider this to be out of the scope this proposal, but it is essential to structure the proposal such that extensions for these use-cases can be built and easily integrated in the future.
### Multi-chain support
The proposal primarily focuses on Ethereum mainnet but most of it can be easily ported to support testnets or even other blockchain ecosystems. One potential challenge is to support other blockchains that already come with native account management systems, but most other blockchains with smart contract functionality are compatible. One concern is around the fragmentation of information if multiple blockchains are supported as sources of information, but this can potentially be solved at the application level (i.e. mainnet apps always refer to mainnet smart contracts, testnet apps always refer to testnet smart contracts, etc.).
### Support for DID and SIOP standards
In order to gather even more widespread adoption, it's important that the implementation is compatible with other specifications that have been developed like the Decentralised Identity (DID) and Self-Issued OIDC Provider (SIOP) specifications, which have been pushed out to achieve many of the decentralised goals that overlap with some of the goals that are outlined in this RFP. On this front, we believe that working with experienced individuals like Oliver Terbu and Rouven Heck on the Consensys Mesh team on further developing a joint proposal to address these challenges would be a great way to get even wider adoption among Web2.0 companies.
## Team
Working Group:
Leonard Tan
Yong Zhen Yu
Hadrien Croubois
Implementers:
Leonard Tan