Skip to content

Instantly share code, notes, and snippets.

@robwormald
Created January 24, 2014 23:55
Show Gist options
  • Save robwormald/8609335 to your computer and use it in GitHub Desktop.
Save robwormald/8609335 to your computer and use it in GitHub Desktop.
var passport = require('passport'),
oauth2orize = require('oauth2orize'),
jwtBearer = require('oauth2orize-jwt-bearer').Exchange,
login = require('connect-ensure-login'),
utils = require('../innitUtils.js');
module.exports = {
express: {
customMiddleware: function(app)
{
/** oAuth Server **/
app.use(passport.initialize());
app.use(passport.session());
var server = oauth2orize.createServer();
// Register supported grant types.
//
// OAuth 2.0 specifies a framework that allows users to grant client
// applications limited access to their protected resources. It does this
// through a process of the user granting access, and the client exchanging
// the grant for an access token.
// Grant authorization codes. The callback takes the `client` requesting
// authorization, the `redirectURI` (which is used as a verifier in the
// subsequent exchange), the authenticated `user` granting access, and
// their response, which contains approved scope, duration, etc. as parsed by
// the application. The application issues a code, which is bound to these
// values, and will be exchanged for an access token.
server.grant(oauth2orize.grant.code(function(client, redirectURI, user, ares, done) {
var code = utils.uid(16);
Authcode.create({
code: code,
client: client.id,
redirectURI: redirectURI,
user: user.id,
scope: ares.scope
}).done(function(err,code){
if(err){return done(err,null);}
return done(null,code.code);
});
}));
// Grant implicit authorization. The callback takes the `client` requesting
// authorization, the authenticated `user` granting access, and
// their response, which contains approved scope, duration, etc. as parsed by
// the application. The application issues a token, which is bound to these
// values.
server.grant(oauth2orize.grant.token(function(client, user, ares, done) {
var token = utils.uid(256);
Token.create({
accessToken: token,
user: user.id,
client: client.id,
//scope: code.scope
}).done(function(err,token){
if (err) {
console.log(err)
return done(err);
}
console.log(token.accessToken)
return done(null, token.accessToken);
});
}));
// Exchange authorization codes for access tokens. The callback accepts the
// `client`, which is exchanging `code` and any `redirectURI` from the
// authorization request for verification. If these values are validated, the
// application issues an access token on behalf of the user who authorized the
// code.
server.exchange(oauth2orize.exchange.code(function(client, code, redirectURI, done) {
Authcode.findOne({
code: code
}).done(function(err,code){
if (err || !code) {
return done(err);
}
if (client.id !== code.clientId) {
return done(null, false);
}
if (redirectURI !== code.redirectURI) {
return done(null, false);
}
var token = utils.uid(256);
Token.create({
token: token,
user: code.user,
client: code.client,
scope: code.scope
}).done(function(err,token){
if (err) {
return done(err);
}
return done(null, token);
});
});
}));
// Exchange user id and password for access tokens. The callback accepts the
// `client`, which is exchanging the user's name and password from the
// authorization request for verification. If these values are validated, the
// application issues an access token on behalf of the user who authorized the code.
server.exchange(oauth2orize.exchange.password(function(client, username, password, scope, done) {
console.log('password xchange')
//Validate the client
Client.findOne({id : client.id}).done(function(err, localClient) {
console.log('password xchange')
if (err) { return done(err); }
if(localClient === null) {
return done(null, false);
}
if(localClient.clientSecret !== client.clientSecret) {
return done(null, false);
}
//Validate the user
User.findByUsername(username, function(err, user) {
if (err) { return done(err); }
if(user === null) {
return done(null, false);
}
if(user.validPassword(password)) {
return done(null, false);
}
//Everything validated, return the token
var token = utils.uid(256);
Token.create({
token : token,
user : user.id,
client : client.id
}).then(function(err) {
if (err) { return done(err); }
done(null, token);
});
});
});
}));
//TODO : google JWT token stuff
// server.exchange('urn:ietf:params:oauth:grant-type:jwt-bearer', jwtBearer(function(client, data, signature, done) {
// var crypto = require('crypto')
// , pub = // TODO - Load your pubKey registered to the client from the file system or database
// , verifier = crypto.createVerify("RSA-SHA256");
// verifier.update(JSON.stringify(data));
// if (verifier.verify(pub, signature, 'base64')) {
// // TODO - base64url decode data then verify client_id, scope and expiration are valid
// AccessToken.create(client, scope, function(err, accessToken) {
// if (err) { return done(err); }
// done(null, accessToken);
// });
// }
// }));
//When a client requests authorization, it will redirect the user to an authorization endpoint. The server must authenticate the user and obtain their permission.
app.get('/oauth/authorize', login.ensureLoggedIn(), server.authorize(function (clientID, redirectURI, done) {
console.log(clientID)
Client.findOne({
clientKey: clientID
}, function (err, cli) {
console.log(cli)
if (err) {
return done(err);
}
if (!cli) {
return done(null, false);
}
if (cli.redirectURI != redirectURI) {
return done(null, false);
}
return done(null, cli, cli.redirectURI);
});
}), function (req, res) {
res.render('dialog', {
transactionID: req.oauth2.transactionID,
user: req.user,
cli: req.oauth2.client
});
});
app.post('/oauth/authorize/decision',
login.ensureLoggedIn(),
server.decision());
server.serializeClient(function(client, done) {
return done(null, client.id);
});
server.deserializeClient(function(id, done) {
Client.findOne(id, function(err, client) {
if (err) { return done(err); }
return done(null, client);
});
});
//exchange the grant for a token
//Once a user has approved access, the authorization grant can be exchanged by the client for an access token
app.get('/token',
passport.authenticate('oauth2-client-password', { session: false }),
server.token(),
server.errorHandler());
//get information about a specified token
app.get('/tokenInfo',function (req, res) {
console.log(req.query)
if (req.query.access_token) {
Token.find({token : req.query.access_token}).then(function (token) {
console.log(token)
if (!token) {
res.status(400);
res.json({ error: "invalid_token" });
} else if(new Date() > token.expirationDate) {
res.status(400);
res.json({ error: "invalid_token" });
}
else {
Client.find(token.client, function (err, client) {
if (err || !client) {
res.status(400);
res.json({ error: "invalid_token"});
} else {
if(token.expirationDate) {
var expirationLeft = Math.floor((token.expirationDate.getTime() - new Date().getTime()) / 1000);
if(expirationLeft <= 0) {
res.json({ error: "invalid_token"});
} else {
res.json({ audience: client.id, expires_in: expirationLeft});
}
} else {
console.log('woohoo?')
res.json({validToken: true })
}
}
});
}
});
} else {
res.status(400);
res.json({ error: "invalid_token"});
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment