# Sign-in with Ethereum
## Links
- [Sign-in with Ethereum RFP](https://notes.ethereum.org/@djrtwo/sign-in-with-ethereum-RFP)
- [Veramo response](https://docs.google.com/document/d/155IX32AZi0Kyxj29f9k745_V5ZcuXs86xRUFIVAm5m8/edit)
- [Self-Issued OpenID Provider V2, draft 02](https://openid.bitbucket.io/connect/openid-connect-self-issued-v2-1_0.html)
- [URL Based Discovery for Trust Frameworks using SIOP](https://hackmd.io/@quartzjer/SIOP_Discovery_Trust_Framework)
## Why do we need a sign-in?
- To personalize UI/UX
- Settings
- Filter backend data
- To track users
## Sequence diagrams
- Open website
- Login
- Get the list of my articles
- Post a new article
### Simple web2 flow
```mermaid
sequenceDiagram
rect rgba(0, 255, 0, .1)
Browser->>+Service: GET /
Service->>+Sessions: Create session
Sessions-->>-Service: SessionId: 10
Service-->>-Browser: HTML + Cookie - SessionId: 10
end
Browser->>+Service: POST /login username, password, sessionId: 10
Service->>+Users: Check username+password
Users-->>-Service: UserId: 5
Service->>+Sessions: Update: SessionId: 10, UserId: 5
Sessions-->>-Service: success
Service-->>-Browser: success
rect rgba(0, 0, 255, .1)
Browser->>+Service: GET /my-articles, sessionId: 10
Service->>+Sessions: Get user - sessionId: 10
Sessions-->>-Service: UserId: 5
Service->>+Articles: Get - UserId: 5
Articles-->>-Service: articles
Service-->>-Browser: articles
Browser->>+Service: POST /article, sessionId: 10, body: foo
Service->>+Sessions: Get user - sessionId: 10
Sessions-->>-Service: UserId: 5
Service->>+Articles: Save - UserId: 5, body: foo
Articles-->>-Service: ArticleId: 3
Service-->>-Browser: Location /articles/3
end
```
### Oauth web2 flow
```mermaid
sequenceDiagram
rect rgba(0, 255, 0, .1)
Browser->>+Service: GET /
Service->>+Sessions: Create session
Sessions-->>-Service: SessionId: 10
Service-->>-Browser: HTML + Cookie - SessionId: 10
end
Browser->>+Service: GET /login
Service-->>-Browser: Location: google.com/auth
Browser->>+Google: POST /login username, password
Google-->>-Browser: Location: service/callback, token: abc
Browser->>+Service: GET: service/callback, token: abc, sessionId: 10
Service->>+Google: Get User - token: abc
Google->>-Service: UserId: 5
Service->>+Sessions: Update SessionId: 10, UserId: 5
Sessions-->>-Service: success
Service-->>-Browser: HTML success
rect rgba(0, 0, 255, .1)
Browser->>+Service: GET /my-articles, sessionId: 10
Service->>+Sessions: Get user - sessionId: 10
Sessions-->>-Service: UserId: 5
Service->>+Articles: Get - UserId: 5
Articles-->>-Service: articles
Service-->>-Browser: articles
Browser->>+Service: POST /article, sessionId: 10, body: foo
Service->>+Sessions: Get user - sessionId: 10
Sessions-->>-Service: UserId: 5
Service->>+Articles: Save - UserId: 5, body: foo
Articles-->>-Service: ArticleId: 3
Service-->>-Browser: Location /articles/3
end
```
### Web2 + DIDAuth flow
```mermaid
sequenceDiagram
rect rgba(0, 255, 0, .1)
Browser->>+Service: GET /
Service->>+Sessions: Create session
Sessions-->>-Service: SessionId: 10
Service-->>-Browser: HTML + Cookie - SessionId: 10
end
Browser->>+Service: GET /login sessionId: 10
Service->>+Nonces: Get new nonce
Nonces-->>-Service: abc123
Service->>+Sessions: Update session: 10, nonce: abc123
Sessions-->>-Service: success
Service->>Service: generate SIOP request
Service-->>-Browser: HTML + siop=' openid://nonce=abc123&cb=...''
rect rgba(255, 0, 0, .1)
Browser->>+OP: GET /login?siop=urlEncode(siop)
OP-->>-Browser: Location: cb?token=xyz
end
Browser->>+Service: GET cb?token=xyz, sessionId: 10
Service->>+Sessions: Get nonce - sessionId: 10
Sessions-->>-Service: abc123
Service->>Service: Verify token with nonce
Service->>+Nonces: Invalidate nonce: abc123
Nonces-->>-Service: success
Service->>+Sessions: Update SessionId: 10, UserId: did:ens:alice.eth
Sessions-->>-Service: success
Service-->>-Browser: HTML success
rect rgba(0, 0, 255, .1)
Browser->>+Service: GET /my-articles, sessionId: 10
Service->>+Sessions: Get user - sessionId: 10
Sessions-->>-Service: UserId: did:ens:alice.eth
Service->>+Articles: Get - UserId: did:ens:alice.eth
Articles-->>-Service: articles
Service-->>-Browser: articles
Browser->>+Service: POST /article, sessionId: 10, body: foo
Service->>+Sessions: Get user - sessionId: 10
Sessions-->>-Service: UserId: did:ens:alice.eth
Service->>+Articles: Save - UserId: did:ens:alice.eth, body: foo
Articles-->>-Service: ArticleId: 3
Service-->>-Browser: Location /articles/3
end
```
#### OP flow
```mermaid
sequenceDiagram
Browser->>+OPServer: GET /login?siop=...
OPServer-->>-Browser: HTML + decoded siop
Browser->>+AppFlow: nonce, domain, web3
AppFlow-->>-Browser: {did, claims, proof}
Browser->>OPServer: POST /sign-token {siop, did, claims, proof}
OPServer->>OPServer: sign JWT
```
#### App flow
```mermaid
sequenceDiagram
app->>+SDK: signIn(nonce, domain, web3)
SDK->>+web3Provider: connect
web3Provider-->>-SDK: account = '0x00...42'
SDK->>ENS: getName('0x00...42')
alt success
ENS-->>SDK: alice.eth
note right of SDK: did = 'did:ens:alice.eth'
SDK->>ENS: getText('picture')
ENS-->>SDK: 'https://example.com/avatar.png'
note over ENS,SDK: claims['picture'] = 'https://example.com/avatar.png'
else there is no ENS domain
ENS-->>SDK: false
note right of SDK: did = 'did:ethr:0x00...42'
end
SDK->>+web3Provider: eth_signTypedData
note over SDK, web3Provider: did, nonce, domain, claims
web3Provider-->>-SDK: signature
SDK->>SDK: validate signature with eth account and nonce
SDK-->>-app: {did, claims, proof}
```
#### ENS Web2 flow using SIOPv2 (simplified version)
```mermaid
sequenceDiagram
note over Browser: sign-in process starts here
Browser->>Backend: get sign-in page
Backend->>BackendSDK: sdk.createSignInRequest(<requested-claims>)
BackendSDK-->>Backend: <SIOPv2-request>
Backend-->>Browser: sign-in page, <SIOPv2-request>
Browser->>FrontendSDK: sdk.login(<SIOPv2-request>)
FrontendSDK->>Wallet: web3.connect
Wallet-->>FrontendSDK: <ETH-account>
FrontendSDK->>ENS: ens.resolve(<ETH-account>)
ENS-->>FrontendSDK: <ENS-name>
FrontendSDK->>ENS: ens.fetchClaims(<ENS-name>)
ENS-->>FrontendSDK: <claims>
note over Browser: <ENS-name> to DID defaults to<br/> simple secp256k1 auth/assertion key DID Doc<br/> if no DID/DID Doc text record was found
FrontendSDK->>FrontendSDK: sdk.discoverDid(<ENS-name>): <did:ens>
FrontendSDK->>FrontendSDK: sdk.createDataToBeSigned(<did:ens>, <claims>, <siop-nonce>, <siop-client>) : <EIP712-data>
FrontendSDK->>Wallet: web3.signTypedData(<EIP712-data>)
Wallet-->>FrontendSDK: <EthereumEip712Signature2021>
FrontendSDK->>FrontendSDK: sdk.packToken(<EIP712-data>, <EthereumEip712Signature2021>) : <id_token>
FrontendSDK-->>Browser: <id_token>
Browser->>Backend: submit <id_token>
Backend->>BackendSDK: sdk.verifyToken(<id_token>)
BackendSDK-->>Backend: <verified-user-info>
Backend->>Backend: createSession() : <session>
Backend-->>Browser: set <session>, <verified-user-info>
```
#### Proposal
##### Minimum Web3 Flow
```mermaid
sequenceDiagram
Frontend->>SDK: login
SDK->>API: GET /auth/nonce
API-->>SDK: nonce
SDK->>Wallet: connect
Wallet-->>SDK: eth account(s)
SDK->>Wallet: personal_sign
Wallet-->>SDK: signature
SDK->>API: POST /auth/token (signature)
API->>API: ecrecover, verify signature
API->>API: did:ens/eth address to DID
API->>API: sign JWT (HS256, publicAddress=0xabb, <br/> username=vitalik.eth, did=did:ethr:0xabb | did:ens:vitalik.eth)
API-->>SDK: JWT
SDK-->>Frontend: JWT
Frontend->>API: POST /other/endpoint with JWT
API-->>Frontend: ok
```
##### Better Web3 Flow
```mermaid
sequenceDiagram
Frontend->>SDK: login
SDK->>API: GET /auth/nonce
API-->>SDK: nonce
SDK->>Wallet: connect
Wallet-->>SDK: eth account(s)
SDK->>Wallet: eip2844, did_authenticate / did_createJWS(ethaccount)
Wallet-->>SDK: JWS with a DID
SDK->>API: POST /auth/token (signature)
API->>API: ecrecover, verify signature
API->>API: ens/eth address to DID
API->>API: sign JWT (HS256, publicAddress=0xabb, <br/> username=vitalik.eth, did=did:ethr:0xabb | did:ens:vitalik.eth)
API-->>SDK: JWT
SDK-->>Frontend: JWT
Frontend->>API: POST /other/endpoint with JWT
API-->>Frontend: ok
```
#### Questions
- The user needs to select which DID to use for the sign-in. How do we construct this list of DIDs?
- did:ethr:0x1234
- did:ens:simonas.eth
- did:nft:0x0000042:69
[Alternative SIOP diagrams](/V8sz7CVhSkO12nZBvNQtnw)