From 516eda4ea623a47ab314062e5faf36b9fe242c86 Mon Sep 17 00:00:00 2001 From: tigerbot Date: Tue, 1 Aug 2017 14:21:11 -0600 Subject: [PATCH] signing the token for the client in the browser --- oauth3.issuer.js | 113 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 95 insertions(+), 18 deletions(-) diff --git a/oauth3.issuer.js b/oauth3.issuer.js index 482e1a2..3a27402 100644 --- a/oauth3.issuer.js +++ b/oauth3.issuer.js @@ -437,6 +437,39 @@ OAUTH3.authz.grants = function (providerUri, opts) { }; }); }; +function calcExpiration(exp, now) { + if (!exp) { + return; + } + + if (typeof exp === 'string') { + var match = /^(\d+\.?\d*) *(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(exp); + if (!match) { + return now; + } + var num = parseFloat(match[1]); + var type = (match[2] || 's').toLowerCase()[0]; + switch (type) { + case 'y': num *= 365.25; /* falls through */ + case 'd': num *= 24; /* falls through */ + case 'h': num *= 60; /* falls through */ + case 'm': num *= 60; /* falls through */ + case 's': exp = num; + } + } + if (typeof exp !== 'number') { + throw new Error('invalid expiration provided: '+exp); + } + + now = now || Math.floor(Date.now() / 1000); + if (exp > now) { + return exp; + } else if (exp > 31557600) { + console.warn('tried to set expiration to more that a year'); + exp = 31557600; + } + return now + exp; +} OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, scopes) { if (!OAUTH3.url.checkRedirect(clientParams.client_uri, clientParams)) { return; @@ -466,25 +499,66 @@ OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, s } return prom.then(function () { - return OAUTH3.discover(providerUri, { client_id: providerUri, debug: clientParams.debug }); - }).then(function (directive) { - return OAUTH3.request(OAUTH3.urls.clientToken(directive, { - method: 'POST' - , session: session - , referrer: clientParams.referrer - , response_type: clientParams.response_type - , client_id: clientParams.client_uri - , azp: clientParams.client_uri - , aud: clientParams.aud - , exp: clientParams.exp - , refresh_token: clientParams.refresh_token - , refresh_exp: clientParams.refresh_exp - , debug: clientParams.debug - })); - }).then(function (results) { + return OAUTH3.hooks.keyPairs.get(session.token.sub); + }).then(function (keyPair) { + if (!keyPair) { + return OAUTH3.discover(providerUri, { + client_id: providerUri + , debug: clientParams.debug + }).then(function (directive) { + return OAUTH3.request(OAUTH3.urls.clientToken(directive, { + method: 'POST' + , session: session + , referrer: clientParams.referrer + , response_type: clientParams.response_type + , client_id: clientParams.client_uri + , azp: clientParams.client_uri + , aud: clientParams.aud + , exp: clientParams.exp + , refresh_token: clientParams.refresh_token + , refresh_exp: clientParams.refresh_exp + , debug: clientParams.debug + })).then(function (result) { + return result.originalData || result.data; + }); + }); + } + + return OAUTH3.hooks.grants.get(keyPair.sub, clientParams.client_uri).then(function (grant) { + var now = Math.floor(Date.now()/1000); + var payload = { + iat: now + , iss: providerUri + , aud: clientParams.aud || providerUri + , azp: clientParams.client_uri + , sub: grant.azpSub + , scope: OAUTH3.scope.stringify(grant.scope) + , }; + + var signProms = []; + signProms.push(OAUTH3.jwt.sign(Object.assign({ + exp: calcExpiration(clientParams.exp || '1h', now) + }, payload))); + // if (clientParams.refresh_token) { + signProms.push(OAUTH3.jwt.sign(Object.assign({ + exp: calcExpiration(clientParams.refresh_exp, now) + }, payload))); + // } + return OAUTH3.PromiseA.all(signProms).then(function (tokens) { + return { + access_token: tokens[0] + , refresh_token: tokens[1] + , scope: OAUTH3.scope.stringify(grant.scope) + , token_type: 'bearer' + }; + }); + }); + }).then(function (session) { // TODO limit refresh token to an expirable token // TODO inform client not to persist token - OAUTH3.url.redirect(clientParams, scopes, results.originalData || results.data); + OAUTH3.url.redirect(clientParams, scopes, session); + }, function (err) { + OAUTH3.url.redirect(clientParams, scopes, {error: err}); }); }; @@ -650,12 +724,15 @@ OAUTH3.hooks.session.get = function (providerUri, id) { return null; } + var now = Math.floor(Date.now()/1000); var payload = { - iss: providerUri + iat: now + , iss: providerUri , aud: providerUri , azp: providerUri , sub: pair.sub || id , scope: '' + , exp: now + 3600 }; return OAUTH3.jwt.sign(payload, pair.privateKey).then(function (token) { return OAUTH3.hooks.session.refresh(