EIP-7272 Ethereum Access Token (EAT) (Ethereum Access Token)
No call decision · Security & privacy · EIP status Draft · created 2023-07-03
A standard in which an off-chain service issues an EIP-712 signed token to accounts that pass screening, and a smart contract verifies that token on-chain to temporarily permit a specific function call.
Why it is needed
Today, access control in smart contracts is usually done by registering roles in the contract in advance, or by letting through only addresses that hold a specific NFT. However, these approaches do not suit permissions that are valid only for a short time or screening criteria that change often. With an on-chain registry, the operator must always keep the registry up to date, and an unqualified party can get through while an update is delayed. Also, if eligibility screening requires sensitive information such as identity data, it is undesirable to put that information on a publicly viewable blockchain and query it there. This proposal leaves screening to an off-chain (outside the blockchain) service, issues a short-lived signed token only to accounts that pass, and has the token verified on-chain. Each time a user comes to request permission, the issuer gets a chance to check and update its records, and personal information does not remain on the chain.
What changes
Today
- The contract controls access using only on-chain information, such as role registrations or NFT ownership checks
- Changing the permission criteria requires modifying on-chain state, and the burden of managing the registry falls on the operator
- Using sensitive eligibility information as a basis risks exposing that information on the chain
After EIP-7272
- An off-chain service issues an EIP-712 signed token (EAT) to accounts that pass screening
- Permission criteria can be changed off-chain, with no on-chain change needed
- The contract only verifies on-chain that the signature, expiry time, and call conditions match, and personal information is never put on the chain
Who is affected
- Dapp developers: An access control layer can be added to existing functions with minimal changes. It works by inheriting the AccessTokenConsumer contract.
- Service operator (issuer): The security of the off-chain server that issues EATs is the security of the entire gate. If the server is compromised, tokens can be issued to unqualified accounts.
- Users: Users go through eligibility screening off-chain, then include the issued token in a transaction and call the function directly within the permitted period.
In depth
Token structure: signature and expiry time
An EAT consists of the signature values v, r, s (uint8, bytes32, bytes32) and an expiry time expiry (uint256). The signature is created as an EIP-712 structured data signature, and the signed payload is the struct AccessToken { uint256 expiry; FunctionCall functionCall }. FunctionCall consists of functionSignature (bytes4, a function identifier that must match msg.sig), target (the address of the called contract), caller (the current caller address, which must match msg.sender), and parameters (the rest of the calldata after the leading v, r, s, and expiry parameters are removed). Binding the token to concrete parameters at issuance time in this way ensures fine-grained access control.
Six things on-chain verification guarantees
On-chain EAT verification checks the following: whether the called function is the expected one, whether the function parameters are the expected values, whether the caller is the expected account, whether the call falls within the permitted period (the token has not expired), whether the called contract is the expected one, and whether the entity that granted permission is a valid issuer (one of the expected issuers signed it). All six conditions must hold for the function to be allowed to execute.
Two contracts: Consumer and Verifier
The reference implementation is split into two contracts: AccessTokenConsumer, which a contract that wants to protect its functions inherits, and AccessTokenVerifier, which is dedicated to EAT verification. The Consumer calls the Verifier to check the integrity of the token. The Verifier's verify() function takes a signature and an AccessToken as input, checks that the token has not expired, recovers the signer from the reconstructed EIP-712 digest and the signature, and then verifies that the signer is a valid issuer. An EAT gate can be attached to any function except the receive and fallback special functions.
Similar to JWT, but built for on-chain verification
Like the JWT (JSON Web Token) used on the web, an EAT is used for short-lived authorization, but it was designed from the start for on-chain verification and for authorizing smart contract function calls. Because it follows EIP-712, it is compatible with existing Ethereum infrastructure and also gets the effect of binding the token to a specific chain. The reference implementation guarantees that a token can be used only once (single-use), but other implementations may choose other approaches. The document also explains why it chose a simple signed message over zero-knowledge proofs (ZKPs): ZKPs add complexity and come in many varieties that hurt interoperability, whereas ecrecover is available by default in any Ethereum smart contract.
Security considerations
There are three key points. First, replay attacks. An implementation MAY mark a token as used in the _consumeAccessToken function so that a consumed EAT cannot be reused. Second, the security of off-chain issuance. The security of a function protected by an EAT depends on the security of the issuing service, so if the service is compromised, a malicious actor can obtain tokens that grant access to on-chain resources they should not be able to reach. Third, balancing the expiry time. If expiry is too long, the risk of token misuse grows, and if it is too short, the usability of the application suffers.
Draft status and discussion
This proposal is an ERC on the Standards Track, and its status is Draft. The specification may still change. In the core developer call records, it was discussed at 09.16 AMA #15, and no decision was made.