From 01fbffd6c2f0f12745a8a4a8f9cc5884ca91c278 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Wed, 22 Mar 2017 09:48:04 -0600 Subject: [PATCH] update api for storage and order of operations --- bin/oauth3.js | 211 ++++++++++++++++++++------------- node_modules/terminal-forms.js | 2 +- oauth3.core.js | 8 +- oauth3.node.storage.js | 24 ++-- oauth3.org.directives.json | 66 +++++++++++ oauth3.org.session.json | 66 +++++++++++ 6 files changed, 281 insertions(+), 96 deletions(-) create mode 100644 oauth3.org.directives.json create mode 100644 oauth3.org.session.json diff --git a/bin/oauth3.js b/bin/oauth3.js index b58eceb..e4c4eb9 100644 --- a/bin/oauth3.js +++ b/bin/oauth3.js @@ -2,108 +2,151 @@ // process.stdout.isTTY var form = require('terminal-forms.js').create(process.stdin, process.stdout); +//var dns = form.PromiseA.promisifyAll(require('dns')); var OAUTH3 = require('../oauth3.node.js'); // TODO change to ._hooks OAUTH3._hooks = require('../oauth3.node.storage.js'); // directives = { get, set } // sessions = { get, set } -OAUTH3.hooks.directives._set = require('../oauth3.node.storage.js').directives._set; -OAUTH3.hooks.session._get = require('../oauth3.node.storage.js').session._get; -OAUTH3.hooks.session._set = require('../oauth3.node.storage.js').session._set; -OAUTH3._hooks.directives.get = require('../oauth3.node.storage.js').directives._get; -OAUTH3._hooks.directives.set = require('../oauth3.node.storage.js').directives._set; -OAUTH3._hooks.session.get = require('../oauth3.node.storage.js').session._get; -OAUTH3._hooks.session.set = require('../oauth3.node.storage.js').session._set; +/* +OAUTH3._hooks.directives.get = require('../oauth3.node.storage.js').directives.get; +OAUTH3._hooks.directives.set = require('../oauth3.node.storage.js').directives.set; +OAUTH3._hooks.session.get = require('../oauth3.node.storage.js').sessions.get; +OAUTH3._hooks.session.set = require('../oauth3.node.storage.js').sessions.set; +*/ var url = require('url'); //console.log('stdin tty', process.stdin.isTTY); //console.log('stdout tty', process.stdout.isTTY); +var oauth3; +var opts = { + providerUri: undefined +}; -form.ask({ label: "What's your OAuth3 Provider URL? ", type: 'url' }).then(function (urlResult) { - var urlObj = url.parse(urlResult.result || urlResult.input); - // TODO get unique client id for bootstrapping app - var oauth3 = OAUTH3.create(urlObj); - var providerPromise = oauth3.setProvider(urlObj.host + urlObj.pathname); +function getCurrentUserEmail() { + return form.ask({ label: "What's your email (or cloud mail) address? ", type: 'email' }).then(function (emailResult) { + var emailParts = (emailResult.result || emailResult.input).split('@'); + var domain = emailParts[1]; + var username; + var sameProvider; - function getCurrentUserEmail() { - return form.ask({ label: "What's your email (or cloud mail) address? ", type: 'email' }).then(function (emailResult) { + var urlObj = url.parse(opts.providerUri || domain); + // TODO get unique client id for bootstrapping app + oauth3 = OAUTH3.create(urlObj); + form.println("got to setProvider"); + return oauth3.setProvider(domain).then(function () { + form.println("got to setProvider SUCCESS"); + sameProvider = true; + // ignore + }, function () { + form.println("got to setProvider ERROR"); + function askOauth3Url() { + return form.ask({ label: "What's your OAuth3 Provider URL? ", type: 'url' }).then(function (urlResult) { + var urlObj = url.parse(urlResult.result || urlResult.input); + // TODO get unique client id for bootstrapping app + oauth3 = OAUTH3.create(urlObj); + return oauth3.setProvider(urlResult.result || urlResult.input).then(function () { + // ignore + }, function (err) { + form.println(err.stack || err.message || err.toString()); + return askOauth3Url(); + }); + }); + } + + return askOauth3Url(); + }).then(function () { // TODO lookup uuid locally before performing loginMeta // TODO lookup token locally before performing loginMeta / otp - return providerPromise.then(function () { - return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: emailResult.input }).then(function (/*result*/) { - return emailResult.input; - }, function (/*err*/) { - // TODO require hashcash to create user account - function confirmCreateAccount() { - // TODO directives should specify private (invite-only) vs internal (request) vs public (allow) accounts + form.println("got to loginMeta"); + return OAUTH3.authn.loginMeta(oauth3._providerDirectives, { email: emailResult.input }).then(function (/*result*/) { + return { node: emailResult.result || emailResult.input, type: 'email' }; + }, function (/*err*/) { + // TODO require hashcash to create user account + function confirmCreateAccount() { + // TODO directives should specify private (invite-only) vs internal (request) vs public (allow) accounts + return form.ask({ + label: "We don't recognize that address. Do you want to create a new account? [Y/n] " + , type: 'text' // TODO boolean with default Y or N + }).then(function (result) { + if (!result.input) { + result.input = 'Y'; + } + + // TODO needs backup address if email is on same domain as login + result.input = result.input.toLowerCase(); + + if ('y' !== result.input) { + return getCurrentUserEmail(); + } + + if (!sameProvider) { + return { node: emailResult.result || emailResult.input, type: 'email' }; + } + return form.ask({ - label: "We don't recognize that address. Do you want to create a new account? [Y/n] " - , type: 'text' // TODO boolean with default Y or N - }).then(function (result) { - if (!result.input) { - result.input = 'Y'; - } - - result.input = result.input.toLowerCase(); - - if ('y' !== result.input) { - return getCurrentUserEmail(); - } - - return emailResult.input; + label: "What's your recovery email (or cloud mail) address? ", type: 'email' + }).then(function (recoveryResult) { + username = emailParts[0]; + return { + node: emailResult.result || emailResult.input + , type: 'name' + , recovery: recoveryResult.result || recoveryResult.input + }; }); - } - - return confirmCreateAccount(); - }); - }); - }); - } - - return getCurrentUserEmail().then(function (email) { - // TODO skip if token exists locally - form.println("Sending login code to '" + email + "'..."); - return OAUTH3.authn.otp(oauth3._providerDirectives, { email: email }).then(function (otpResult) { - return form.ask({ - label: "What's your login code? " - , help: "(it was sent to '" + email + "' and looks like 1234-5678-9012)" - // onkeyup - // ondebounce - // onchange - // regexp // html5 name? - , onReturnAsync: function (rs, ws, input/*, ch*/) { - var formatted = input.toLowerCase().replace(/[^\d]+/g, ''); - - if (12 !== formatted.length) { - return form.PromiseA.reject(new Error("invalid code please try again in the format xxxx-yyyy-zzzz")); - } - - formatted = formatted.match(/.{4,4}/g).join('-'); - - if (14 !== formatted.split('').length) { - return form.PromiseA.reject(new Error("invalid code '" + formatted + "', please try again xxxx-yyyy-zzzz")); - } - - var data = { - username: email - , username_type: 'email' - , client_id: OAUTH3.uri.normalize(oauth3._providerDirectives.issuer) - , client_uri: OAUTH3.uri.normalize(oauth3._providerDirectives.issuer) - , otp_code: formatted - , otp_uuid: otpResult.data.uuid - }; - - // returns session instead of input - var colors = require('colors'); - form.setStatus(colors.dim("authenticating with server...")); - return OAUTH3.authn.resourceOwnerPassword(oauth3._providerDirectives, data); + }); } - }).then(function (results) { - var session = results.result; - form.println('session:'); - form.println(session); + return confirmCreateAccount(); }); }); }); +} + +return getCurrentUserEmail().then(function (user) { + // TODO skip if token exists locally + var email = (user.recovery || user.node); + form.println("Sending login code to '" + email + "'..."); + return OAUTH3.authn.otp(oauth3._providerDirectives, { email: email }).then(function (otpResult) { + return form.ask({ + label: "What's your login code? " + , help: "(it was sent to '" + email + "' and looks like 1234-5678-9012)" + // onkeyup + // ondebounce + // onchange + // regexp // html5 name? + , onReturnAsync: function (rs, ws, input/*, ch*/) { + var formatted = input.toLowerCase().replace(/[^\d]+/g, ''); + + if (12 !== formatted.length) { + return form.PromiseA.reject(new Error("invalid code please try again in the format xxxx-yyyy-zzzz")); + } + + formatted = formatted.match(/.{4,4}/g).join('-'); + + if (14 !== formatted.split('').length) { + return form.PromiseA.reject(new Error("invalid code '" + formatted + "', please try again xxxx-yyyy-zzzz")); + } + + var data = { + username: email + , username_type: 'email' + , client_id: OAUTH3.uri.normalize(oauth3._providerDirectives.issuer) + , client_uri: OAUTH3.uri.normalize(oauth3._providerDirectives.issuer) + , otp_code: formatted + , otp_uuid: otpResult.data.uuid + }; + + // returns session instead of input + var colors = require('colors'); + form.setStatus(colors.dim("authenticating with server...")); + return OAUTH3.authn.resourceOwnerPassword(oauth3._providerDirectives, data); + } + }).then(function (results) { + var session = results.result; + + form.println('session:'); + form.println(session); + }); + }); }); diff --git a/node_modules/terminal-forms.js b/node_modules/terminal-forms.js index 3f2e11a..f078d47 160000 --- a/node_modules/terminal-forms.js +++ b/node_modules/terminal-forms.js @@ -1 +1 @@ -Subproject commit 3f2e11a41d5dbf5903abbf457eba3b2f3ec6a1d8 +Subproject commit f078d479b085e8658fb2039eb3e4de49afd9db0e diff --git a/oauth3.core.js b/oauth3.core.js index 1afeeea..32b4460 100644 --- a/oauth3.core.js +++ b/oauth3.core.js @@ -1054,10 +1054,10 @@ p = OAUTH3.discover(this._providerUri, { client_id: this._clientUri }); } - return OAUTH3.discover(this._clientUri, { client_id: this._clientUri }).then(function (clientDirectives) { - me._clientDirectives = clientDirectives; - return p.then(function () { - return clientDirectives; + return p.then(function () { + return OAUTH3.discover(me._clientUri, { client_id: me._clientUri }).then(function (clientDirectives) { + me._clientDirectives = clientDirectives; + return clientDirectives; }); }); } diff --git a/oauth3.node.storage.js b/oauth3.node.storage.js index 0285a30..0351508 100644 --- a/oauth3.node.storage.js +++ b/oauth3.node.storage.js @@ -5,7 +5,7 @@ var path = require('path'); module.exports = { directives: { - _get: function (providerUri) { + get: function (providerUri) { // TODO make safe try { return require(path.join(process.cwd(), providerUri + '.directives.json')); @@ -13,23 +13,33 @@ module.exports = { return null; } } - , _set: function (providerUri, directives) { + , set: function (providerUri, directives) { fs.writeFileSync(path.join(process.cwd(), providerUri + '.directives.json'), JSON.stringify(directives, null, 2)); return directives; } } -, session: { - _get: function (providerUri) { +, sessions: { + get: function (providerUri, id) { // TODO make safe try { - return require(path.join(process.cwd(), providerUri + '.session.json')); + if (id) { + return require(path.join(process.cwd(), providerUri + '.' + id + '.session.json')); + } + else { + return require(path.join(process.cwd(), providerUri + '.session.json')); + } } catch(e) { return null; } } - , _set: function (providerUri, session) { - fs.writeFileSync(path.join(process.cwd(), providerUri + '.session.json'), JSON.stringify(session, null, 2)); + , set: function (providerUri, session, id) { + if (id) { + fs.writeFileSync(path.join(process.cwd(), providerUri + '.' + id + '.session.json'), JSON.stringify(session, null, 2)); + } + else { + fs.writeFileSync(path.join(process.cwd(), providerUri + '.session.json'), JSON.stringify(session, null, 2)); + } return session; } } diff --git a/oauth3.org.directives.json b/oauth3.org.directives.json new file mode 100644 index 0000000..39a4515 --- /dev/null +++ b/oauth3.org.directives.json @@ -0,0 +1,66 @@ +{ + "provider_uri": "https://oauth3.org", + "client_uri": "oauth3.org", + "token_type": "bearer", + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiIzOTZjMzJlNzE1NmIzNGI1ZWY1ZWYwZWU4Zjk3Y2NiMyIsImlhdCI6MTQ5MDE5NzUyNywiaXNzIjoib2F1dGgzLm9yZyIsImF1ZCI6Im9hdXRoMy5vcmciLCJhenAiOiJvYXV0aDMub3JnIiwic3ViIjoiIiwia2lkIjoib2F1dGgzLm9yZyIsInNjcCI6IiIsImFzIjoibG9naW4iLCJncnQiOiJwYXNzd29yZCIsInNydiI6ZmFsc2UsImsiOiJvYXV0aDMub3JnIiwiYXBwIjoib2F1dGgzLm9yZyIsImFjeCI6eyJpZCI6IjE1LUxhM3JnZXBFelBCR0xITHlrdEZOT1NDZFNVOXZJdjlKc2EzTkMxYVJUc3ZmUTZ5cDJuVFFfZWxmdkhzYTEifSwiYXhzIjpbXSwidXNyIjoiYTM3YWVkYTk5ZDQ5MThhMDM0YzM0MmQ2NGNkZjRiN2VkMjM0ZGZlNSIsImFjYyI6eyJpZCI6IjUzZTUwMTk2LTE4ZTMtNGJlNi04NDcyLTQ1ZDBjNDMxZjdhZCJ9LCJhY3MiOltdLCJpZHgiOiJuZnZ1bHRETE0tT0EzVUV3dVJHTDE3RFY1UXpIbWhac005Z2xMdnFLVGJacGh1T0NqMnBEUzByRk9XSXhaRjZLIiwidG9rZW5UeXBlIjoiYmVhcmVyIiwiZXhwIjoxNDkwMTk5MzI3LCJpcCI6IjIwNy4xNzMuMTY1LjUwIn0.qQu6NdsU4oVucv4uV_jusfL2HKgnPpfwF6iVG0H-P08akDtGgDoXcyVfl6hQdpVL9DGYVwvCPPUkLT0bJztM08lWhg69dVs-2e2I2BhjClsKeLsrFDBrUMwWVqqzCNVj8WBzcULLtl_mEgZc1qwVpZvXXiu0vmrRl3gtzVRaLL0", + "scope": "", + "expires_in": 1800, + "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI0OGJhNjJhNTQxNGFlODQ3OWJhMzA0MGQ1Mzc5NmY3MiIsImlhdCI6MTQ5MDE5NzUyNywiaXNzIjoib2F1dGgzLm9yZyIsImF1ZCI6Im9hdXRoMy5vcmciLCJhenAiOiJvYXV0aDMub3JnIiwic3ViIjoiIiwia2lkIjoib2F1dGgzLm9yZyIsInNjcCI6IiIsImFzIjoibG9naW4iLCJncnQiOiJwYXNzd29yZCIsInNydiI6ZmFsc2UsImsiOiJvYXV0aDMub3JnIiwiYXBwIjoib2F1dGgzLm9yZyIsImFjeCI6eyJpZCI6IjE1LUxhM3JnZXBFelBCR0xITHlrdEZOT1NDZFNVOXZJdjlKc2EzTkMxYVJUc3ZmUTZ5cDJuVFFfZWxmdkhzYTEifSwiYXhzIjpbXSwidXNyIjoiYTM3YWVkYTk5ZDQ5MThhMDM0YzM0MmQ2NGNkZjRiN2VkMjM0ZGZlNSIsImFjYyI6eyJpZCI6IjUzZTUwMTk2LTE4ZTMtNGJlNi04NDcyLTQ1ZDBjNDMxZjdhZCJ9LCJhY3MiOltdLCJpZHgiOiJuZnZ1bHRETE0tT0EzVUV3dVJHTDE3RFY1UXpIbWhac005Z2xMdnFLVGJacGh1T0NqMnBEUzByRk9XSXhaRjZLIiwicmVmcmVzaCI6dHJ1ZX0.QfufVyAGit2YOy9Hs9mv4eoCuyCYb9FDT_UXGd3JaFZe6MwqxLLnq2fWkkV2jgzDAK5t0JMu2Vk91jPP2IBXMkpZSzjaEKJ3-Eokb14Mo5GIrp54ndM20gWVZc-ReQtOUtSVG28bfnOBT5ceUM6SBrTxfz1ENOfmAiWl5591roQ", + "token": { + "jti": "396c32e7156b34b5ef5ef0ee8f97ccb3", + "iat": 1490197527, + "iss": "oauth3.org", + "aud": "oauth3.org", + "azp": "oauth3.org", + "sub": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1", + "kid": "oauth3.org", + "scp": "", + "as": "login", + "grt": "password", + "srv": false, + "k": "oauth3.org", + "app": "oauth3.org", + "acx": { + "id": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1" + }, + "axs": [], + "usr": "a37aeda99d4918a034c342d64cdf4b7ed234dfe5", + "acc": { + "id": "53e50196-18e3-4be6-8472-45d0c431f7ad" + }, + "acs": [], + "idx": "nfvultDLM-OA3UEwuRGL17DV5QzHmhZsM9glLvqKTbZphuOCj2pDS0rFOWIxZF6K", + "tokenType": "bearer", + "exp": 1490199327, + "ip": "207.173.165.50", + "client_uri": "oauth3.org", + "provider_uri": "https://oauth3.org" + }, + "refresh": { + "jti": "48ba62a5414ae8479ba3040d53796f72", + "iat": 1490197527, + "iss": "oauth3.org", + "aud": "oauth3.org", + "azp": "oauth3.org", + "sub": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1", + "kid": "oauth3.org", + "scp": "", + "as": "login", + "grt": "password", + "srv": false, + "k": "oauth3.org", + "app": "oauth3.org", + "acx": { + "id": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1" + }, + "axs": [], + "usr": "a37aeda99d4918a034c342d64cdf4b7ed234dfe5", + "acc": { + "id": "53e50196-18e3-4be6-8472-45d0c431f7ad" + }, + "acs": [], + "idx": "nfvultDLM-OA3UEwuRGL17DV5QzHmhZsM9glLvqKTbZphuOCj2pDS0rFOWIxZF6K", + "refresh": true, + "provider_uri": "https://oauth3.org" + } +} \ No newline at end of file diff --git a/oauth3.org.session.json b/oauth3.org.session.json new file mode 100644 index 0000000..a8c82f1 --- /dev/null +++ b/oauth3.org.session.json @@ -0,0 +1,66 @@ +{ + "provider_uri": "https://oauth3.org", + "client_uri": "oauth3.org", + "token_type": "bearer", + "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI4MmU5MDhlMTljMmIxM2IxNmM3N2JlMTNkMTljZmEzOSIsImlhdCI6MTQ5MDEzODg2MiwiaXNzIjoib2F1dGgzLm9yZyIsImF1ZCI6Im9hdXRoMy5vcmciLCJhenAiOiJvYXV0aDMub3JnIiwic3ViIjoiIiwia2lkIjoib2F1dGgzLm9yZyIsInNjcCI6IiIsImFzIjoibG9naW4iLCJncnQiOiJwYXNzd29yZCIsInNydiI6ZmFsc2UsImsiOiJvYXV0aDMub3JnIiwiYXBwIjoib2F1dGgzLm9yZyIsImFjeCI6eyJpZCI6IjE1LUxhM3JnZXBFelBCR0xITHlrdEZOT1NDZFNVOXZJdjlKc2EzTkMxYVJUc3ZmUTZ5cDJuVFFfZWxmdkhzYTEifSwiYXhzIjpbXSwidXNyIjoiYTM3YWVkYTk5ZDQ5MThhMDM0YzM0MmQ2NGNkZjRiN2VkMjM0ZGZlNSIsImFjYyI6eyJpZCI6IjUzZTUwMTk2LTE4ZTMtNGJlNi04NDcyLTQ1ZDBjNDMxZjdhZCJ9LCJhY3MiOltdLCJpZHgiOiJuZnZ1bHRETE0tT0EzVUV3dVJHTDE3RFY1UXpIbWhac005Z2xMdnFLVGJacGh1T0NqMnBEUzByRk9XSXhaRjZLIiwidG9rZW5UeXBlIjoiYmVhcmVyIiwiZXhwIjoxNDkwMTQwNjYyLCJpcCI6IjIwNy4xNzMuMTY1LjUwIn0.luWnALBIv9TD_mGHUIddRpOnbVAhkYO-DJtEQitODQX2IEC7cIcbSrvJBKI3i_djeMj69fm-ctr6XFUU7WiEVnBsMh55WK1gkdFqFzImo67apQ5kAV8GTGGbG___kisjl12AMvL09_shU1Sp8F8cHayTZTmSbyyWbbFKT3cZCsg", + "scope": "", + "expires_in": 1800, + "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJqdGkiOiI1ZDBjMGMyNTkyNmZhNmMxOTM0MjlhZWRkMjJjOTEyYiIsImlhdCI6MTQ5MDEzODg2MiwiaXNzIjoib2F1dGgzLm9yZyIsImF1ZCI6Im9hdXRoMy5vcmciLCJhenAiOiJvYXV0aDMub3JnIiwic3ViIjoiIiwia2lkIjoib2F1dGgzLm9yZyIsInNjcCI6IiIsImFzIjoibG9naW4iLCJncnQiOiJwYXNzd29yZCIsInNydiI6ZmFsc2UsImsiOiJvYXV0aDMub3JnIiwiYXBwIjoib2F1dGgzLm9yZyIsImFjeCI6eyJpZCI6IjE1LUxhM3JnZXBFelBCR0xITHlrdEZOT1NDZFNVOXZJdjlKc2EzTkMxYVJUc3ZmUTZ5cDJuVFFfZWxmdkhzYTEifSwiYXhzIjpbXSwidXNyIjoiYTM3YWVkYTk5ZDQ5MThhMDM0YzM0MmQ2NGNkZjRiN2VkMjM0ZGZlNSIsImFjYyI6eyJpZCI6IjUzZTUwMTk2LTE4ZTMtNGJlNi04NDcyLTQ1ZDBjNDMxZjdhZCJ9LCJhY3MiOltdLCJpZHgiOiJuZnZ1bHRETE0tT0EzVUV3dVJHTDE3RFY1UXpIbWhac005Z2xMdnFLVGJacGh1T0NqMnBEUzByRk9XSXhaRjZLIiwicmVmcmVzaCI6dHJ1ZX0.XljVX_QXgnYw8gyIZjQdxfyDlAAwWtU-kLitibw2_3xo9muLFPCL_dAk5XnMRygyyh5B9H4p4qB2Gb5BEJKJRfAtQ6TeZadTBtxwoY7zcns9f4Nx59VNii4k_Xp3uhJ6fQp8ERvkMgBy52Sj5ag0PFnuIwk35wLdSfiikDGnwKo", + "token": { + "jti": "82e908e19c2b13b16c77be13d19cfa39", + "iat": 1490138862, + "iss": "oauth3.org", + "aud": "oauth3.org", + "azp": "oauth3.org", + "sub": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1", + "kid": "oauth3.org", + "scp": "", + "as": "login", + "grt": "password", + "srv": false, + "k": "oauth3.org", + "app": "oauth3.org", + "acx": { + "id": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1" + }, + "axs": [], + "usr": "a37aeda99d4918a034c342d64cdf4b7ed234dfe5", + "acc": { + "id": "53e50196-18e3-4be6-8472-45d0c431f7ad" + }, + "acs": [], + "idx": "nfvultDLM-OA3UEwuRGL17DV5QzHmhZsM9glLvqKTbZphuOCj2pDS0rFOWIxZF6K", + "tokenType": "bearer", + "exp": 1490140662, + "ip": "207.173.165.50", + "client_uri": "oauth3.org", + "provider_uri": "https://oauth3.org" + }, + "refresh": { + "jti": "5d0c0c25926fa6c193429aedd22c912b", + "iat": 1490138862, + "iss": "oauth3.org", + "aud": "oauth3.org", + "azp": "oauth3.org", + "sub": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1", + "kid": "oauth3.org", + "scp": "", + "as": "login", + "grt": "password", + "srv": false, + "k": "oauth3.org", + "app": "oauth3.org", + "acx": { + "id": "15-La3rgepEzPBGLHLyktFNOSCdSU9vIv9Jsa3NC1aRTsvfQ6yp2nTQ_elfvHsa1" + }, + "axs": [], + "usr": "a37aeda99d4918a034c342d64cdf4b7ed234dfe5", + "acc": { + "id": "53e50196-18e3-4be6-8472-45d0c431f7ad" + }, + "acs": [], + "idx": "nfvultDLM-OA3UEwuRGL17DV5QzHmhZsM9glLvqKTbZphuOCj2pDS0rFOWIxZF6K", + "refresh": true, + "provider_uri": "https://oauth3.org" + } +} \ No newline at end of file