From ea788bcb7631bf39a0c3c71683bdf5a8ae3943d8 Mon Sep 17 00:00:00 2001 From: tigerbot Date: Mon, 3 Jul 2017 12:26:12 -0600 Subject: [PATCH 1/6] reduced duplicate parsing of location --- js/issuer.js | 63 +++++++++++++++++++++------------------------------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/js/issuer.js b/js/issuer.js index 08c630b..bc575d2 100644 --- a/js/issuer.js +++ b/js/issuer.js @@ -9,7 +9,7 @@ $(function () { var OAUTH3 = window.OAUTH3; var CONFIG = { - host: OAUTH3.utils.clientUri(window.location) + host: OAUTH3.clientUri(window.location) , directives: null // will be populated before the login button appears }; var loc = window.location; @@ -20,10 +20,6 @@ $(function () { }; $('.js-scopes-container').html(''); - /* - OAUTH3._hooks.sessions.all = function (providerUri) { - }; - */ OAUTH3._hooks = { sessions: {} }; OAUTH3._hooks.sessions.get = function (providerUri, id) { return JSON.parse(window.localStorage.getItem('session-' + providerUri + (id || '')) || 'null'); @@ -35,7 +31,7 @@ $(function () { }; // TODO let query.parse do location.hash || location.search || location - var clientParams = OAUTH3.query.parse(window.location.hash || window.location.search); + var clientParams = OAUTH3.query.parse(loc.hash || loc.search); if (/authorization_dialog/.test(window.location.href)) { // OAUTH3.lintClientParams(params, window) // OAUTH3.normalizeClientParams(params, window) @@ -58,12 +54,12 @@ $(function () { + "'" + OAUTH3.url.normalize(window.document.referrer) + "'" ); } - if (clientParams.client_uri) { + if (clientParams.client_uri && clientParams.client_uri !== clientParams.client_id) { console.warn("'client_id' should be used instead of 'client_uri'"); } if (!(clientParams.client_id || clientParams.client_uri)) { - window.alert("'response_type' must exist and be either 'token' (implicit flow) or 'code' (authorization flow)"); - console.error("'response_type' must exist and be either 'token' (implicit flow) or 'code' (authorization flow)"); + window.alert("'client_id' must exist as the uri identifying the client"); + console.error("'client_id' must exist as the uri identifying the client"); clientParams.client_id = clientParams.client_uri = OAUTH3.url.normalize(window.document.referrer); } if (!clientParams.redirect_uri) { @@ -99,11 +95,10 @@ $(function () { } function getGrants(session) { - var clientObj = OAUTH3.query.parse(loc.hash || loc.search); - var clientLogo = OAUTH3.url.normalize(clientObj.client_uri) // optional relative logo ? + var clientLogo = OAUTH3.url.normalize(clientParams.client_uri) // optional relative logo ? + '/.well-known/oauth3/logo-128x128.png' ; - var callbackUrl; + // TODO put in directives.json or similar var grantDescriptions = { 'oauth3_authn': "Basic secure authentication" @@ -127,10 +122,10 @@ $(function () { $('.js-client-logo').attr('src', clientLogo); //$('.js-user-avatar').attr('src', userAvatar); - return OAUTH3.authz.scopes(CONFIG.host, session, clientObj).then(function (scopes) { + return OAUTH3.authz.scopes(CONFIG.host, session, clientParams).then(function (scopes) { if (!scopes.pending.length) { // looks like we've done all of this before - OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientObj, scopes); + OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientParams, scopes); return; } @@ -138,10 +133,12 @@ $(function () { // TODO secure iFrame from click-jacking by requiring input? // ex: input.security-code[type="text"].val(Math.random()); input.js-verify-code[placeholder="Type what you see"] if (OAUTH3._browser.isIframe()) { - callbackUrl = clientObj.redirect_uri + '#state=' + clientObj.state + '&error=access_denied&error_description=' - + encodeURIComponent("You're requesting permission in an iframe, but the permissions have not yet been granted") - + '&error_uri=' + encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED'); - location.href = callbackUrl; + location.href = clientParams.redirect_uri +'#'+ OAUTH3.query.stringify({ + state: clientParams.state + , error: 'access_denied' + , error_description: encodeURIComponent("You're requesting permission in an iframe, but the permissions have not yet been granted") + , error_uri: encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED') + }); return; } @@ -331,8 +328,6 @@ $(function () { }); getSession(CONFIG.host).then(function (session) { - var clientParams = OAUTH3.query.parse(loc.hash || loc.search); - return OAUTH3.authz.scopes(CONFIG.host, session, clientParams).then(function (scopes) { scopes.new = acceptedScopes; return OAUTH3.authz.redirectWithToken(CONFIG.host, session, clientParams, scopes); @@ -346,21 +341,17 @@ $(function () { ev.preventDefault(); ev.stopPropagation(); - var loginWinObj = OAUTH3.query.parse(loc.hash || loc.search); - var denyObj = { error: 'access_denied' , error_description: 'The user has denied access.' , error_uri: 'https://' + CONFIG.host + '/.well-known/oauth3/errors.html#/?error=access_denied' - , state: loginWinObj.state - , scope: loginWinObj.scope + , state: clientParams.state + , scope: clientParams.scope }; - window.location = loginWinObj.redirect_uri + '#' + OAUTH3.query.stringify(denyObj); + window.location = clientParams.redirect_uri + '#' + OAUTH3.query.stringify(denyObj); }; util.handleLogout = function () { - var clientParams = OAUTH3.query.parse(loc.hash || loc.search); - localStorage.clear(); clientParams.redirect_uri += '?' + OAUTH3.query.stringify({ @@ -397,16 +388,17 @@ $(function () { return getSession(CONFIG.host).then(function (session) { return getGrants(session); }, function (e) { - var clientObj = OAUTH3.query.parse(loc.hash || loc.search); // TODO select the providers the client wants to show // providers=daplie.com,facebook.com,google.com // etc // TODO let the client specify switch_user // TODO let the client specify relogin if stale if (OAUTH3._browser.isIframe()) { - var callbackUrl = clientObj.redirect_uri + '#state=' + clientObj.state + '&error=access_denied&error_description=' - + encodeURIComponent("You're requesting permission in an iframe, but the user is not yet authenticated") - + '&error_uri=' + encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED'); - location.href = callbackUrl; + location.href = clientParams.redirect_uri +'#'+ OAUTH3.query.stringify({ + state: clientParams.state + , error: 'access_denied' + , error_description: encodeURIComponent("You're requesting permission in an iframe, but the user is not yet authenticated") + , error_uri: encodeURIComponent('https://oauth3.org/docs/errors/#E_IFRAME_DENIED') + }); } if (clientParams.subject) { $('.js-oauth3-email').val(clientParams.subject); @@ -419,10 +411,7 @@ $(function () { } // Session initialization - return OAUTH3.discover( - OAUTH3.clientUri(window.location) - , { client_uri: OAUTH3.clientUri(window.location) } - ).then(function (directives) { + return OAUTH3.discover(CONFIG.host, { client_uri: CONFIG.host }).then(function (directives) { // TODO cache directives in memory (and storage) CONFIG.directives = directives; directives.issuer = directives.issuer || (window.location.host + window.location.pathname).replace(/\/$/, ''); @@ -439,7 +428,5 @@ $(function () { } $('body').addClass('in'); - }); - }); From cd1ff73eeaa5552265dceb6155eb99f980dfc731 Mon Sep 17 00:00:00 2001 From: tigerbot Date: Mon, 3 Jul 2017 12:45:21 -0600 Subject: [PATCH 2/6] handled case of un-refreshable saved session --- js/issuer.js | 52 +++++++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/js/issuer.js b/js/issuer.js index bc575d2..549b546 100644 --- a/js/issuer.js +++ b/js/issuer.js @@ -171,9 +171,6 @@ $(function () { }); $('.js-authz').show().addClass('in'); - }, function (err) { - window.alert('grantResults: ' + err.message); - console.error('scope results', err); }); } @@ -283,35 +280,31 @@ $(function () { , expire: opts.rememberDevice || (1 * 60 * 60 * 1000) , mock: true }).then(function (session) { - $('.js-authn').removeClass('in').hide(); - - function getAccount(session) { - if (session.token.sub) { - return OAUTH3.PromiseA.resolve(session); - } - - return OAUTH3.requests.accounts.create(CONFIG.directives, session, { - display_name: email.replace(/@.*/, '') - , comment: "created for '" + email + "' by '" + CONFIG.host + "'" - , priority: 1000 // default priority for first account - , name: undefined // TODO we could ask in the UI - }).then(function (resp) { - var results = resp.data; - return OAUTH3.hooks.session.refresh(session, { - access_token: (results.access_token || results.accessToken) - , refresh_token: (results.refresh_token || results.refreshToken) - }); - }); + if (session.token.sub) { + return OAUTH3.PromiseA.resolve(session); } - return getAccount(session).then(function () { - return getGrants(session); + return OAUTH3.requests.accounts.create(CONFIG.directives, session, { + display_name: email.replace(/@.*/, '') + , comment: "created for '" + email + "' by '" + CONFIG.host + "'" + , priority: 1000 // default priority for first account + , name: undefined // TODO we could ask in the UI + }).then(function (resp) { + var results = resp.data; + return OAUTH3.hooks.session.refresh(session, { + access_token: (results.access_token || results.accessToken) + , refresh_token: (results.refresh_token || results.refreshToken) + }); + }); + }).then(function (session) { + return getGrants(session).catch(function (err) { + window.alert('grantResults: ' + err.message); + console.error('scope results', err); }); }, function (error) { $('.error-msg').text('Incorrect code'); }); - }; util.acceptScopesAndLogin = function (ev) { ev.preventDefault(); @@ -371,6 +364,8 @@ $(function () { // // Page Setup // + $('.js-authorization-dialog').hide(); + $('.js-logout-container').hide(); $('.js-userid-container').hide(); $('.js-authn').hide(); $('.js-authz').hide(); @@ -387,7 +382,7 @@ $(function () { function handleAuthorizationDialog() { return getSession(CONFIG.host).then(function (session) { return getGrants(session); - }, function (e) { + }).catch(function () { // TODO select the providers the client wants to show // providers=daplie.com,facebook.com,google.com // etc // TODO let the client specify switch_user @@ -405,8 +400,6 @@ $(function () { $('.js-authn-show').prop('disabled', false); } $('.js-userid-container').show(); - }).then(function () { - //$('body').addClass('in'); }); } @@ -416,9 +409,6 @@ $(function () { CONFIG.directives = directives; directives.issuer = directives.issuer || (window.location.host + window.location.pathname).replace(/\/$/, ''); - $('.js-authorization-dialog').hide(); - $('.js-logout-container').hide(); - if (/authorization_dialog/.test(window.location.href)) { $('.js-authorization-dialog').show(); handleAuthorizationDialog(); From 7902dea5f3b1ae9cba3379fefcaf2e51c5abb265 Mon Sep 17 00:00:00 2001 From: tigerbot Date: Wed, 26 Jul 2017 18:16:30 -0600 Subject: [PATCH 3/6] removed useless check for account existence --- js/issuer.js | 51 +++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/js/issuer.js b/js/issuer.js index 549b546..31d29bb 100644 --- a/js/issuer.js +++ b/js/issuer.js @@ -84,13 +84,13 @@ $(function () { function getSession(providerUri) { return OAUTH3.hooks.session.get(providerUri).then(function (session) { - if (session && session.access_token) { - normalizeSession(session); - return OAUTH3.PromiseA.resolve(session); - } - else { - return OAUTH3.PromiseA.reject(new Error("no access_token in session")); - } + if (session && session.access_token) { + normalizeSession(session); + return OAUTH3.PromiseA.resolve(session); + } + else { + return OAUTH3.PromiseA.reject(new Error("no access_token in session")); + } }); } @@ -206,34 +206,20 @@ $(function () { // TODO loading email = $('.js-oauth3-email').val(); - return OAUTH3.authn.loginMeta(CONFIG.directives, {email: email, mock: true}).then(function (userResults) { - if (!userResults.data.error) { - console.log('User exists:', userResults); + return OAUTH3.authn.otp(CONFIG.directives, {email: email, mock: true}).then(function (otpResults) { + + if (otpResults.data.error) { + window.alert('otpResults: ' + otpResults.data.error_description || otpResults.data.error.message); + return; } - if (userResults.data.error) { - $('.js-authn-show').removeAttr('disabled'); - console.warn('User does not exist:', email); - console.warn('User Results:', userResults); - //window.alert('userResults: ' + userResults.data.error_description || userResults.data.error.message); - //return; - } + var ua = window.navigator.userAgent; + $('.js-sniffed-device').text(ua); + $('.js-userid-container').removeClass('in').hide(); + $('.js-authn').show().addClass('in'); + $('.js-authn-otp-uuid').val(otpResults.data.uuid); - return OAUTH3.authn.otp(CONFIG.directives, {email: email, mock: true}).then(function (otpResults) { - - if (otpResults.data.error) { - window.alert('otpResults: ' + otpResults.data.error_description || otpResults.data.error.message); - return; - } - - var ua = window.navigator.userAgent; - $('.js-sniffed-device').text(ua); - $('.js-userid-container').removeClass('in').hide(); - $('.js-authn').show().addClass('in'); - $('.js-authn-otp-uuid').val(otpResults.data.uuid); - - $('.js-user-email').text(email); - }); + $('.js-user-email').text(email); }); }; util.rememberDevice = function (ev) { @@ -303,6 +289,7 @@ $(function () { console.error('scope results', err); }); }, function (error) { + console.error(error); $('.error-msg').text('Incorrect code'); }); }; From 8f30d80b380d75f2ebe74b7b086392a7aab1d1a2 Mon Sep 17 00:00:00 2001 From: tigerbot Date: Tue, 1 Aug 2017 11:39:20 -0600 Subject: [PATCH 4/6] changed how the "remember me" checkbox is handled --- index.html | 9 ++++----- js/issuer.js | 38 +++++--------------------------------- 2 files changed, 9 insertions(+), 38 deletions(-) diff --git a/index.html b/index.html index 51da29c..958781f 100644 --- a/index.html +++ b/index.html @@ -71,8 +71,7 @@ - - + @@ -146,11 +145,11 @@ + + + - - - diff --git a/js/issuer.js b/js/issuer.js index 31d29bb..f7f8f7b 100644 --- a/js/issuer.js +++ b/js/issuer.js @@ -20,16 +20,6 @@ $(function () { }; $('.js-scopes-container').html(''); - OAUTH3._hooks = { sessions: {} }; - OAUTH3._hooks.sessions.get = function (providerUri, id) { - return JSON.parse(window.localStorage.getItem('session-' + providerUri + (id || '')) || 'null'); - }; - OAUTH3._hooks.sessions.set = function (providerUri, newSession, id) { - window.localStorage.setItem('session-' + providerUri, JSON.stringify(newSession)); - window.localStorage.setItem('session-' + providerUri + (id || newSession.id || newSession.token.id || ''), JSON.stringify(newSession)); - return newSession; - }; - // TODO let query.parse do location.hash || location.search || location var clientParams = OAUTH3.query.parse(loc.hash || loc.search); if (/authorization_dialog/.test(window.location.href)) { @@ -222,26 +212,11 @@ $(function () { $('.js-user-email').text(email); }); }; - util.rememberDevice = function (ev) { - ev.preventDefault(); - ev.stopPropagation(); - - util.submitLoginCode({ - rememberDevice: true - }); - }; - util.rememberDeviceNot = function (ev) { - ev.preventDefault(); - ev.stopPropagation(); - - util.submitLoginCode({ - rememberDevice: false - }); - }; // Reference Implementation - - util.submitLoginCode = function (opts) { + util.submitLoginCode = function (ev) { + ev.preventDefault(); + ev.stopPropagation(); // TODO // perhaps we should check that the code is valid before continuing to login (so that we don't send the key) @@ -249,7 +224,6 @@ $(function () { // TODO // we should be sending the public key for this device as a jwk along with the authentication // (and how long to remember this device) - var uuid = $('.js-authn-otp-uuid').val(); var code = $('.js-authn-otp-code').val().trim(); return OAUTH3.authn.resourceOwnerPassword(CONFIG.directives, { @@ -263,7 +237,7 @@ $(function () { // TODO should be otp_id (agnostic of uuid) , otp_uuid: uuid // add expiration to the refresh token and/or public key - , expire: opts.rememberDevice || (1 * 60 * 60 * 1000) + , remember_device: $('.js-remember-label').find('.js-remember-checkbox').prop('checked') , mock: true }).then(function (session) { $('.js-authn').removeClass('in').hide(); @@ -344,7 +318,6 @@ $(function () { util.editEmail = function () { $('.js-authn').hide(); $('.js-userid-container').show(); - debugger; }; @@ -359,8 +332,7 @@ $(function () { $('body').on('click', '.js-logout', util.handleLogout); $('body').on('click', '.js-authn-show', util.submitAuthEmail); - $('body').on('click', '.js-authz-remember-me', util.rememberDevice); - $('body').on('click', '.js-authz-remember-me-not', util.rememberDeviceNot); + $('body').on('click', '.js-submit-code-btn', util.submitLoginCode); $('body').on('click', '.js-login-allow', util.acceptScopesAndLogin); $('body').on('click', '.js-login-deny', util.closeLoginDeny); $('body').on('click', '.js-edit-email-button', util.editEmail); From 7d18f05bafdf34cc7d6f1af60ec32d010f4d2641 Mon Sep 17 00:00:00 2001 From: aj Date: Tue, 15 Aug 2017 20:26:10 +0000 Subject: [PATCH 5/6] org.oauth3 -> oauth3.org --- README.md | 10 +++++----- index.html | 6 +++--- install.sh | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9e2c100..db7432b 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ This is a WALNUT module representing the html package for oauth3.org. -It must be installed to `/srv/walnut/packages/pages/org.oauth3` +It must be installed to `/srv/walnut/packages/pages/azp@oauth3.org` ```bash -git clone git@git.daplie.com:OAuth3/org.oauth3.git /srv/walnut/packages/pages/org.oauth3 -pushd /srv/walnut/packages/pages/org.oauth3 +git clone git@git.daplie.com:OAuth3/org.oauth3.git /srv/walnut/packages/pages/azp@oauth3.org +pushd /srv/walnut/packages/pages/azp@oauth3.org bash ./install.sh popd ``` ```bash -echo "org.oauth3" >> /srv/walnut/packages/sites/EXAMPLE.COM +echo "azp@oauth3.org" >> /srv/walnut/packages/sites/EXAMPLE.COM ``` -This uses the OAuth3 JavaScript SDK `oauth3.js` as a subpackage in `/srv/walnut/packages/pages/org.oauth3/assets/org.oauth3`. +This uses the OAuth3 JavaScript SDK `oauth3.js` as a subpackage in `/srv/walnut/packages/pages/azp@oauth3.org/assets/oauth3.org`. diff --git a/index.html b/index.html index 56604e6..90de3b5 100644 --- a/index.html +++ b/index.html @@ -145,9 +145,9 @@ - - - + + + diff --git a/install.sh b/install.sh index 13a4ae8..b76af65 100755 --- a/install.sh +++ b/install.sh @@ -2,13 +2,13 @@ set -e set -u -# git clone git@git.daplie.com:OAuth3/org.oauth3.git /srv/walnut/packages/pages/org.oauth3 +# git clone git@git.daplie.com:OAuth3/org.oauth3.git /srv/walnut/packages/pages/azp@oauth3.org mkdir -p assets -if ! [ -d ./assets/org.oauth3 ]; then - git clone git@git.daplie.com:OAuth3/oauth3.js.git ./assets/org.oauth3 +if ! [ -d ./assets/oauth3.org ]; then + git clone git@git.daplie.com:OAuth3/oauth3.js.git ./assets/oauth3.org fi -pushd ./assets/org.oauth3 +pushd ./assets/oauth3.org git checkout v1 git pull popd From cc066a0bcde23cb6cc4563a348cd32468f7978d7 Mon Sep 17 00:00:00 2001 From: aj Date: Tue, 15 Aug 2017 20:28:03 +0000 Subject: [PATCH 6/6] org.oauth3 -> oauth3.org --- .well-known/oauth3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.well-known/oauth3 b/.well-known/oauth3 index 585edad..51f73eb 120000 --- a/.well-known/oauth3 +++ b/.well-known/oauth3 @@ -1 +1 @@ -../assets/org.oauth3/.well-known/oauth3 \ No newline at end of file +../assets/oauth3.org/.well-known/oauth3 \ No newline at end of file