The common design of decentralized applications (DApps) relies not only on the Ethereum blockchain, but also on the API layer. In this case, the DApp interacts with the smart contract through the user’s Ethereum account and with the API layer through JWT tokens issued by exchanging user credentials.

The goal is to request JWT tokens using ethereum accounts as user credentials.

The simplest approach might be to ask the user to trade on Ethereum with other randomly generated data, and then check the transaction and random data before issuing a JWT. This approach has several side effects:

  • 1. The user must transact and pay gas for simple authentication.
  • 2. Users must wait 12-120 seconds (gas based on consumption) to complete the authentication process.
  • 3. All logins for each user become non-public on the Ethereum blockchain.

Since this approach is impractical and has some user experience limitations, we need a way for the user to prove that he has the private key associated with the account he wants to log in to, rather than just (of course) asking for the private key regardless of whether he makes a transaction.

The solution

This article by Dan Finlay, a member of the Metamask team, inspired this tutorial for me. Basically, your DApp can prompt the user to sign the message using his private key. This signing operation does not generate a transaction, and it is handled transparently by the Metamask add-on (by the way, your account needs to be unlocked). After signing, the account, message, and signature are sent to the API Token endpoint. The validation method begins by inferring the account (also known as the public key) from the signature by a function that accepts a signature and a plaintext message as input. If the ethereum address calculated is equal to the account provided by the user, a JWT Token is issued for that account.

It is important to note that the entire authentication process does not require a username/password or OAuth external service. The mechanism used to verify a user’s identity is the same one ethereum uses to secure the Ethereum blockchain. This is thanks to Go Ethereum (Geth) providing web3.personal. Sign in JSON RPC via the Metamask plugin.

The server side calls the corresponding JSON RPC to retrieve the account from the signature: web3.personal. Ecrecover. In this tutorial, we’ll build an Asp.Net Core 2 project as an API layer and a simple HTML/javascript client as a DApp to demonstrate this authentication process in action.

  • 1. Click the login button from the DApp user. This requires web3 objects provided by Metamask.
  • 2.Metamask requires the user to go through JSON RPCweb3.personal.signSign the message.
  • 3. The signature is sent to the API layer through the JSON RPCweb3.personal.ecrecoverVerify the account.
  • 4. After validation, the API layer will publish the JWT.

A prerequisite for

  • 1. Install the Metamask plug-in for Chrome or Firefox. The add-on “brings Ethereum to your browser.” In fact, Metamask provides a Web3 object that interacts with the Ethereum blockchain in your DApp, processes your private key and manages transactions in your browser.
  • 2. Optional. Run the Geth node. I’ll show you two ways to recover an Ethereum account from a signature, one of which requires your API layer to call JSON RPC against the Geth node. Note: Infura doesn’t work yet, as they don’t allow mostweb3.personal.*JSON RPC interface. For development purposes, running the Geth node is simple. In a production environment, running a Geth node is not an easy task for security reasons. The best way to do this is to rely on the Blockchain as a Service Stack (BaaS) provided by AWS or Azure.
  • 3. Development stack: Visual Studio 2017 and Node Package Manager (NPM).
  • 4. Basic knowledge of Ethereum /Asp.Net core/front-end development and JWT certification process.

start

Open Visual Studio 2017, create EthereumJwtSolution and add two Asp.Net Core 2 Web application projects: EthereumJwtApi and EthereumJwtClient. Select empty project scaffolding for both projects.

EthereumJwtClient is just an HTML/Javascript client. We’ll build the client application on TOP of Asp.Net Core, just to run it easily on IIS Express.

We need to prepare EthereumJwtApi to create and process JWT tokens to protect some secure endpoints. The task was simple, because Asp.Net Core 2 has a built-in JWT mechanism to plug into our application. Open startup. cs and modify the ConfigureServices method:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = Configuration["Jwt:Issuer"],
            ValidAudience = Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
        };
    });

    services.AddCors(options =>
    {
        options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials()
        .Build());
    });

    services.AddMvc();
Copy the code

Then modify the Configure method:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}

app.UseCors("CorsPolicy");

app.UseAuthentication();

app.UseMvc();
Copy the code

We told our API application to use the JWT authentication service. To work with our users, we also need to configure the Cors policy. We define the JWT configuration in appsetting.json:

"Jwt": {
    "Key": "averysecretpassphrase", // A random and secure passhphrase
    "Issuer": "http://localhost:49443/", // This API base URI
    "Audience": "http://localhost:51149/" // The client base URI
  },
