Signing into the backend with Ethereum and JSON Web Tokens
Written by: Jonathan Brown
In a previous life, before I got involved in blockchain technology, I was participating in the Drupal community for 10 years.
Towards the end of this period I created the integration between Drupal and Mozilla Persona. Persona was an attempt to make account management a proper part of web browser functionality. Ultimately, Persona was shut down.
Later, I learned about the MetaMask browser plugin. MetaMask enables a web browser to run Ethereum-based applications, essentially enabling front end Javascript (JS) applications to directly interact with Ethereum.
MetaMask will handle all account management responsibilities so it occurred that there were parallels between MetaMask and Mozilla Persona.
They are both browser-based plugins that can provide single sign-on functionality. The single difference: this is only one small part of what can be done with MetaMask.
The whole point of a DApp — short for decentralized or distributed application — is that there is no back end. This is where the blockchain comes in, helping track, sort and verify information between nodes or actors in the network.
Currently, JSON Web Tokens (JWT) are the trendy solution for managing user authentication.
Before JWT, websites would have to maintain a database table in the back end to record all active sessions and then match session IDs stored in browser cookies.
JWT is essentially a distributed session table. The back end cryptographically signs some claims about a user and the generated token is then returned to the client.
Every time the client sends a request they can present the token which will be cryptographically verified by the back end. If the back end needs to destroy a session it blacklists the token by adding it to a database table until it expires.
So, signing into the backend with Ethereum accounts using JWT seems like the obvious way forward.
I have created a small demo application as a proof of concept: https://github.com/vanbexlabs/ethereum-auth-demo
You can select which Ethereum account you wish to use in MetaMask.
When “Sign in” is clicked the Web3 environment (MetaMask / Mist) is requested to sign a message using the account’s private key.
MetaMask will then prompt the user to click “Sign”. This is to prove to the back end that they are in possession of the private key. In theory, MetaMask could have a dedicated user interface for signing in, but for the moment signing a message is all that is required.
The account address and signed message will then be returned to the back end where they are verified and a JWT token is generated. This token is returned to the browser for storage.
There is an ongoing discussion about where in the browser JWT tokens should be stored, which can be viewed here.
For maximum security users should utilize both cookies and HTML5 web storage. With web storage you are vulnerable to XSS where JavaScript injected into the page can read the token. With “HttpOnly” cookies they cannot be read from JavaScript, however they are susceptible to cross-site request forgery (CSRF).
This is where another website will trick the web browser into making a request to another domain that the browser has a cookie for. The solution to this is to have a CSRF token in HTML5 local storage that needs to be sent with the request.
Note: This token has not yet been implemented in the etherparty demo.
When “Who am I” is clicked in the demo application the back end will verify the token with express-jwt and the address will be returned to the client, displayed in a pop-up.