Koa.js - Authentication



Authentication is a process in which the credentials provided are compared to those on file in the database of authorized users' information on a local operating system or within an authentication server. If the credentials match, the process is completed and the user is granted authorization for access.

We'll be creating a very basic authentication system that'll use Basic HTTP Authentication. This is the simplest possible way to enforce access control as it doesn't require cookies, sessions, or anything else. To use this, the client has to send the Authorization header along with every request it makes. The username and password are not encrypted, but are concatenated in a single string like the following.

username:password

This string is encoded with Base64, and the word Basic is put before this value. For example, if your username is Ayush and password India, then the string "Ayush:India" would be sent as encoded in the authorization header.

Authorization: Basic QXl1c2g6SW5kaWE=

To implement this in your koa app, you'll need the koa-basic-auth middleware. Install it using −

$ npm install --save koa-basic-auth

Now open your app.js file and enter the following code in it.

//This is what the authentication would be checked against
var credentials = { name: 'Ayush', pass: 'India' }

var koa = require('koa');
var auth = require('koa-basic-auth');
var _ = require('koa-router')();

var app = koa();

//Error handling middleware
app.use(function *(next){
   try {
      yield next;
   } catch (err) {
      if (401 == err.status) {
         this.status = 401;
         this.set('WWW-Authenticate', 'Basic');
         this.body = 'You have no access here';
      } else {
         throw err;
      }
   }
});

// Set up authentication here as first middleware. 
// This returns an error if user is not authenticated.
_.get('/protected', auth(credentials), function *(){
   this.body = 'You have access to the protected area.';
   yield next;
});

// No authentication middleware present here.
_.get('/unprotected', function*(next){
   this.body = "Anyone can access this area";
   yield next;
});

app.use(_.routes());
app.listen(3000);

We have created an error handling middleware to handle all authentication related errors. Then, we have created 2 routes −

  • /protected − This route can only be accessed if the user sends the correct authentication header. For all others, it'll give an error.

  • /unprotected − This route can be accessed by anyone, with or without the authentication.

Now if you send a request to /protected without an authentication header or with the wrong credentials, you'll receive an error. For example,

$ curl https://localhost:3000/protected

You'll receive the response as −

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic
Content-Type: text/plain; charset=utf-8
Content-Length: 28
Date: Sat, 17 Sep 2016 19:05:56 GMT
Connection: keep-alive

Please authenticate yourself

However, with the right credentials, you'll get the expected response. For example,

$ curl -H "Authorization: basic QXl1c2g6SW5kaWE=" https://localhost:3000/protected -i

You'll get the response as −

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 38
Date: Sat, 17 Sep 2016 19:07:33 GMT
Connection: keep-alive

You have access to the protected area.

The /unprotected route is still accessible to everyone.

Advertisements