├── .gitignore ├── README.md ├── examples └── express │ ├── app.js │ ├── lib │ ├── oauth.js │ └── providers │ │ └── facebook.js │ ├── public │ └── stylesheets │ │ ├── style.css │ │ └── style.styl │ ├── rename_to_secrets.json │ ├── test │ └── app.test.js │ └── views │ ├── index.jade │ ├── layout.jade │ └── signin.jade ├── lib ├── oauth2.js └── utils.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | secrets.json 14 | node_modules 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # I've stopped development for a moment. Since I want to rewrite this lib using SuperAgent node module, that is currently under development. 2 | 3 | # OAuth2 wrapper for nodejs 4 | 5 | A simple oauth2 API for node.js . This API allows users to authenticate against OAuth2 providers, and thus act as OAuth2 consumers 6 | 7 | Tested against 8 | 9 | * [Facebook](http://developers.facebook.com/docs/authentication/), 10 | * [Google](http://code.google.com/apis/accounts/docs/OAuth2.html), 11 | * [Vkontakte](http://vkontakte.ru/topic-1_24428376). 12 | 13 | ## Installation 14 | 15 | $ npm install oauth2 16 | 17 | ## Contributors 18 | 19 | * Alexey Zakharov ([lexer](http://github.com/lexer)) 20 | * Utyasheva Oksana ([uoksana](http://github.com/uoksana)) -------------------------------------------------------------------------------- /examples/express/app.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var express = require('express') 7 | , fs = require('fs') 8 | , oauthSecrets = JSON.parse(fs.readFileSync('./secrets.json', 'utf-8')) 9 | , Oauth2 = require('../../lib/oauth2'); 10 | 11 | var app = module.exports = express.createServer(); 12 | 13 | // Configuration 14 | 15 | app.configure(function(){ 16 | app.set('views', __dirname + '/views'); 17 | app.set('view engine', 'jade'); 18 | app.use(express.bodyParser()); 19 | app.use(express.methodOverride()); 20 | app.use(express.cookieParser()); 21 | app.use(express.session({ secret: 'your secret here' })); 22 | app.use(require('stylus').middleware({ src: __dirname + '/public' })); 23 | app.use(app.router); 24 | app.use(express.static(__dirname + '/public')); 25 | }); 26 | 27 | app.configure('development', function(){ 28 | app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 29 | }); 30 | 31 | app.configure('production', function(){ 32 | app.use(express.errorHandler()); 33 | }); 34 | 35 | // Routes 36 | 37 | app.get('/', function(req, res){ 38 | res.render('index', { 39 | title: 'Node oauth 2' 40 | }); 41 | }); 42 | 43 | app.get('/auth/facebook', function(req, res){ 44 | 45 | var client_id = oauthSecrets.facebook.clientId; 46 | var provider = 'facebook'; 47 | var redirect_uri = 'http://localhost:3000/auth/facebook/callback'; 48 | 49 | res.redirect('https://www.facebook.com/dialog/oauth?client_id=' + client_id + '&redirect_uri='+ redirect_uri); 50 | }); 51 | 52 | app.get('/auth/google', function(req, res){ 53 | 54 | var client_id = '582833444971.apps.googleusercontent.com'; 55 | var provider = 'google'; 56 | var redirect_uri = 'http://127.0.0.1:3000/auth/google/callback'; 57 | 58 | res.redirect( 59 | 'https://accounts.google.com/o/oauth2/auth?client_id=' + client_id + '&redirect_uri=' + redirect_uri + 60 | '&scope=https://www.google.com/m8/feeds/&response_type=code'); 61 | }); 62 | 63 | app.get('/auth/vkontakte', function(req,res){ 64 | var client_id = oauthSecrets.vkontakte.clientId; 65 | var provider = 'vkontakte'; 66 | var redirect_uri = 'http://127.0.0.1:3000/auth/vkontakte/callback'; 67 | 68 | res.redirect( 69 | 'http://api.vkontakte.ru/oauth/authorize?client_id=' + client_id + '&redirect_uri=' + redirect_uri + 70 | '&scope=notify,friends/&response_type=code'); 71 | }); 72 | 73 | app.get('/auth/:provider/callback', function(req, res){ 74 | if (req.params.provider === "facebook") { 75 | var oauth2 = new OAuth2({ 76 | host: "graph.facebook.com", 77 | accessTokenPath: "/oauth/access_token", 78 | clientId: oauthSecrets.facebook.clientId, 79 | clientSecret: oauthSecrets.facebook.clientSecret 80 | }); 81 | 82 | oauth2.getAccessToken(req.query.code,'http://localhost:3000/auth/facebook/callback', function(error, result) { 83 | console.log(result); 84 | res.send("Success"); 85 | }); 86 | } 87 | 88 | if (req.params.provider === "google") { 89 | var oauth2 = new OAuth2({ 90 | host: "accounts.google.com", 91 | accessTokenPath: "/o/oauth2/token", 92 | clientId: oauthSecrets.google.clientId, 93 | clientSecret: oauthSecrets.google.clientSecret 94 | }); 95 | oauth2.getAccessToken(req.query.code, 'http://127.0.0.1:3000/auth/google/callback', function(error, result) { 96 | res.send(JSON.stringify({ 97 | error: error, 98 | result: result 99 | })); 100 | }); 101 | } 102 | 103 | if (req.params.provider === "vkontakte") { 104 | var oauth2 = new OAuth2({ 105 | host: "api.vkontakte.ru", 106 | accessTokenPath: "/oauth/access_token", 107 | clientId: oauthSecrets.vkontakte.clientId, 108 | clientSecret: oauthSecrets.vkontakte.clientSecret 109 | }); 110 | 111 | oauth2.getAccessToken(req.query.code,'http://127.0.0.1:3000/auth/vkontakte/callback', function(error, result) { 112 | res.send(JSON.stringify({ 113 | error: error, 114 | result: result 115 | })); 116 | }); 117 | } 118 | }); 119 | 120 | 121 | // Only listen on $ node app.js 122 | 123 | if (!module.parent) { 124 | app.listen(3000); 125 | console.log("Express server listening on port %d", app.address().port); 126 | } 127 | -------------------------------------------------------------------------------- /examples/express/lib/oauth.js: -------------------------------------------------------------------------------- 1 | module.exports.OAuth2 = function(providers) { 2 | 3 | } 4 | 5 | module.exports.OAuth2.prototype.routes = function(app) { 6 | providers.forEach(function(p){ 7 | app.get('/auth/' + provider.name, function(req, res){ 8 | var client_id = provider.clientId; 9 | var redirect_uri = 'http://' + req.headers.host + '/auth/' + provider.name + '/callback'; 10 | 11 | res.redirect('https://www.facebook.com/dialog/oauth?client_id=' + client_id + '&redirect_uri='+ redirect_uri); 12 | }); 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /examples/express/lib/providers/facebook.js: -------------------------------------------------------------------------------- 1 | var Facebook = module.exports.Facebook = function(clientId, clientSecret) { 2 | this.clientId = clientId; 3 | this.clientSecret = clientSecret; 4 | }; 5 | 6 | Facebook.prototype.authorizeUrl = function(redirectUrl) { 7 | 'https://www.facebook.com/dialog/oauth?client_id=' + this.clientId + '&redirect_uri='+ redirectUrl 8 | } 9 | 10 | Facebook. 11 | -------------------------------------------------------------------------------- /examples/express/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | a { 6 | color: #00b7ff; 7 | } 8 | -------------------------------------------------------------------------------- /examples/express/public/stylesheets/style.styl: -------------------------------------------------------------------------------- 1 | body 2 | padding 50px 3 | font 14px "Lucida Grande", Helvetica, Arial, sans-serif 4 | a 5 | color #00B7FF -------------------------------------------------------------------------------- /examples/express/rename_to_secrets.json: -------------------------------------------------------------------------------- 1 | { 2 | "google": { 3 | "clientId": "", 4 | "clientSecret": "" 5 | }, 6 | "facebook": { 7 | "clientId": "", 8 | "clientSecret": "" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/express/test/app.test.js: -------------------------------------------------------------------------------- 1 | 2 | // Run $ expresso 3 | 4 | /** 5 | * Module dependencies. 6 | */ 7 | 8 | var app = require('../app') 9 | , assert = require('assert'); 10 | 11 | 12 | module.exports = { 13 | 'GET /': function(){ 14 | assert.response(app, 15 | { url: '/' }, 16 | { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8' }}, 17 | function(res){ 18 | assert.includes(res.body, 'Express'); 19 | }); 20 | } 21 | }; -------------------------------------------------------------------------------- /examples/express/views/index.jade: -------------------------------------------------------------------------------- 1 | .facebook 2 | a#facebook_sigin(href="/auth/facebook", title="Facebook signin") Facebook 3 | .google 4 | a#google_sigin(href="/auth/google", title="Google signin") Google 5 | .google 6 | a#vkontakte_sigin(href="/auth/vkontakte", title="Vkontakte signin") Vkontakte 7 | 8 | -------------------------------------------------------------------------------- /examples/express/views/layout.jade: -------------------------------------------------------------------------------- 1 | !!! 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body!= body -------------------------------------------------------------------------------- /examples/express/views/signin.jade: -------------------------------------------------------------------------------- 1 | a#facebook_sigin(href="/auth/facebook", title="Facebook signin") Facebook 2 | a#google_sigin(href="/auth/google", title="Google signin") Google 3 | 4 | -------------------------------------------------------------------------------- /lib/oauth2.js: -------------------------------------------------------------------------------- 1 | var https = require('https') 2 | , qs = require('querystring'); 3 | 4 | 5 | exports.OAuth2 = OAuth2 = function(options) { 6 | this.host = options.host; 7 | this.authorizePath = options.authorizePath; 8 | this.accessTokenPath = options.accessTokenPath; 9 | this.clientId = options.clientId; 10 | this.clientSecret = options.clientSecret; 11 | 12 | this.version = '0.0.1'; 13 | } 14 | 15 | OAuth2.prototype.request = function request(opt, fn) { 16 | var self = this 17 | , method = opt.method || "GET" 18 | , path = opt.path 19 | , headers = opt.headers || {} 20 | , params = opt.params || {} 21 | , body; 22 | 23 | if (Object.keys(params).length > 0) { 24 | var paramStr = qs.stringify(params) 25 | 26 | if (method !== "GET") { 27 | body = new Buffer(paramStr); 28 | headers['content-type'] = 'application/x-www-form-urlencoded'; 29 | headers['content-length'] = body.length; 30 | } else { 31 | path = path + "?" + paramStr; 32 | } 33 | } 34 | 35 | headers['accept'] = 'application/json'; 36 | 37 | var options = { 38 | host: self.host, 39 | port: 443, 40 | path: path, 41 | method: method, 42 | headers: headers 43 | }; 44 | 45 | var req = https.request(options, function(res) { 46 | res.setEncoding('utf8'); 47 | 48 | var result = ''; 49 | 50 | res.on('data', function(data) { 51 | result += data; 52 | }); 53 | res.on('end', function() { 54 | try { 55 | result = JSON.parse(result); 56 | } catch(err) { 57 | fn(err); 58 | } 59 | 60 | fn(null, result); 61 | }); 62 | }); 63 | 64 | req.write(body); 65 | 66 | req.on('error', function(err) { 67 | fn(err); 68 | }); 69 | 70 | req.end(); 71 | } 72 | 73 | OAuth2.prototype.get = function(options, fn) { 74 | options.method = "GET"; 75 | return this.request(options, fn); 76 | } 77 | 78 | OAuth2.prototype.post = function(options, fn) { 79 | options.method = "POST"; 80 | return this.request(options, fn); 81 | } 82 | 83 | OAuth2.prototype.put = function(options, fn) { 84 | options.method = "PUT"; 85 | return this.request(options, fn); 86 | } 87 | 88 | OAuth2.prototype.del = function(options, fn) { 89 | options.method = "DELETE"; 90 | return this.request(options, fn); 91 | } 92 | 93 | OAuth2.prototype.tokenRequest = function(options, fn) { 94 | 95 | options.params['client_id'] = this.clientId; 96 | options.params['client_secret'] = this.clientSecret; 97 | options.path = this.accessTokenPath; 98 | 99 | return this.post(options, fn); 100 | } 101 | 102 | 103 | OAuth2.prototype.getAccessToken = function(code, redirectUri, fn) { 104 | this.tokenRequest({ 105 | params: { 106 | 'code': code, 107 | 'redirect_uri': redirectUri, 108 | 'grant_type': 'authorization_code' 109 | } 110 | }, fn); 111 | } 112 | 113 | 114 | OAuth2.prototype.refreshToken = function(refreshToken, fn) { 115 | this.tokenRequest({ 116 | params: { 117 | 'refresh_token': refreshToken, 118 | 'grant_type': 'refresh_token' 119 | } 120 | }, fn); 121 | } 122 | 123 | /*OAuth2.prototype.request = function(options, fn) { 124 | headers['Authorization'] = 'OAuth ' + auth['access_token']; 125 | headers['Host'] = this.base; 126 | 127 | return this.client.request(method, url, headers); 128 | }*/ 129 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | exports.union = function(a, b){ 2 | a = a || {}; 3 | if (a && b) { 4 | var keys = Object.keys(b) 5 | , len = keys.length 6 | , key; 7 | for (var i = 0; i < len; ++i) { 8 | key = keys[i]; 9 | if (!a.hasOwnProperty(key)) { 10 | a[key] = b[key]; 11 | } 12 | } 13 | } 14 | return a; 15 | }; 16 | 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oauth2", 3 | "description": "Oauth2 multi provider npm module", 4 | "version": "0.0.1", 5 | "author": "Alexey Zakharov ", 6 | "contributors": [ 7 | { "name": "Alexey Zakharov", "email": "alexey.v.zaharov@gmail.com" }, 8 | { "name": "Oksana Utyasheva", "email": "utyasheva.oksana@gmail.com" } 9 | ], 10 | "dependencies": { 11 | 12 | }, 13 | "keywords": ["ouath2", "facebook", "google", "vkontakte", "twitter"], 14 | "repository": "git://github.com/lexer/node-oauth2", 15 | "main": "./lib/oauth2", 16 | "engines": { "node": ">= 0.4.6 < 0.5.0" } 17 | } 18 | --------------------------------------------------------------------------------