Thursday, March 2, 2017

Koa.js - Authentication

Authentication is a process in which the credentials provided are compared to those on file in a 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
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 a 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 a authentication header or with wrong credentials, you'll get an error. For example,
$ curl https://localhost:3000/protected
You'll get 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
But 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 still is accessible to everyone.

No comments:

Post a Comment