diff --git a/README.md b/README.md index 5eda2ef..7026037 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,88 @@ oauth3.js ========= +The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation +(Yes! works in browsers and node.js with no extra dependencies or bloat and no hacks!) + +Instead of bloating your webapp and ruining the mobile experience, +you can use a single, small javascript file for all OAuth3 providers +(and almost all OAuth2 providers) with a seemless experience. + +Also, instead of complicated (or worse - insecure) CLI and Desktop login methods, +you can easily integrate an OAuth3 flow (or broker) into any node.js app (i.e. Electron, Node-Webkit) +with 0 pain. + +Installation +------------ + +**Easy Install** for Web Apps (including Mobile): + +1. In your web site / web app folder create a folder called `assets` +2. Inside of `assets` create another folder called `org.oauth3` +3. Download [oauth.js-v1.zip](https://git.daplie.com/Daplie/oauth3.js/repository/archive.zip?ref=v1) +4. Double-click to unzip the folder. +5. Copy `oauth3.js` and `oauth3.browser.js` to `assets/org.oauth3` + +**Advanced Installation with `git`** + +``` +# Navigate to your web site or web app +pushd /path/to/your/web/app + + +# clone the project as assets/org.oauth3 +mkdir -p assets +git clone git@git.daplie.com:Daplie/oauth3.js.git assets/org.oauth3 +pushd assests/org.oauth3 +git checkout v1 +popd + + +# symlink `.well-known/oauth3` to `assets/org.oauth3/.well-known/oauth3` +mkdir -p .well-known +ln -sf ../assets/org.oauth3/.well-known/oauth3 .well-known/oauth3 +``` + +**Advanced Installation with `bower`** + +``` +# Install to bower_components +bower install oauth3 + + +# create a `.well-known` folder and an `assets` folder +mkdir -p .well-known assets + + +# symlink `.well-known/oauth3` to `bower_components/oauth3/.well-known/oauth3` +ln -sf ../bower_components/oauth3/.well-known/oauth3 .well-known/oauth3 + + +# symlink `assets/org.oauth3` to `bower_components/oauth3` +ln -sf ../bower_components/oauth3/.well-known/oauth3 .well-known/oauth3 +ln -sf ../bower_components/oauth3 assets/org.oauth3 +``` + +Usage +----- + +Update your HTML to include the the following script tags: + +``` + + +``` + +If you use jQuery you should also include + +``` + +``` + + +Stable API +---------- + Public utilities for browser and node.js: * `querystringify(query)` @@ -14,6 +96,25 @@ URL generation: * `loginCode` * `resourceOwnerPassword` +Roadmap +------- + +* v1.0 - "implicit grant" authorization with examples + * popup + * iframe + * documentation +* v1.1 - cleanup + * in-flow discovery + * smallest possible size + * inline windowing (non-promisable callback) + * async set/get + * logout +* v1.2 - features + * "authorization code" flow + * "broker" flow +* v1.3 - features + * remove grants + URI vs URL ---------- diff --git a/oauth3.browser.js b/oauth3.browser.js index ddc512c..7805971 100644 --- a/oauth3.browser.js +++ b/oauth3.browser.js @@ -13,7 +13,8 @@ } var browser = exports.OAUTH3_BROWSER = { - clientUri: function (location) { + window: window + , clientUri: function (location) { return OAUTH3_CORE.normalizeUri(location.host + location.pathname); } , discover: function (providerUri, opts) { @@ -133,12 +134,21 @@ , frameRequest: function (url, state, opts) { var promise; - if ('background' === opts.type) { + if (!opts.windowType) { + opts.windowType = 'popup'; + } + + if ('background' === opts.windowType) { promise = browser.insertIframe(url, state, opts); - } else if ('popup' === opts.type) { + } else if ('popup' === opts.windowType) { promise = browser.openWindow(url, state, opts); + } else if ('inline' === opts.windowType) { + // callback function will never execute and would need to redirect back to current page + // rather than the callback.html + url += '&original_url=' + browser.window.location.href; + promise = browser.window.location = url; } else { - throw new Error("login framing method not specified or not type yet implemented"); + throw new Error("login framing method options.windowType not specified or not type yet implemented"); } return promise.then(function (params) { @@ -254,7 +264,7 @@ // // Logins // - , requests: { + , authn: { authorizationRedirect: function (providerUri, opts) { // TODO get own directives @@ -483,14 +493,14 @@ , code: data.code - , access_token: data.accessToken - , expires_at: data.expiresAt - , expires_in: data.expiresIn + , access_token: data.access_token + , expires_at: data.expires_at + , expires_in: data.expires_in , scope: data.scope - , refresh_token: data.refreshToken - , refresh_expires_at: data.refreshExpiresAt - , refresh_expires_in: data.refreshExpiresIn + , refresh_token: data.refresh_token + , refresh_expires_at: data.refresh_expires_at + , refresh_expires_in: data.refresh_expires_in }); if ('token' === scope.appQuery.response_type) { @@ -535,6 +545,7 @@ }, 50); } }; + browser.requests = browser.authn; Object.keys(browser).forEach(function (key) { if ('requests' === key) { diff --git a/oauth3.core.provider.js b/oauth3.core.provider.js index 86ddfeb..4626d37 100644 --- a/oauth3.core.provider.js +++ b/oauth3.core.provider.js @@ -233,7 +233,7 @@ console.log(grantResults); if (grantResults.data.error) { - window.alert('grantResults: ' + grantResults.data.errorDescription || grantResults.data.error.message); + window.alert('grantResults: ' + grantResults.data.error_description || grantResults.data.error.message); return; } diff --git a/oauth3.js b/oauth3.js index 972095c..3406c05 100644 --- a/oauth3.js +++ b/oauth3.js @@ -27,6 +27,7 @@ }; // TODO move recase out + /* oauth3._recaseRequest = function (recase, req) { // convert JavaScript camelCase to oauth3/ruby snake_case if (req.data && 'object' === typeof req.data) { @@ -44,6 +45,7 @@ } return resp; }; + */ oauth3.hooks = { checkSession: function (preq, opts) { @@ -193,9 +195,9 @@ // TODO simplify (nix recase) oauth3.provideRequest = function (rawRequest, opts) { opts = opts || {}; - var Recase = exports.Recase || require('recase'); + //var Recase = exports.Recase || require('recase'); // TODO make insensitive to providing exceptions - var recase = Recase.create({ exceptions: {} }); + //var recase = Recase.create({ exceptions: {} }); function lintAndRequest(preq) { function goGetHer() { @@ -236,9 +238,10 @@ return lintAndRequest(req, opts); } - req = oauth3._recaseRequest(recase, req); + //req = oauth3._recaseRequest(recase, req); return lintAndRequest(req, opts).then(function (res) { - return oauth3._recaseResponse(recase, res); + //return oauth3._recaseResponse(recase, res); + return res; }); }; @@ -295,10 +298,10 @@ var prequest = core.urls.loginCode(directive, opts); return oauth3.request(prequest).then(function (res) { - // result = { uuid, expiresAt } + // result = { uuid, expires_at } return { otpUuid: res.data.uuid - , otpExpires: res.data.expiresAt + , otpExpires: res.data.expires_at }; }); });