Copy the code

Create a simple potentially secure endpoint for testing purposes:

[Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet, Authorize] public IEnumerable<string> Get() { return new string[] { "Secret 1", "Secret 2" }; }}Copy the code

Tokencontroller.cs will handle JWT requests and related token issues:

[Route("api/[controller]")] public class TokenController : Controller { private IConfiguration _config; public TokenController(IConfiguration config) { _config = config; } [AllowAnonymous] [HttpPost] public async Task<IActionResult> CreateToken([FromBody]LoginVM login) { var user = await Authenticate(login); if (user ! = null) { var tokenString = BuildToken(user); return Ok(new { token = tokenString }); } return Unauthorized(); } private string BuildToken(UserVM user) { var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, user.Account), new Claim(JwtRegisteredClaimNames.GivenName, user.Name), new Claim(JwtRegisteredClaimNames.Email, user.Email), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Audience"], claims, expires: DateTime.Now.AddMinutes(30), signingCredentials: creds); return new JwtSecurityTokenHandler().WriteToken(token); } private async Task<UserVM> Authenticate(LoginVM login) { // TODO: this method will authenticate the user recovering the Ethereum address from signature using the Geth RPC web3.personal.ecrecover API UserVM user = user = new UserVM { Account = login.Account, Name = string.Empty, Email = string.Empty }; return user; } private async Task<UserVM> Authenticate2(LoginVM login) { // TODO: This method will authenticate the user recovering his Ethereum address through underlaying offline ecrecover method. UserVM user = user = new UserVM { Account = login.Account, Name = string.Empty, Email = string.Empty }; return user; }Copy the code

This is a typical JWT controller, the core methods, Authenticate and Authenticate2 are not yet implemented. Once implemented, they will do the same thing: recover the Ethereum address from the signature and check that it is equal to the ethereum address provided by the client.

LoginVM indicates the user credentials provided by the client, and UserVM indicates the “server-side” login user:

public class LoginVM
{
    public string Signer { get; set; } // Ethereum account that claim the signature
    public string Signature { get; set; } // The signature
    public string Message { get; set; } // The plain message
    public string Hash { get; set; } // The prefixed and sha3 hashed message 
}

public class UserVM
{
    public string Account { get; set; } // Unique account name (the Ethereum account)
    public string Name { get; set; } // The user name
    public string Email { get; set; } // The user Email
}
Copy the code

The Authenticate method takes the Signature and Message attributes as input to the ecRecover function, and the Authenticate2 method takes the Signature and Hash attributes. I’ll explain the difference later.

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Share some interactive online programming tutorials related to blockchain such as Ethereum, EOS and Bitcoin:

  • Java Ethereum development tutorial, mainly for Java and Android programmers for blockchain Ethereum development web3J details.
  • Python Ethereum is a detailed explanation of blockchain ethereum development by Python engineers using Web3.py.
  • PHP Ethereum, mainly introduces the use of PHP for smart contract development interaction, account creation, transactions, transfers, token development, filters and transactions and other content.
  • Ethereum introductory course, mainly introduces smart contract and DAPP application development, suitable for entry.
  • Ethereum development advanced tutorial, mainly introduces the use of Node.js, mongodb, blockchain, IPFS to achieve decentralized e-commerce DApp combat, suitable for advanced.
  • C# ethereum, mainly explains how to use C# based development. Net ethereum applications, including account management, status and transactions, smart contract development and interaction, filters and transactions, etc.
  • This course will help you get a quick start on the development of EOS blockchain decentralized applications. It covers core knowledge points such as EOS tool chain, account and wallet, issuing tokens, development and deployment of smart contracts, and interaction between codes and smart contracts. Finally, the development of a notepad DApp will be completed using all knowledge points comprehensively.
  • Java development tutorial COINS, this course for beginners, content covers the core concepts of COINS, such as block mechanism, key chain store, decentralized consensus and script, trading and UTXO etc, also explained how to integrate the currency support functions in Java code, such as creating address wallet, tectonic naked trading, management, Is a rare bitcoin development course for Java engineers.
  • PHP currency development tutorial, this course for beginners, content covers the core concepts of COINS, such as block mechanism, key chain store, decentralized consensus and script, trading and UTXO etc, also explained how to integrated the currency support functions in PHP code, such as creating address wallet, tectonic naked trading, management, This is a rare bitcoin development course for Php engineers.

Huizhi net original translation, reprint please indicate the source. Here is the original text