From 77923e40c739afd4696f1eed4a60a196e5daf65a Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Mon, 28 Sep 2015 14:28:19 -0300 Subject: [PATCH] Fixing issue #28. Changed refresh.auth to access.auth in line 950 of index.js --- index.js | 1963 ++++++++++++++++++++++++++---------------------------- 1 file changed, 933 insertions(+), 1030 deletions(-) diff --git a/index.js b/index.js index 8e4b60e..30c0e3d 100644 --- a/index.js +++ b/index.js @@ -19,400 +19,352 @@ url = require('url'), Q = require('q'), jwt = require('jwt-simple'), util = require("util"), -base64url = require('base64url'), -cleanObj = require('clean-obj'); +base64url = require('base64url'); var defaults = { - login_url: '/login', - consent_url: '/consent', - scopes: { - openid: 'Informs the Authorization Server that the Client is making an OpenID Connect request.', - profile:'Access to the End-User\'s default profile Claims.', - email: 'Access to the email and email_verified Claims.', - address: 'Access to the address Claim.', - phone: 'Access to the phone_number and phone_number_verified Claims.', - offline_access: 'Grants access to the End-User\'s UserInfo Endpoint even when the End-User is not present (not logged in).' - }, - policies:{ - loggedIn: function(req, res, next) { - if(req.session.user) { - next(); - } else { - var q = req.parsedParams?req.path+'?'+querystring.stringify(req.parsedParams):req.originalUrl; - res.redirect(this.settings.login_url+'?'+querystring.stringify({return_url: q})); - } - }, - }, - adapters: { - redis: sailsRedis - }, - connections: { - def: { - adapter: 'redis' - } - }, - models: { - user: { - identity: 'user', - connection: 'def', - schema: true, - policies: 'loggedIn', - attributes: { - name: {type: 'string', required: true, unique: true}, - given_name: {type: 'string', required: true}, - middle_name: 'string', - family_name: {type: 'string', required: true}, - profile: 'string', - email: {type: 'string', email: true, required: true, unique: true}, - password: 'string', - picture: 'binary', - birthdate: 'date', - gender: 'string', - phone_number: 'string', - samePassword: function(clearText) { - var sha256 = crypto.createHash('sha256'); - sha256.update(clearText); - return this.password == sha256.digest('hex'); - } - }, - beforeCreate: function(values, next) { - if(values.password) { - if(values.password != values.passConfirm) { - return next("Password and confirmation does not match"); - } - var sha256 = crypto.createHash('sha256'); - sha256.update(values.password); - values.password = sha256.digest('hex'); - } - next(); - }, - beforeUpdate: function(values, next) { - if(values.password) { - if(values.password != values.passConfirm) { - return next("Password and confirmation does not match"); - } - var sha256 = crypto.createHash('sha256'); - sha256.update(values.password); - values.password = sha256.digest('hex'); - } - next(); - } - }, - client: { - identity: 'client', - connection: 'def', - schema: true, - policies: 'loggedIn', - attributes: { - key: {type: 'string', required: true, unique: true}, - secret: {type: 'string', required: true, unique: true}, - name: {type: 'string', required: true}, - image: 'binary', - user: {model: 'user'}, - redirect_uris: {type:'array', required: true}, - credentialsFlow: {type: 'boolean', defaultsTo: false} - }, - beforeCreate: function(values, next) { - if(!values.key) { - var sha256 = crypto.createHash('sha256'); - sha256.update(values.name); - sha256.update(Math.random()+''); - values.key = sha256.digest('hex'); - } - if(!values.secret) { - var sha256 = crypto.createHash('sha256'); - sha256.update(values.key); - sha256.update(values.name); - sha256.update(Math.random()+''); - values.secret = sha256.digest('hex'); - } - next(); - } - }, - consent: { - identity: 'consent', - connection: 'def', - policies: 'loggedIn', - attributes: { - user: {model: 'user', required: true}, - client: {model: 'client', required: true}, - scopes: 'array' - } - }, - auth: { - identity: 'auth', - connection: 'def', - policies: 'loggedIn', - attributes: { - client: {model: 'client', required: true}, - scope: {type: 'array', required: true}, - user: {model: 'user', required: true}, - sub: {type: 'string', required: true}, - code: {type: 'string', required: true}, - redirectUri: {type: 'url', required: true}, - responseType: {type: 'string', required: true}, - status: {type: 'string', required: true}, - accessTokens: { - collection: 'access', - via: 'auth' - }, - refreshTokens: { - collection: 'refresh', - via: 'auth' - } - } - }, - access: { - identity: 'access', - connection: 'def', - attributes: { - token: {type: 'string', required: true}, - type: {type: 'string', required: true}, - idToken: 'string', - expiresIn: 'integer', - scope: {type: 'array', required: true}, - client: {model: 'client', required: true}, - user: {model: 'user', required: true}, - auth: {model: 'auth'} - } - }, - refresh: { - identity: 'refresh', - connection: 'def', - attributes: { - token: {type: 'string', required: true}, - scope: {type: 'array', required: true}, - auth: {model: 'auth', required: true}, - status: {type: 'string', required: true} - } - } - } + login_url: '/login', + consent_url: '/consent', + scopes: { + openid: 'Informs the Authorization Server that the Client is making an OpenID Connect request.', + profile:'Access to the End-User\'s default profile Claims.', + email: 'Access to the email and email_verified Claims.', + address: 'Access to the address Claim.', + phone: 'Access to the phone_number and phone_number_verified Claims.', + offline_access: 'Grants access to the End-User\'s UserInfo Endpoint even when the End-User is not present (not logged in).' + }, + policies:{ + loggedIn: function(req, res, next) { + if(req.session.user) { + next(); + } else { + var q = req.parsedParams?req.path+'?'+querystring.stringify(req.parsedParams):req.originalUrl; + res.redirect(this.settings.login_url+'?'+querystring.stringify({return_url: q})); + } + }, + }, + adapters: { + redis: sailsRedis + }, + connections: { + def: { + adapter: 'redis' + } + }, + models: { + user: { + identity: 'user', + connection: 'def', + schema: true, + policies: 'loggedIn', + attributes: { + name: {type: 'string', required: true, unique: true}, + given_name: {type: 'string', required: true}, + middle_name: 'string', + family_name: {type: 'string', required: true}, + profile: 'string', + email: {type: 'string', email: true, required: true, unique: true}, + password: 'string', + picture: 'binary', + birthdate: 'date', + gender: 'string', + phone_number: 'string', + samePassword: function(clearText) { + var sha256 = crypto.createHash('sha256'); + sha256.update(clearText); + return this.password == sha256.digest('hex'); + } + }, + beforeCreate: function(values, next) { + if(values.password) { + if(values.password != values.passConfirm) { + return next("Password and confirmation does not match"); + } + var sha256 = crypto.createHash('sha256'); + sha256.update(values.password); + values.password = sha256.digest('hex'); + } + next(); + }, + beforeUpdate: function(values, next) { + if(values.password) { + if(values.password != values.passConfirm) { + return next("Password and confirmation does not match"); + } + var sha256 = crypto.createHash('sha256'); + sha256.update(values.password); + values.password = sha256.digest('hex'); + } + next(); + } + }, + client: { + identity: 'client', + connection: 'def', + schema: true, + policies: 'loggedIn', + attributes: { + key: {type: 'string', required: true, unique: true}, + secret: {type: 'string', required: true, unique: true}, + name: {type: 'string', required: true}, + image: 'binary', + user: {model: 'user'}, + redirect_uris: {type:'array', required: true}, + credentialsFlow: {type: 'boolean', defaultsTo: false} + }, + beforeCreate: function(values, next) { + if(!values.key) { + var sha256 = crypto.createHash('sha256'); + sha256.update(values.name); + sha256.update(Math.random()+''); + values.key = sha256.digest('hex'); + } + if(!values.secret) { + var sha256 = crypto.createHash('sha256'); + sha256.update(values.key); + sha256.update(values.name); + sha256.update(Math.random()+''); + values.secret = sha256.digest('hex'); + } + next(); + } + }, + consent: { + identity: 'consent', + connection: 'def', + policies: 'loggedIn', + attributes: { + user: {model: 'user', required: true}, + client: {model: 'client', required: true}, + scopes: 'array' + } + }, + auth: { + identity: 'auth', + connection: 'def', + policies: 'loggedIn', + attributes: { + client: {model: 'client', required: true}, + scope: {type: 'array', required: true}, + user: {model: 'user', required: true}, + code: {type: 'string', required: true}, + redirectUri: {type: 'url', required: true}, + responseType: {type: 'string', required: true}, + status: {type: 'string', required: true}, + accessTokens: { + collection: 'access', + via: 'auth' + }, + refreshTokens: { + collection: 'refresh', + via: 'auth' + } + } + }, + access: { + identity: 'access', + connection: 'def', + attributes: { + token: {type: 'string', required: true}, + type: {type: 'string', required: true}, + idToken: 'string', + expiresIn: 'integer', + scope: {type: 'array', required: true}, + client: {model: 'client', required: true}, + user: {model: 'user', required: true}, + auth: {model: 'auth'} + } + }, + refresh: { + identity: 'refresh', + connection: 'def', + attributes: { + token: {type: 'string', required: true}, + scope: {type: 'array', required: true}, + auth: {model: 'auth', required: true}, + status: {type: 'string', required: true} + } + } + } }; function parse_authorization(authorization) { - if(!authorization) - return null; + if(!authorization) + return null; - var parts = authorization.split(' '); + var parts = authorization.split(' '); - if(parts.length != 2 || parts[0] != 'Basic') - return null; + if(parts.length != 2 || parts[0] != 'Basic') + return null; - var creds = new Buffer(parts[1], 'base64').toString(), - i = creds.indexOf(':'); + var creds = new Buffer(parts[1], 'base64').toString(), + i = creds.indexOf(':'); - if(i == -1) - return null; + if(i == -1) + return null; - var username = creds.slice(0, i); - password = creds.slice(i + 1); + var username = creds.slice(0, i); + password = creds.slice(i + 1); - return [username, password]; + return [username, password]; } + + function OpenIDConnect(options) { - this.settings = extend(true, {}, defaults, options); - - //allow removing attributes, by marking thme as null - cleanObj(this.settings.models, true); - - for(var i in this.settings.policies) { - this.settings.policies[i] = this.settings.policies[i].bind(this); - } - - if(this.settings.alien) { - for(var i in alien) { - if(this.settings.models[i]) delete this.settings.models[i]; - } - } - - if(this.settings.orm) { - this.orm = this.settings.orm; - for(var i in this.settings.policies) { - this.orm.setPolicy(true, i, this.settings.policies[i]); - } - } else { - - this.orm = new modelling({ - models: this.settings.models, - adapters: this.settings.adapters, - connections: this.settings.connections, - app: this.settings.app, - policies: this.settings.policies - }); - } + this.settings = extend(true, {}, defaults, options); + //var rm = require('redis-modelize'); + for(var i in this.settings.policies) { + this.settings.policies[i] = this.settings.policies[i].bind(this); + } + + if(this.settings.alien) { + for(var i in alien) { + if(this.settings.models[i]) delete this.settings.models[i]; + } + } + + if(this.settings.orm) { + this.orm = this.settings.orm; + for(var i in this.settings.policies) { + this.orm.setPolicy(true, i, this.settings.policies[i]); + } + } else { + + this.orm = new modelling({ + models: this.settings.models, + adapters: this.settings.adapters, + connections: this.settings.connections, + app: this.settings.app, + policies: this.settings.policies + }); + } } OpenIDConnect.prototype = new EventEmitter(); OpenIDConnect.prototype.done = function() { - this.orm.done(); + this.orm.done(); }; OpenIDConnect.prototype.model = function(name) { - return this.orm.model(name); + return this.orm.model(name); } OpenIDConnect.prototype.use = function(name) { - var alien = {}; - if(this.settings.alien) { - var self = this; - if(!name) { - alien = this.settings.alien; - } else { - var m; - if(_.isPlainObject(name) && name.models) { - m = name.models; - } - if(util.isArray(m||name)) { - (m||name).forEach(function(model) { - if(self.settings.alien[model]) { - alien[model] = self.settings.alien[model]; - } - }); - } else if(self.settings.alien[m||name]) { - alien[m||name] = self.settings.alien[m||name]; - } - } - } - return [this.orm.use(name), function(req, res, next) { - extend(req.model, alien); - next(); - }]; + var alien = {}; + if(this.settings.alien) { + var self = this; + if(!name) { + alien = this.settings.alien; + } else { + var m; + if(_.isPlainObject(name) && name.models) { + m = name.models; + } + if(util.isArray(m||name)) { + (m||name).forEach(function(model) { + if(self.settings.alien[model]) { + alien[model] = self.settings.alien[model]; + } + }); + } else if(self.settings.alien[m||name]) { + alien[m||name] = self.settings.alien[m||name]; + } + } + } + return [this.orm.use(name), function(req, res, next) { + extend(req.model, alien); + next(); + }]; }; OpenIDConnect.prototype.getOrm = function() { - return this.orm; + return this.orm; } /*OpenIDConnect.prototype.getClientParams = function() { - return this.orm.client.getParams(); + return this.orm.client.getParams(); };*/ /*OpenIDConnect.prototype.searchClient = function(parts, callback) { - return new this.orm.client.reverse(parts, callback); + return new this.orm.client.reverse(parts, callback); }; OpenIDConnect.prototype.getUserParams = function() { - return this.orm.user.getParams(); + return this.orm.user.getParams(); }; OpenIDConnect.prototype.user = function(params, callback) { - return new this.orm.user(params, callback); + return new this.orm.user(params, callback); }; OpenIDConnect.prototype.searchUser = function(parts, callback) { - return new this.orm.user.reverse(parts, callback); + return new this.orm.user.reverse(parts, callback); };*/ OpenIDConnect.prototype.errorHandle = function(res, uri, error, desc) { - if(uri) { - var redirect = url.parse(uri,true); - redirect.query.error = error; //'invalid_request'; - redirect.query.error_description = desc; //'Parameter '+x+' is mandatory.'; - res.redirect(400, url.format(redirect)); - } else { - res.send(400, error+': '+desc); - } + if(uri) { + var redirect = url.parse(uri,true); + redirect.query.error = error; //'invalid_request'; + redirect.query.error_description = desc; //'Parameter '+x+' is mandatory.'; + res.redirect(400, url.format(redirect)); + } else { + res.send(400, error+': '+desc); + } }; OpenIDConnect.prototype.endpointParams = function (spec, req, res, next) { - try { - req.parsedParams = this.parseParams(req, res, spec); - next(); - } catch(err) { - this.errorHandle(res, err.uri, err.error, err.msg); - } + try { + req.parsedParams = this.parseParams(req, res, spec); + next(); + } catch(err) { + this.errorHandle(res, err.uri, err.error, err.msg); + } } OpenIDConnect.prototype.parseParams = function(req, res, spec) { - var params = {}; - var r = req.param('redirect_uri'); - for(var i in spec) { - var x = req.param(i); - if(x) { - params[i] = x; - } - } - - for(var i in spec) { - var x = params[i]; - if(!x) { - var error = false; - if(typeof spec[i] == 'boolean') { - error = spec[i]; - } else if (_.isPlainObject(spec[i])) { - for(var j in spec[i]) { - if(!util.isArray(spec[i][j])) { - spec[i][j] = [spec[i][j]]; - } - spec[i][j].forEach(function(e) { - if(!error) { - if(util.isRegExp(e)) { - error = e.test(params[j]); - } else { - error = e == params[j]; - } - } - }); - } - } else if (_.isFunction(spec[i])) { - error = spec[i](params); - } - - if(error) { - throw {type: 'error', uri: r, error: 'invalid_request', msg: 'Parameter '+i+' is mandatory.'}; - //this.errorHandle(res, r, 'invalid_request', 'Parameter '+i+' is mandatory.'); - //return; - } - } - } - return params; -}; - -/** - * login - * - * returns a function to be placed as middleware in connect/express routing methods. For example: - * - * app.post('/login', oidc.login(), afterLogin, loginErrorHandler); - * - * This calls verification strategy and creates session. - * Verification strategy must have two parameters: req and callback function with two parameters: error and user - * - * - */ - -OpenIDConnect.prototype.login = function(validateUser) { - var self = this; - - return [self.use({policies: {loggedIn: false}, models: 'user'}), - function(req, res, next) { - validateUser(req, /*next:*/function(error,user) { - if(!error && !user) { - error = new Error('User not validated'); - } - if(!error) { - if(user.id) { - req.session.user = user.id; - } else { - delete req.session.user; - } - if(user.sub) { - if(typeof user.sub ==='function') { - req.session.sub = user.sub(); - } else { - req.session.sub = user.sub; - } - } else { - delete req.session.sub; - } - return next(); - } else { - return next(error); - } - }); - }]; + var params = {}; + var r = req.param('redirect_uri'); + for(var i in spec) { + var x = req.param(i); + if(x) { + params[i] = x; + } + } + + for(var i in spec) { + var x = params[i]; + if(!x) { + var error = false; + if(typeof spec[i] == 'boolean') { + error = spec[i]; + } else if (_.isPlainObject(spec[i])) { + for(var j in spec[i]) { + if(!util.isArray(spec[i][j])) { + spec[i][j] = [spec[i][j]]; + } + spec[i][j].forEach(function(e) { + if(!error) { + if(util.isRegExp(e)) { + error = e.test(params[j]); + } else { + error = e == params[j]; + } + } + }); + } + } else if (_.isFunction(spec[i])) { + error = spec[i](params); + } + + if(error) { + throw {type: 'error', uri: r, error: 'invalid_request', msg: 'Parameter '+i+' is mandatory.'}; + //this.errorHandle(res, r, 'invalid_request', 'Parameter '+i+' is mandatory.'); + //return; + } + } + } + return params; }; /** @@ -426,250 +378,250 @@ OpenIDConnect.prototype.login = function(validateUser) { * */ OpenIDConnect.prototype.auth = function() { - var self = this; - var spec = { - response_type: true, - client_id: true, - scope: true, - redirect_uri: true, - state: false, - nonce: function(params){ - return params.response_type.indexOf('id_token')!==-1; - }, - display: false, - prompt: false, - max_age: false, - ui_locales: false, - claims_locales: false, - id_token_hint: false, - login_hint: false, - acr_values: false, - response_mode: false - }; - return [function(req, res, next) { - self.endpointParams(spec, req, res, next); - }, - self.use(['client', 'consent', 'auth', 'access']), - function(req, res, next) { - Q(req.parsedParams).then(function(params) { - //Step 2: Check if response_type is supported and client_id is valid. - - var deferred = Q.defer(); - switch(params.response_type) { - case 'none': - case 'code': - case 'token': - case 'id_token': - break; - default: - //var error = false; - var sp = params.response_type.split(' '); - sp.forEach(function(response_type) { - if(['code', 'token', 'id_token'].indexOf(response_type) == -1) { - throw {type: 'error', uri: params.redirect_uri, error: 'unsupported_response_type', msg: 'Response type '+response_type+' not supported.'}; - } - }); - } - req.model.client.findOne({key: params.client_id}, function(err, model) { - if(err || !model || model === '') { - deferred.reject({type: 'error', uri: params.redirect_uri, error: 'invalid_client', msg: 'Client '+params.client_id+' doesn\'t exist.'}); - } else { - req.session.client_id = model.id; - req.session.client_secret = model.secret; - deferred.resolve(params); - } - }); - - return deferred.promise; - }).then(function(params){ - //Step 3: Check if scopes are valid, and if consent was given. - - var deferred = Q.defer(); - var reqsco = params.scope.split(' '); - req.session.scopes = {}; - var promises = []; - req.model.consent.findOne({user: req.session.user, client: req.session.client_id}, function(err, consent) { - reqsco.forEach(function(scope) { - var innerDef = Q.defer(); - if(!self.settings.scopes[scope]) { - innerDef.reject({type: 'error', uri: params.redirect_uri, error: 'invalid_scope', msg: 'Scope '+scope+' not supported.'}); - } - if(!consent) { - req.session.scopes[scope] = {ismember: false, explain: self.settings.scopes[scope]}; - innerDef.resolve(true); - } else { - var inScope = consent.scopes.indexOf(scope) !== -1; - req.session.scopes[scope] = {ismember: inScope, explain: self.settings.scopes[scope]}; - innerDef.resolve(!inScope); - } - promises.push(innerDef.promise); - }); - - Q.allSettled(promises).then(function(results){ - var redirect = false; - for(var i = 0; i 1) { - var last = errors.pop(); - self.errorHandle(res, null, 'invalid_scope', 'Required scopes '+errors.join(', ')+' and '+last+' where not granted.'); - } else if(errors.length > 0) { - self.errorHandle(res, null, 'invalid_scope', 'Required scope '+errors.pop()+' not granted.'); - } else { - req.check = req.check||{}; - req.check.scopes = access.scope; - next(); - } - } else { - self.errorHandle(res, null, 'unauthorized_client', 'Access token is not valid.'); - } - }); - } else { - self.errorHandle(res, null, 'unauthorized_client', 'No access token found.'); - } - } - } - ]; + //Seguir desde acá!!!! + var scopes = Array.prototype.slice.call(arguments, 0); + if(!util.isArray(scopes)) { + scopes = [scopes]; + } + var self = this; + spec = { + access_token: false + }; + + return [ + function(req, res, next) { + self.endpointParams(spec, req, res, next); + }, + self.use(['access', 'auth']), + function(req, res, next) { + var params = req.parsedParams;//self.parseParams(req, res, spec); + if(!scopes.length) { + next(); + } else { + if(!params.access_token) { + params.access_token = (req.headers['authorization'] || '').indexOf('Bearer ') == 0?req.headers['authorization'].replace('Bearer', '').trim():false; + } + if(params.access_token) { + req.model.access.findOne({token: params.access_token}) + .populate('user') + .exec(function(err, access) { + //self.model.access.reverse(params.access_token, function(err, id) { + if(!err && access) { + if(access.user.id == req.session.user) { + var errors = []; + scopes.forEach(function(scope) { + if(typeof scope == 'string') { + if(access.scope.indexOf(scope) == -1) { + errors.push(scope); + } + } else if(util.isRegExp(scope)) { + var inS = false; + access.scope.forEach(function(s){ + if(scope.test(s)) { + inS = true; + } + }); + !inS && errors.push('('+scope.toString().replace(/\//g,'')+')'); + } + }); + if(errors.length > 1) { + var last = errors.pop(); + self.errorHandle(res, null, 'invalid_scope', 'Required scopes '+errors.join(', ')+' and '+last+' where not granted.'); + } else if(errors.length > 0) { + self.errorHandle(res, null, 'invalid_scope', 'Required scope '+errors.pop()+' not granted.'); + } else { + req.session.check = req.session.check||{}; + req.session.check.scopes = access.scope; + next(); + } + } else { + //Delete access token, and every thing related to it. + + req.model.auth.findOne({id: access.auth}) + .populate('accessTokens') + .populate('refreshTokens') + .populate('client') + .exec(function(err, auth) { + auth.accessTokens.forEach(function(access){ + access.destroy(); + }); + auth.refreshTokens.forEach(function(refresh){ + refresh.destroy(); + }); + auth.destroy(); + }); + + self.errorHandle(res, null, 'invalid_grant', 'Access token issued for an other user.'); + } + } else { + self.errorHandle(res, null, 'unauthorized_client', 'Access token is not valid.'); + } + }); + } else { + self.errorHandle(res, null, 'unauthorized_client', 'No access token found.'); + } + } + } + ]; }; /** @@ -1077,102 +1051,31 @@ OpenIDConnect.prototype.check = function() { * This function returns the user info in a json object. Checks for scope and login are included. */ OpenIDConnect.prototype.userInfo = function() { - var self = this; - return [ - self.check('openid', /profile|email/), - self.use({policies: {loggedIn: false}, models: ['access', 'user']}), - function(req, res, next) { - req.model.access.findOne({token: req.parsedParams.access_token}) - .exec(function(err, access) { - if(!err && access) { - req.model.user.findOne({id: access.user}, function(err, user) { - if(req.check.scopes.indexOf('profile') != -1) { - user.sub = req.session.sub||req.session.user; - delete user.id; - delete user.password; - delete user.openidProvider; - res.json(user); - } else { - res.json({email: user.email}); - } - }); - } else { - self.errorHandle(res, null, 'unauthorized_client', 'Access token is not valid.'); - } - }); - }]; -}; - -/** - * removetokens - * - * returns a function to be placed as middleware in connect/express routing methods. For example: - * - * app.get('/logout', oidc.removetokens(), function(req, res, next) { ... }); - * - * this function removes all tokens that were issued to the user - * access_token is required either as a parameter or as a Bearer token - */ -OpenIDConnect.prototype.removetokens = function() { - var self = this, - spec = { - access_token: false //parameter not mandatory - }; - - return [ - function(req, res, next) { - self.endpointParams(spec, req, res, next); - }, - self.use({policies: {loggedIn: false}, models: ['access','auth']}), - function(req, res, next) { - var params = req.parsedParams; - - if(!params.access_token) { - params.access_token = (req.headers['authorization'] || '').indexOf('Bearer ') === 0 ? req.headers['authorization'].replace('Bearer', '').trim() : false; - } - if(params.access_token) { - //Delete the provided access token, and other tokens issued to the user - req.model.access.findOne({token: params.access_token}) - .exec(function(err, access) { - if(!err && access) { - req.model.auth.findOne({user: access.user}) - .populate('accessTokens') - .populate('refreshTokens') - .exec(function(err, auth) { - if(!err && auth) { - auth.accessTokens.forEach(function(access){ - access.destroy(); - }); - auth.refreshTokens.forEach(function(refresh){ - refresh.destroy(); - }); - auth.destroy(); - }; - req.model.access.find({user:access.user}) - .exec(function(err,accesses){ - if(!err && accesses) { - accesses.forEach(function(access) { - access.destroy(); - }); - }; - return next(); - }); - }); - } else { - self.errorHandle(res, null, 'unauthorized_client', 'Access token is not valid.'); - } - }); - } else { - self.errorHandle(res, null, 'unauthorized_client', 'No access token found.'); - } - } - ]; + var self = this; + return [ + self.check('openid', /profile|email/), + self.use('user'), + function(req, res, next) { + req.model.user.findOne({id: req.session.user}, function(err, user) { + //self.client(req.session.user, function(err, id) { + if(req.session.check.scopes.indexOf('profile') != -1) { + user.sub = user.id + delete user.id; + delete user.password; + delete user.openidProvider; + res.json(user); + } else { + res.json({email: user.email}); + } + }); + } + ]; }; exports.oidc = function(options) { - return new OpenIDConnect(options); + return new OpenIDConnect(options); }; exports.defaults = function() { - return defaults; + return defaults; }