Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update i use #36

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 121 additions & 119 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,6 @@ var EventEmitter = require('events').EventEmitter,
querystring = require('querystring'),
serializer = require('serializer');

_extend = function(dst,src) {

var srcs = [];
if ( typeof(src) == 'object' ) {
srcs.push(src);
} else if ( typeof(src) == 'array' ) {
for (var i = src.length - 1; i >= 0; i--) {
srcs.push(this._extend({},src[i]))
};
} else {
throw new Error("Invalid argument")
}

for (var i = srcs.length - 1; i >= 0; i--) {
for (var key in srcs[i]) {
dst[key] = srcs[i][key];
}
};

return dst;
}
function parse_authorization(authorization) {
if(!authorization)
return null;
Expand Down Expand Up @@ -70,44 +49,44 @@ function OAuth2Provider(options) {

OAuth2Provider.prototype = new EventEmitter();

OAuth2Provider.prototype.generateAccessToken = function(user_id, client_id, extra_data, token_options) {
token_options = token_options || {}
var out = _extend(token_options, {
access_token: this.serializer.stringify([user_id, client_id, +new Date, extra_data]),
OAuth2Provider.prototype.generateAccessToken = function(user_id, client_id, scope) {
var out = {
access_token: this.serializer.stringify([user_id, client_id, +new Date, scope]),
refresh_token: null,
});
};

return out;
};

OAuth2Provider.prototype.login = function() {
var self = this;
var __self = this;

return function(req, res, next) {
var data, atok, user_id, client_id, grant_date, extra_data;
var data, atok, user_id, client_id, grant_date, scope;

if(req.query['access_token']) {
atok = req.query['access_token'];
if(req.query['access_token'] || req.body['access_token']) {
atok = req.query['access_token'] || req.body['access_token'];
} else if((req.headers['authorization'] || '').indexOf('Bearer ') == 0) {
atok = req.headers['authorization'].replace('Bearer', '').trim();
} else {
return next();
}

try {
data = self.serializer.parse(atok);
data = __self.serializer.parse(atok);
user_id = data[0];
client_id = data[1];
grant_date = new Date(data[2]);
extra_data = data[3];
scope = data[3];
} catch(e) {
res.writeHead(400);
return res.end(e.message);
}

self.emit('access_token', req, {
__self.emit('access_token', req, {
user_id: user_id,
client_id: client_id,
extra_data: extra_data,
scope: scope,
grant_date: grant_date
}, next);
};
Expand All @@ -121,96 +100,117 @@ OAuth2Provider.prototype.oauth = function() {

if(req.method == 'GET' && self.options.authorize_uri == uri) {
var client_id = req.query.client_id,
redirect_uri = req.query.redirect_uri;

if(!client_id || !redirect_uri) {
redirect_uri = req.query.redirect_uri,
scope = (req.query.scope || "basic");

if(!client_id || !redirect_uri || !scope) {
res.writeHead(400);
return res.end('client_id and redirect_uri required');
}

// authorization form will be POSTed to same URL, so we'll have all params
var authorize_url = req.url;

self.emit('enforce_login', req, res, authorize_url, function(user_id) {
self.emit('enforce_login', req, res, authorize_url, scope, function(user_id) {
// store user_id in an HMAC-protected encrypted query param
authorize_url += '&' + querystring.stringify({x_user_id: self.serializer.stringify(user_id)});

// user is logged in, render approval page
self.emit('authorize_form', req, res, client_id, authorize_url);

//fires when use allows app
self.emit('before_authorize_form', req, res, client_id, scope, function() {
self.emit('authorize_form', req, res, client_id, authorize_url, scope);
},function(){
var code = serializer.randomString(128);
self.emit('save_grant', req, client_id, code, scope, function() {
var extras = {
code: code,
};
var url = redirect_uri;
url += '?';
// pass back anti-CSRF opaque value
if (state) extras['state'] = state;
url += querystring.stringify(extras);
res.writeHead(303, {
Location: url
});
res.end();
});
});
});

} else if(req.method == 'POST' && self.options.authorize_uri == uri) {
var client_id = (req.query.client_id || req.body.client_id),
redirect_uri = (req.query.redirect_uri || req.body.redirect_uri),
response_type = (req.query.response_type || req.body.response_type) || 'code',
state = (req.query.state || req.body.state),
x_user_id = (req.query.x_user_id || req.body.x_user_id);

var url = redirect_uri;

switch(response_type) {
case 'code': url += '?'; break;
case 'token': url += '#'; break;
//fires when use allows app
var client_id = (req.query.client_id || req.body.client_id),
scope = (req.query.scope || req.body.scope || "basic"),
redirect_uri = (req.query.redirect_uri || req.body.redirect_uri),
response_type = (req.query.response_type || req.body.response_type) || 'code',
state = (req.query.state || req.body.state),
x_user_id = (req.query.x_user_id || req.body.x_user_id);
var url = redirect_uri;
switch (response_type) {
case 'code':
url += '?';
break;
case 'token':
url += '#';
break;
default:
res.writeHead(400);
return res.end('invalid response_type requested');
}

if('allow' in req.body) {
if('token' == response_type) {
var user_id;

try {
user_id = self.serializer.parse(x_user_id);
} catch(e) {
console.error('allow/token error', e.stack);

res.writeHead(500);
return res.end(e.message);
}

self.emit('create_access_token', user_id, client_id, function(extra_data,token_options) {
var atok = self.generateAccessToken(user_id, client_id, extra_data, token_options);

if(self.listeners('save_access_token').length > 0)
self.emit('save_access_token', user_id, client_id, atok);

url += querystring.stringify(atok);

res.writeHead(303, {Location: url});
res.end();
});
} else {
var code = serializer.randomString(128);

self.emit('save_grant', req, client_id, code, function() {
var extras = {
code: code,
};

// pass back anti-CSRF opaque value
if(state)
extras['state'] = state;

url += querystring.stringify(extras);

res.writeHead(303, {Location: url});
res.writeHead(400);
return res.end('invalid response_type requested');
}
if ('allow' in req.body) {
self.emit('after_authorize_form', req, res, client_id, scope,function(){
if ('token' == response_type) {
var user_id;
try {
user_id = self.serializer.parse(x_user_id);
}
catch (e) {
console.error('allow/token error', e.stack);
res.writeHead(500);
return res.end(e.message);
}
//self.emit('create_access_token', req, user_id, client_id, scope, function(scope) {
var atok = self.generateAccessToken(user_id, client_id, scope);
if (self.listeners('save_access_token').length > 0) self.emit('save_access_token', user_id, client_id, atok);
url += querystring.stringify(atok);
res.writeHead(303, {
Location: url
});
res.end();
//});
}
else {
var code = serializer.randomString(128);
self.emit('save_grant', req, client_id, code, scope, function() {
var extras = {
code: code,
};
// pass back anti-CSRF opaque value
if (state) extras['state'] = state;
url += querystring.stringify(extras);
res.writeHead(303, {
Location: url
});
res.end();
});
}
});
}
else {
url += querystring.stringify({
error: 'access_denied'
});
res.writeHead(303, {
Location: url
});
res.end();
});
}
} else {
url += querystring.stringify({error: 'access_denied'});

res.writeHead(303, {Location: url});
res.end();
}

} else if(req.method == 'POST' && self.options.access_token_uri == uri) {
var client_id = req.body.client_id,
client_secret = req.body.client_secret,
redirect_uri = req.body.redirect_uri,
code = req.body.code;

var client_id = req.body.client_id || req.query.client_id,
redirect_uri = req.body.redirect_uri || req.query.redirect_uri,
client_secret = req.body.client_secret || req.query.client_secret,
code = req.body.code || req.query.code;
if(!client_id || !client_secret) {
var authorization = parse_authorization(req.headers.authorization);

Expand All @@ -222,36 +222,38 @@ OAuth2Provider.prototype.oauth = function() {
client_id = authorization[0];
client_secret = authorization[1];
}


//post auth
if('password' == req.body.grant_type) {
if(self.listeners('client_auth').length == 0) {
res.writeHead(401);
return res.end('client authentication not supported');
}

self.emit('client_auth', client_id, client_secret, req.body.username, req.body.password, function(err, user_id) {
self.emit('client_auth', client_id, client_secret, req.body.username, req.body.password, function(err, user_id, scope) {
if(err) {
res.writeHead(401);
return res.end(err.message);
}

res.writeHead(200, {'Content-type': 'application/json'});

self._createAccessToken(user_id, client_id, function(atok) {
self._createAccessToken(scope, user_id, client_id, function(atok) {
self.emit('remove_grant', user_id, client_id, code, scope);
res.end(JSON.stringify(atok));
});
});
} else {
self.emit('lookup_grant', client_id, client_secret, code, function(err, user_id) {
self.emit('lookup_grant', client_id, client_secret, code, function(err, user_id, scope) {
if(err) {
res.writeHead(400);
return res.end(err.message);
}

res.writeHead(200, {'Content-type': 'application/json'});

self._createAccessToken(user_id, client_id, function(atok) {
self.emit('remove_grant', user_id, client_id, code);
self._createAccessToken(scope, user_id, client_id, function(atok) {
self.emit('remove_grant', user_id, client_id, code, scope);

res.end(JSON.stringify(atok));
});
Expand All @@ -264,17 +266,17 @@ OAuth2Provider.prototype.oauth = function() {
};
};

OAuth2Provider.prototype._createAccessToken = function(user_id, client_id, cb) {
OAuth2Provider.prototype._createAccessToken = function(scope, user_id, client_id, cb) {
var self = this;

this.emit('create_access_token', user_id, client_id, function(extra_data, token_options) {
var atok = self.generateAccessToken(user_id, client_id, extra_data, token_options);
//this.emit('create_access_token', req, user_id, client_id, function(scope) {
var atok = self.generateAccessToken(user_id, client_id, scope);

if(self.listeners('save_access_token').length > 0)
self.emit('save_access_token', user_id, client_id, atok);
self.emit('save_access_token', user_id, client_id, atok, scope);

return cb(atok);
});
//});
};

exports.OAuth2Provider = OAuth2Provider;