node.js oauth login wizard with leveldb session storage
$ npm install gandalf
var http = require('http')
var Router = require('routes-router')
var mount = require('routes-router-mount')
var level = require('level-test')()
var Gandalf = require('gandalf')
var ecstatic = require('ecstatic')
var db = level('gandalf-examples--simple', {encoding: 'json'})
var gandalf = Gandalf(db, {
providers:{
facebook:{
id:process.env.FACEBOOK_ID,
secret:process.env.FACEBOOK_SECRET
},
twitter:{
id:process.env.TWITTER_ID,
secret:process.env.TWITTER_SECRET
}
}
})
var router = mount(Router())
// mount the OAuth login handlers
router.mount('/auth', gandalf.handler())
// get the current session data
router.addRoute('/status', {
// add session handler to this method
'GET':gandalf.session(function(req, res){
req.session.get('userid', function(err, id){
// load the user from the userid in the session
gandalf.loadUser(id, function(err, user){
res.end(JSON.stringify(user))
})
})
})
})
// only logged in people can see this route
router.addRoute('/private', gandalf.protect())
// these are served without hitting the session
router.addRoute('/*', ecstatic(__dirname + '/www'))
var server = http.createServer(router)
server.listen(80, function(){
console.log('server listening');
})
create a new authentication handler by passing in an existing leveldb - this can also be a sub-level
Pass a providers
config to activate external OAUTH providers:
var gandalf = Gandalf(db, {
providers:{
facebook:{
id:process.env.FACEBOOK_ID,
secret:process.env.FACEBOOK_SECRET
},
twitter:{
id:process.env.TWITTER_ID,
secret:process.env.TWITTER_SECRET
}
}
})
The supported types are:
- github
- dropbox
Password mode (/register and /login) are activated automatically.
One user can connect
multiple external providers and link them to the same user id.
Return a function that will create a session
property of the request:
var session = gandalf.session()
router.addRoute('/api', function(req, res){
session(req, res, function(){
// we now have a session for the request
req.session.get('userid', function(err, userid){
})
})
})
You can also pass a function to gandalf.session and it will be wrapped:
router.addRoute('/api', gandalf.session(function(req, res){
//req.session is populated
}))
Mount the authentication handler onto an endpoint of your application (for example on /auth
).
You can then link to /auth/github
to perform a github login or POST to /auth/register
to register new accounts.
router.addRoute('/api', gandalf.handler())
The following are the routes that are mounted:
e.g. /google
- this triggers the OAuth login loop for a provider
post username and password and other fields to register a new user
{
"username":"bob",
"password":"123",
"email":"bob@bob.com",
"likes":"porridge"
}
post username and password fields to login using the password method
{
"username":"bob",
"password":"123"
}
post a username to use for a connected user - use this when a user connects using an external service but you still need a username
(as opposed to just an id)
{
"username":"bob"
}
clear the session and redirect to '/'
check if the given username exists
return a JSON representation of the current session - this includes OAuth tokens
Return a 403 error if the user is not logged in:
router.addRoute('/private', gandalf.protect(function(req, res){
// the user is logged in
// we also have req.session and req.userid
}))
If you do not pass a function then there just needs to be a user for access to be granted.
Delete a user and all their details
Remove the connection details for 'provider' in the given user
When a value has been put to the database
When a batch has been sent to the database
A HTTP request has hit the handler
A HTTP request has hit a provider handler
A resource has been denied in a protect handler
A login request
A register request
A connect request
A user profile has been created by provider
A claim request
A logout request
MIT