← Back to overview
January 21, 2016 · auth0 gitbook node.js

Better internal documentation with GitBook, Express and Auth0

GitBook is a great tool for writing books but also for writing documentation. It's being used by great projects like Redux.

The way it works is simple, you just write your content in markdown and then use a file to define the structure of your book (SUMMARY.md). Done. The end result looks like this:

While this is great for public facing things, you could also leverage this for internal documentation. The only thing you need is to add authentication on top of your book. This tutorial will show you how to do this with a very simple Express application and Auth0.

Source: https://github.com/sandrinodimattia/gitbook-express-auth0-boilerplate

Configuration

Just go ahead and sign up for an account on Auth0. This is where you can define an application for you internal documentation application and link it to different connections (sources of users).

The most important setting here is the Allowed Callback URLs as it will need to point to where you are hosting the application. For local development you'll need to use http://localhost:4001/login/callback.

Take note of the Domain, Client ID and Client Secret as you'll need it in the next steps.

A secure application to host the book

Now that we have authentication covered, we'll need a small application that will host the book and expose it to authenticated users. This sample application will run an Express server which hosts the book and protects it with passport-auth0:

// Initialize configuration.
nconf.argv()  
  .env()
  .file({ file: './config.json' });

// Initialize authentication.
passport.serializeUser((user, done) => done(null, user));  
passport.deserializeUser((user, done) => done(null, user));  
passport.use(new Auth0Strategy({  
  domain: nconf.get('AUTH0_DOMAIN'),
  clientID: nconf.get('AUTH0_CLIENT_ID'),
  clientSecret: nconf.get('AUTH0_CLIENT_SECRET'),
  callbackURL: '/login/callback'
}, function(accessToken, refreshToken, extraParams, profile, done) {
    return done(null, profile);
}));

// Initialize the app.
const app = new Express();  
app.use(cookieParser());  
app.use(session({  
  secret: nconf.get('SESSION_SECRET'),
  saveUninitialized: true,
  resave: false,
  cookie: { maxAge: 3600000 }
}));
app.use(passport.initialize());  
app.use(passport.session());  
app.use(compression());

// Authentication endpoints.
app.get('/login',  
  passport.authenticate('auth0', { connection: nconf.get('AUTH0_CONNECTION') }),
  function(req, res) { });
app.get('/login/callback',  
  passport.authenticate('auth0'),
  function(req, res) { res.redirect('/'); });
app.get('/logout',  
  function(req, res) {
    req.session.destroy();
    req.logout();
    res.redirect('/');
  });

// Force authentication for the next routes.
app.use(function(req, res, next) {  
  if (!req.isAuthenticated()) {
    return res.redirect('/login');
  }
  next();
});

// Host the book.
app.use(Express.static(path.join(__dirname, './content/_book')));

// Start the server.
const port = process.env.PORT || 4001;  
app.listen(port, function(error) {  
  if (error) {
    console.log(error);
  } else {
    console.log('Listening on http://localhost:' + port);
  }
});

Building and Hosting

The package.json comes with a few commands to build the book (convert the markdown to html) and host the application:

  "scripts": {
    "build": "gitbook build ./content/",
    "serve:book": "gitbook serve ./content/",
    "serve:dev": "cross-env NODE_ENV=development node server",
    "serve:prod": "cross-env NODE_ENV=production node server",
    "postinstall": "npm run build"
  }

Also make sure you update the config.json file with the settings from your Auth0 account.

Writing Documentation

You can now write your docs in the /content folder using markdown, for example:

# Tables!

| Tables        | Are           | Cool  |
| ------------- |:-------------:| -----:|
| col 3 is      | right-aligned | $1600 |
| col 2 is      | centered      |   $12 |
| zebra stripes | are neat      |    $1 |

And using the SUMMARY.md file you can define the structure of your docs:

# Summary

* [Foo](foo/index.md)
    * [Bar](foo/bar.md)
* Examples
    * [Code](examples/code-example.md)
    * [Images](examples/image-example.md)
    * [Tables](examples/table-example.md)

You can also change the settings of your book by modifying the /content/book.json file:

{
  "title": "XYZ Documentation",
  "links": {
    "sidebar": {
      "XYZ Documentation": "http://sandrinodimattia.net",
      "Logout": "/logout"
    }
  },
  "pluginsConfig": {
    "sharing": {
        "google": false,
        "facebook": false,
        "twitter": false
    }
  }
}

End Result

A demo is available here: http://gitbook-boilerplate-demo.herokuapp.com/

Users that try to access this site will see the login page:

And once they're authenticated they'll have access to the documentation:

Next Steps

You can now connect Auth0 to enterprise directories like Google Apps for Business, Azure AD, ... or if you want you can use Social Connections and restrict user access based on an email domain using Rules:

function (user, context, callback) {  
    var whitelist = ['example.com', 'example.org']; //authorized domains
    var userHasAccess = whitelist.some(
      function (domain) {
        var emailSplit = user.email.split('@');
        return emailSplit[emailSplit.length - 1].toLowerCase() === domain;
      });

    if (!userHasAccess) {
      return callback(new UnauthorizedError('Access denied.'));
    }

    return callback(null, user, context);
}

Happy documenting!

  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket
Comments powered by Disqus