ethlogin - Ethereum based authentication

Actors
  1. Client - user browser (not trusted)
  2. Identity server - ethlogin (trusted)
  3. App server - site backend server (trusted)
Purpose
  1. Verify the user identity
    Example
Requirements
  1. Metamask extension installed on the client browser.
  2. Client key registered with ethlogin. Client key = a key specific to your domain.
Login Flow
  1. User clicks on the Login button. The button is part of an iframe. Note that the client key is passed to the iframe as a GET parameter.
    The iframe src: https://ethlogin.com/signin_v1.html?client_key=...
  2. User is asked to sign a message:
  3. The client receives an object from the iframe, using window.addEventListener (see the example source) with the user names and address.
    {
      "valid": true,
      "hex_message": "0x3132372e302e...",
      "address": "0xad008000005e7d58c6508071e03f48",
      "names": [
        "erel.eth"
      ],
      "signature": "0xf03ff824d66666668bc86e1eb5b0cc76ad07617576c5dacab4b130c37093775714431f13db69ae4dd4e9a7e253426fe9e3c97946e8c1e01fa93326c5c27be1c",
      "name": "erel.eth",
      "message": "example.com wants you to sign in with your Ethereum..."
     }
    				
  4. If the valid value is true then the user was supposedly authenticated. However, as we can't guarantee the user input, we need to verify the message integrity on the server as well.
  5. Client sends the object to the app server.
  6. App server creates a json string with the client key and the message received from the client (no need to parse the client message, it is added as a string).
    {
        "client_key": "301bc559-9859-409d-868e-7d3cd175ff50",
        "client_info": "{\"valid\":true,\"hex_message\":\"0x3132372e302e302e312077616e74732...5300a\",\"address\":\"0xad0...6508071e03f48\",\"names\":[\"erel.eth\",\"אראל.eth\"],\"signature\":\"0xeacac1688f2ddf769b997d60a316ec319fb8c6af3b2ab135dd90aa582509300a3de20c07d905b05dd13c59967fe499772253c4fd0ea0ed6ac83d462312e331811c\",\"name\":\"erel.eth\",\"message\":\"127.0.0.1 wants you to sign in with your Ethereum account:\\n0xad008ad5f5c9a0405e095e7d58c6508071e03f48\\n\\n\\nURI: http:\/\/127.0.0.1:51042\/test.html\\nVersion: 1\\nChain ID: 1\\nNonce: eda7293c\\nIssued At: 2021-11-16T13:27:50.286Z\\nClient Key: 301bc559-9859-409d-868e-7d3cd175ff50\\"}",
    }
    
  7. App server sends the json string to the identity server - https://ethlogin.com/verify_identity_server/v1
  8. Identity server replies with a json response:
    		{
        "valid": true,
        "hex_message": "0x3132372e.....331305a0a436c69656e74204b65793a2033303162633535392d393835392d343039642d383638652d3764336364313735666635300a",
        "address": "0xad008ad.....58c6508071e03f48",
        "names": [
            "erel.eth"
        ],
        "signature": "0x831e022b733f7708e.......0b0a188d502257eba6791c",
        "name": "erel.eth",
        "message": "example.com wants you to sign in with your Ethereum account:\n0xad00Z\nClient Key: 301bc559-9859-409d-868e-7d3cd175ff50\n"
    }
    
  9. If the valid value is true then the app server can trust the user identity.
Notes
  1. Messages are valid for one hour.
  2. The above flow is open to phishing attacks.
    It is possible to prevent such attacks by setting a random nonce on the app server. The nonce should be passed to the iframe as a GET parameter with the nonce key.
    The same nonce should also be added to the json that is sent to the identity server (with the nonce key), in step #6. The identity server will reject the message if the nonce in the message doesn't match.