Remember to set your GitHub CLIENTID and Secret in auth.js.


1. Install modules

Back to TOC
We need to use additional node modules for this tutorial:

  1. Session (koa-sess, this is not the same as koa-session)
  2. RedisStore (koa-redis)
npm install --save koa-sess koa-redis

2. Using Session

Back to TOC

There are 2 session modules for Koa:
1. koa-sess, which is memory/storage based.
2. koa-session, which is cookie based.

For this tutorial purpose we will use koa-sess.

//This is app.js
const
  ....
  session = require('koa-sess'),
  ....
app.keys=['koa-tutorial'];
app.use(session());

We will set the app.keys and then use the session middleware.

You can set any key you like.


3. Initialize passport with session

Back to TOC

Add app.use(passport.session()); after the line app.use(passport.initialize());

//This is app.js
...
app.use(passport.initialize());
app.use(passport.session());

4. Redirect for post-authenticated process

Back to TOC

publicRouter.get('/auth/github/callback',
  passport.authenticate('github', {successReturnToOrRedirect: '/', failureRedirect: '/'})
);

successReturnToOrRedirect allow us to use url in this.session.returnTo so it is more dynamic and enable to redirect back where we came from instead of just '/'.

//Middleware: authed
function *authed(next){
  if (this.req.isAuthenticated()){
    yield next;
  } else {
    //Set redirect path in session
    this.session.returnTo = this.session.returnTo || this.req.url;
    this.redirect('/auth/github');
  }
}

The code this.session.returnTo || this.req.url; means when returnTo is available, use it back, else set returnTo to request url. This is useful when you have a login form page in between your desired return path and the authentication process.

Might need to keep resetting this.req.url for every public path user going to visit before login.

securedRouter.get('/app2', authed, function *(){
  this.body = 'Secured Zone: koa-tutorial APP2\n'
});

Path to /app2 just to prove we have entered secured zone after authentication passed.


5. Test application I

Back to TOC

2014-03-07T08:53:09.048Z - GET /app
2014-03-07T08:53:09.077Z - GET /auth/github
2014-03-07T08:53:10.229Z - GET /auth/github/callback?code=a1da082fc1ae504f7b2c
2014-03-07T08:53:12.604Z - GET /app
Line 1 GET /app
You have request to open localhost:3000/app which is GET /app.
Line 2 GET /auth/github
You were not authenticated, therefore redirects to /auth/github. this.session.returnTo is set to /app
Line 3 GET /auth/github/callback?code=a1da082fc1ae504f7b2c
You will be showing a GitHub login page if you haven’t login there yet.
After login to GitHub, a callback to /auth/github/callback.
Line 4 GET /app
The OAuth login is successful, therefore redirects to this.session.returnTo which is /app.

Now try go to /app2, notice there’s no more redirect to /auth/github because you are already authenticated.


6. Add session expiry

Back to TOC

Let’s add an expiry of 30 seconds after login.

app.use(session({
  cookie: {maxAge: 1000 * 30},
}));

maxAge is integer number in millisecond.

Now wait for 30 seconds and refresh again. You will notice that the session expired and you are redirected to authentication again.

app.use(session({
  cookie: {maxAge: 1000 * 60 * 5}
}));

7. RedisStore Persistent Session

Back to TOC
Suppose you have a clustered setting or you just want to provide a robust experience, you need to share or hold the session even if the server has shutdown, you need to store the session in a persistent storage.

In this section we will use Redis as the session storage.
Its pretty easy to setup.

//This is app.js
const
  ...
  redisStorage = require('koa-redis'),
  ...
app.use(session({
  cookie: {maxAge: 1000 * 60 * 5},
  store : redisStore()
}));

That’s it. We are now able to run session using Redis.


8. Test application II (Persistent Session)

Back to TOC


9. Complete app.js

Back to TOC

"use strict"

const
  Router = require('koa-router'),
  passport = require('./auth'),
  session = require('koa-sess'),
  redisStore = require('koa-redis'),

  koa = require('koa'),
  app = koa();


//Middleware: request logger
function *reqlogger(next){
  console.log('%s - %s %s',new Date().toISOString(), this.req.method, this.req.url);
  yield next;
}
app.use(reqlogger);

//Initialize session
app.keys=['koa-tutorial'];
app.use(session({
  cookie: {maxAge: 1000 * 60 * 5},
  store : redisStore()
}));

//Initialize passport with session
app.use(passport.initialize());
app.use(passport.session());

app.use(Router(app));

app.get('/', function *(){
  console.log('Express-style example');
  this.body = "This is root page ('/')";
});



const publicRouter = new Router();

//Configure /auth/github & /auth/github/callback
publicRouter.get('/auth/github', passport.authenticate('github', {scope: ['user','repo']}));
publicRouter.get('/auth/github/callback',
  passport.authenticate('github', {successReturnToOrRedirect: '/', failureRedirect: '/'})
);


app.use(publicRouter.middleware());



//Secures routes
const securedRouter = new Router();

//Middleware: authed
function *authed(next){
  if (this.req.isAuthenticated()){
    yield next;
  } else {
    //Set redirect path in session
    this.session.returnTo = this.session.returnTo || this.req.url;
    this.redirect('/auth/github');
  }
}

securedRouter.get('/app', authed, function *(){
  this.body = 'Secured Zone: koa-tutorial\n' + JSON.stringify(this.req.user, null, '\t');
});

securedRouter.get('/app2', authed, function *(){
  this.body = 'Secured Zone: koa-tutorial APP2\n'
});

app.use(securedRouter.middleware());

app.use(function *(){
  this.body = 'Hello World';
});

app.listen(3000);

Download

Back to TOC
You can download this tutorial project here:
https://github.com/Zev23/koa-tutorial-authenticate-with-persistent-session-using-redis






Copyright © Zev23.com 2014 All Rights Reserved. No part of this website may be reproduced without Zev23.com’s express consent.

Post a Comment
Newer Post Older Post Home