From 847e8c2a6a6478c6486e5ed92ab8be91af7d0560 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 20 Mar 2017 17:55:27 -0600 Subject: [PATCH] begining of node support --- oauth3.node.js | 112 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 oauth3.node.js diff --git a/oauth3.node.js b/oauth3.node.js new file mode 100644 index 0000000..156cd5e --- /dev/null +++ b/oauth3.node.js @@ -0,0 +1,112 @@ +'use strict'; + +//var OAUTH3 = require('./oauth3.core.js').OAUTH3; +var OAUTH3 = require('./oauth3.issuer.js').OAUTH3; +// used for OAUTH3.urls.resourcePasswordOwner +// used for OAUTH3.authn.loginMeta +// used for OAUTH3.authn.otp +// used for OAUTH3.authn.resourcePasswordOwner +var PromiseA = require('bluebird'); +var requestAsync = PromiseA.promisify(require('request')); +var crypto = require('crypto'); + +OAUTH3._discoverHelper = function(providerUri, opts) { + return OAUTH3._browser.discover(providerUri, opts); +}; +OAUTH3._requestHelper = function (preq, opts) { + /* + if (opts && opts.directives) { + preq.url = OAUTH3.url.resolve(opts.directives.issuer, preq.url); + } + */ + return OAUTH3._node.request(preq, opts); +}; +OAUTH3._node = {}; +OAUTH3._node.discover = function(providerUri/*, opts*/) { + return OAUTH3.request({ + method: 'GET' + , url: OAUTH3.url.normalize(providerUri) + '/.well-known/oauth3/directives.json' + }).then(function (resp) { + return resp.data; + }); +}; +OAUTH3._node.request = function(preq/*, _sys*/) { + var data = { + method: preq.method + , url: preq.url || preq.uri + , headers: preq.headers + , json: preq.data || preq.body || preq.json || undefined // TODO which to use? + , formData: preq.formData || undefined + }; + + //console.log('DEBUG request'); + //console.log(preq.url || preq.uri); + //console.log(data.json); + + return requestAsync(data).then(OAUTH3._node._parseJson); +}; +OAUTH3._node._parseJson = function (resp) { + var err; + var json = resp.body; + + // TODO toCamelCase + if (!(resp.statusCode >= 200 && resp.statusCode < 400)) { + // console.log('[A3] DEBUG', resp.body); + err = new Error("bad response code: " + resp.statusCode); + err.result = resp.body; + return PromiseA.reject(err); + } + + //console.log('resp.body', typeof resp.body); + if ('string' === typeof json) { + try { + json = JSON.parse(json); + } catch(e) { + err = new Error('response not parsable:' + resp.body); + err.result = resp.body; + return PromiseA.reject(err); + } + } + + // handle both Oauth2- and node-style errors + if (json.error) { + err = new Error(json.error && json.error.message || json.error_description || json.error); + err.result = json; + return PromiseA.reject(err); + } + + return json; +}; +OAUTH3._logoutHelper = function(directives, opts) { + var logoutReq = OAUTH3.urls.logout( + directives + , { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location)) + , windowType: 'popup' // we'll figure out background later + , broker: opts.broker + //, state: opts._state + , debug: opts.debug + } + ); + + return OAUTH3._browser.frameRequest( + OAUTH3.url.resolve(directives.issuer, logoutReq.url) + , logoutReq.state // state should recycle params + , { windowType: 'popup' + , reuseWindow: opts.broker && '-broker' + , debug: opts.debug + } + ).then(function (params) { + OAUTH3._browser.closeFrame(params.state || opts._state, opts); + + if (params.error) { + // TODO directives.audience + return OAUTH3.PromiseA.reject(OAUTH3.error.parse(directives.issuer /*providerUri*/, params)); + } + + return params; + }); +}; +OAUTH3._node.randomState = function () { + return crypto.randomBytes(16).toString('hex'); +}; +OAUTH3.randomState = OAUTH3._node.randomState;