Compare commits

...

40 Commits
rpc ... master

Author SHA1 Message Date
291bfd6a79 retrieve signing key 2018-07-06 08:12:13 +00:00
def91fb60d fix url for validating token 2018-07-06 07:51:39 +00:00
738573a79c typo fix _providerUri => providerUri 2018-07-06 05:56:01 +00:00
58f245f90c typo auth => oauth3 2018-07-06 05:48:25 +00:00
c5735f402c add symlinks for back-compat 2018-07-06 04:55:52 +00:00
db43f09ce2 .well-known => _apis 2018-07-06 04:55:34 +00:00
e7ffe06d9d .well-known => _apis 2018-07-06 00:45:58 +00:00
3d9d7b00d7 update links 2018-04-23 22:10:10 +00:00
cf5c106f64 correct logout 2017-11-29 05:30:22 +00:00
f4b3dbd495 Merge branch 'v1.2-next' of git.oauth3.org:OAuth3/oauth3.js into v1.2-next 2017-11-29 05:13:53 +00:00
6f6d07e670 add navigator.auth api 2017-11-29 05:13:49 +00:00
23db17a31e accept scope as array, use scope as delimited string 2017-11-29 04:17:43 +00:00
d87645d135 oauth3_authn -> authn@oauth3.org 2017-11-29 02:12:39 +00:00
989dbfb150 Merge branch 'v1.2-next' of git.oauth3.org:OAuth3/oauth3.js into v1.2-next 2017-11-29 02:09:39 +00:00
36fe8e2a80 default scope changed to authn@oauth3.org 2017-11-29 02:09:19 +00:00
ff6d9665e2 default broker is new.oauth3.org 2017-11-29 02:09:00 +00:00
2587d03860 fix trailing slash 2017-11-28 02:26:31 +00:00
f14f42404e Merge branch 'v1.2' into v1.2-next 2017-11-28 01:25:00 +00:00
0aa85baf6d Merge branch 'v1.2-next' of git.oauth3.org:OAuth3/oauth3.js into v1.2-next 2017-11-25 09:11:01 +00:00
39c0c775ed get issuer via rpc 2017-11-25 09:10:54 +00:00
2bfc752ea1 Merge branch 'rpc' into v1.2-next 2017-11-25 08:59:15 +00:00
18170e94f4 Merge remote-tracking branch 'origin/rpc' into v1.2-next 2017-11-25 08:39:37 +00:00
ff76a4116e Merge branch 'rpc' into v1.2-next 2017-11-25 08:32:39 +00:00
d84b7bd6ea Merge branch 'rpc' into v1.2-next 2017-11-25 08:28:46 +00:00
687391e56b Merge branch 'rpc' into v1.2-next 2017-11-25 08:21:45 +00:00
9f48a44958 merge rpc 2017-11-25 08:15:44 +00:00
77c64df163 Merge branch 'discover-pixel' into v1.2-next 2017-11-24 01:28:23 +00:00
fcca994c65 fix parseSubject 2017-11-24 01:27:24 +00:00
e27af15485 Merge branch 'no-timeout' into v1.2-next 2017-11-24 01:00:20 +00:00
c59e23d114 Merge branch 'no-timeout' of OAuth3/oauth3.js into v1.2 2017-11-24 01:00:06 +00:00
6225b1e2fe better error message 2017-11-24 00:59:37 +00:00
9298776620 ws 2017-11-24 00:50:26 +00:00
2c0b757c13 no timeout 2017-11-24 00:49:35 +00:00
f6017e7e49 test oauth3 support via pixel 2017-11-23 07:25:35 +00:00
4da61d835e add clear.gif 2017-11-23 07:23:44 +00:00
215d3f0e92 add blank.gif 2017-11-23 03:14:00 +00:00
tigerbot
9ac5c3ed89 Merge remote-tracking branch 'origin/v1.2' 2017-11-17 12:42:00 -07:00
c2ec21c446 update accounts apis 2017-11-17 06:10:25 +00:00
a7a9a16847 Merge branch 'v1.2' 2017-11-16 20:46:38 +00:00
82ed16e162 don't overwrite existing authn 2017-11-16 20:41:50 +00:00
13 changed files with 319 additions and 129 deletions

View File

@ -1 +1 @@
well-known _apis

View File

@ -5,7 +5,7 @@ oauth3.js
| [issuer.html](https://git.oauth3.org/OAuth3/issuer.html) | [issuer.html](https://git.oauth3.org/OAuth3/issuer.html)
| [issuer.rest.walnut.js](https://git.oauth3.org/OAuth3/issuer.rest.walnut.js) | [issuer.rest.walnut.js](https://git.oauth3.org/OAuth3/issuer.rest.walnut.js)
| [issuer.srv](https://git.oauth3.org/OAuth3/issuer.srv) | [issuer.srv](https://git.oauth3.org/OAuth3/issuer.srv)
| Sponsored by [Daplie](https://daplie.com) | Sponsored by [ppl](https://ppl.family)
The world's smallest, fastest, and most secure OAuth3 (and OAuth2) JavaScript implementation 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!) (Yes! works in browsers and node.js with no extra dependencies or bloat and no hacks!)
@ -29,8 +29,7 @@ If you have no idea what you're doing
4. Download [oauth3.js-v1.zip](https://git.oauth3.org/OAuth3/oauth3.js/repository/archive.zip?ref=v1) 4. Download [oauth3.js-v1.zip](https://git.oauth3.org/OAuth3/oauth3.js/repository/archive.zip?ref=v1)
5. Double-click to unzip the folder. 5. Double-click to unzip the folder.
6. Copy the file `oauth3.core.js` into the folder `example.com/assets/oauth3.org/` 6. Copy the file `oauth3.core.js` into the folder `example.com/assets/oauth3.org/`
7. Copy the folder `well-known` into the folder `example.com/` 7. Copy the folder `_apis` into the folder `example.com/`
8. Rename the folder `well-known` to `.well-known` (when you do this, it become invisible, that's okay)
9. Add `<script src="assets/oauth3.org/oauth3.core.js"></script>` to your `index.html` 9. Add `<script src="assets/oauth3.org/oauth3.core.js"></script>` to your `index.html`
9. Add `<script src="app.js"></script>` to your `index.html` 9. Add `<script src="app.js"></script>` to your `index.html`
10. Create files in `example.com` called `app.js` and `index.html` and put this in it: 10. Create files in `example.com` called `app.js` and `index.html` and put this in it:
@ -59,13 +58,13 @@ If you have no idea what you're doing
`app.js`: `app.js`:
```js ```js
var OAUTH3 = window.OAUTH3; var OAUTH3 = window.OAUTH3;
var auth = OAUTH3.create(window.location); // use window.location to set Client URI (your app's id) var oauth3 = OAUTH3.create(window.location); // use window.location to set Client URI (your app's id)
// this is any OAuth3-compatible provider, such as oauth3.org // this is any OAuth3-compatible provider, such as oauth3.org
// in v1.1.0 we'll add backwards compatibility for facebook.com, google.com, etc // in v1.1.0 we'll add backwards compatibility for facebook.com, google.com, etc
// //
function onChangeProvider(_providerUri) { function onChangeProvider(providerUri) {
// example https://oauth3.org // example https://oauth3.org
return oauth3.setIdentityProvider(providerUri); return oauth3.setIdentityProvider(providerUri);
} }
@ -87,11 +86,13 @@ function onClickLogin() {
console.info('Secure PPID (aka subject):', session.token.sub); console.info('Secure PPID (aka subject):', session.token.sub);
return oauth3.request({ return oauth3.request({
url: 'https://oauth3.org/api/issuer@oauth3.org/inspect' url: 'https://api.oauth3.org/api/issuer@oauth3.org/jwks/:sub/:kid'
.replace(/:sub/g, session.token.sub)
.replace(/:kid/g, session.token.kid || session.token.iss)
, session: session , session: session
}).then(function (resp) { }).then(function (resp) {
console.info("Inspect Token:"); console.info("Signing Public Key JWK:");
console.log(resp.data); console.log(resp.data);
}); });
@ -144,13 +145,13 @@ it might look like this:
example.com example.com
├── .well-known (hidden) ├── _apis
│   └── oauth3 │   └── oauth3.org
│   ├── callback.html │   ├── callback.html
│   ├── directives.json │   ├── directives.json
│   └── index.html │   └── index.html
├── assets ├── assets
│   └── org.oauth3 │   └── oauth3.org
│   └── oauth3.core.js │   └── oauth3.core.js
@ -171,17 +172,17 @@ Installation (if you know what you're doing)
pushd /path/to/your/web/app pushd /path/to/your/web/app
# clone the project as assets/org.oauth3 # clone the project as assets/oauth3.org
mkdir -p assets mkdir -p assets
git clone git@git.daplie.com:OAuth3/oauth3.js.git assets/org.oauth3 git clone git@git.oauth3.org:OAuth3/oauth3.js.git assets/oauth3.org
pushd assets/org.oauth3 pushd assets/oauth3.org
git checkout v1 git checkout v1
popd popd
# symlink `.well-known/oauth3` to `assets/org.oauth3/.well-known/oauth3` # symlink `_apis/oauth3.org` to `assets/oauth3.org/_apis/oauth3.org`
mkdir -p .well-known mkdir -p _apis
ln -sf ../assets/org.oauth3/.well-known/oauth3 .well-known/oauth3 ln -sf ../assets/oauth3.org/_apis/oauth3 _apis/oauth3.org
``` ```
**Advanced Installation with `bower`** **Advanced Installation with `bower`**
@ -191,17 +192,17 @@ ln -sf ../assets/org.oauth3/.well-known/oauth3 .well-known/oauth3
bower install oauth3 bower install oauth3
# create a `.well-known` folder and an `assets` folder # create a `_apis` folder and an `assets` folder
mkdir -p .well-known assets mkdir -p _apis assets
# symlink `.well-known/oauth3` to `bower_components/oauth3/.well-known/oauth3` # symlink `_apis/oauth3.org` to `bower_components/oauth3.org/_apis/oauth3.org`
ln -sf ../bower_components/oauth3/.well-known/oauth3 .well-known/oauth3 ln -sf ../bower_components/oauth3.org/_apis/oauth3.org _apis/oauth3.org
# symlink `assets/org.oauth3` to `bower_components/oauth3` # symlink `assets/oauth3.org` to `bower_components/oauth3.org`
ln -sf ../bower_components/oauth3/.well-known/oauth3 .well-known/oauth3 ln -sf ../bower_components/oauth3.org/_apis/oauth3.org _apis/oauth3.org
ln -sf ../bower_components/oauth3 assets/org.oauth3 ln -sf ../bower_components/oauth3.org assets/oauth3.org
``` ```
Usage Usage
@ -210,7 +211,7 @@ Usage
Update your HTML to include the the following script tag: Update your HTML to include the the following script tag:
```html ```html
<script src="assets/org.oauth3/oauth3.core.js"></script> <script src="assets/oauth3.org/oauth3.core.js"></script>
``` ```
You can create a very simple demo application like this: You can create a very simple demo application like this:
@ -289,7 +290,7 @@ You're all set. Nothing else is needed.
We've created an `Oauth3` service just for you: We've created an `Oauth3` service just for you:
```html ```html
<script src="assets/org.oauth3/oauth3.ng.js"></script> <script src="assets/oauth3.org/oauth3.ng.js"></script>
``` ```
```js ```js
@ -322,7 +323,7 @@ promise = oauth3.init(opts); // set and fetch your own si
// promises your site's config // opts = { location, session, issuer, audience } // promises your site's config // opts = { location, session, issuer, audience }
promise = oauth3.setIdentityProvider(url); // changes the Identity Provider URI (the site you're logging into), promise = oauth3.setIdentityProvider(url); // changes the Identity Provider URI (the site you're logging into),
// promises the provider's config // gets the config for that site (from their .well-known/oauth3), // promises the provider's config // gets the config for that site (from their _apis/oauth3.org),
// and caches it in internal state as the default // and caches it in internal state as the default
promise = oauth3.setResourceProvider(url); // changes the Resource Provider URI (the site you're getting stuff from) promise = oauth3.setResourceProvider(url); // changes the Resource Provider URI (the site you're getting stuff from)
@ -339,12 +340,11 @@ promise = oauth3.request({ url, method, data }); // make an (authorized) arbi
// (contacts, photos, whatever) // (contacts, photos, whatever)
promise = oauth3.api(apiname, opts); // make an (authorized) well-known api call to an audience promise = oauth3.api(apiname, opts); // make an (authorized) well-known api call to an audience
// See https://labs.daplie.com/docs/ for API schemas // Ex: oauth3.api('dns.list', { sld: 'example', tld: 'com' });
// Ex: oauth3.api('dns.list', { sld: 'daplie', tld: 'com' });
// TODO // TODO
api = await oauth3.package(audience, schemaname); // make an (authorized) well-known api call to an audience api = await oauth3.package(audience, schemaname); // make an (authorized) well-known api call to an audience
// Ex: api = await oauth3.package('domains.daplie.com', 'dns@oauth3.org'); // Ex: api = await oauth3.package('domains.example.com', 'dns@oauth3.org');
// api.list({ sld: 'mydomain', tld: 'com' }); // api.list({ sld: 'mydomain', tld: 'com' });
@ -353,6 +353,10 @@ promise = oauth3.logout(); // opens logout window for t
oauth3.session(); // returns the current session, if any oauth3.session(); // returns the current session, if any
``` ```
<!-- TODO
Track down the old https://labs.daplie.com/docs/ for API schemas
--
Real API Real API
---------- ----------
@ -494,5 +498,5 @@ can be very ugly and confusing and we definitely need to allow relative paths.
A potential work-around would be to assume all paths are relative (eliminate #4 instead) A potential work-around would be to assume all paths are relative (eliminate #4 instead)
and have the path always key off of the base URL - if oauth3 directives are to be found at and have the path always key off of the base URL - if oauth3 directives are to be found at
https://example.com/username/.well-known/oauth3/directives.json then /api/whatever would refer https://example.com/username/_apis/oauth3.org/index.json then /api/whatever would refer
to https://example.com/username/api/whatever. to https://example.com/username/api/whatever.

BIN
_apis/oauth3/blank.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

BIN
_apis/oauth3/clear.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View File

@ -128,7 +128,7 @@
onError(err); onError(err);
} }
OAUTH3.request({ url: 'directives.json' }).then(function (resp) { OAUTH3.request({ url: params._pathname.replace(/^\.well-known\/oauth3\//, '') }).then(function (resp) {
urlsafe64 = OAUTH3._base64.encodeUrlSafe(JSON.stringify(resp.data, null, 0)); urlsafe64 = OAUTH3._base64.encodeUrlSafe(JSON.stringify(resp.data, null, 0));
onSuccess(urlsafe64); onSuccess(urlsafe64);

96
navigator.auth.js Normal file
View File

@ -0,0 +1,96 @@
(function () {
'use strict';
function create(myOpts) {
return {
requestScope: function (opts) {
// TODO pre-generate URL
// deliver existing session if it exists
var scope = opts && opts.scope || [];
if (myOpts.session) {
if (!scope.length || scope.every(function (scp) {
return -1 !== opts.myOpts.session.scope.indexOf(scp);
})) {
return OAUTH3.PromiseA.resolve(myOpts.session);
}
}
// request a new session otherwise
return OAUTH3.implicitGrant(myOpts.directives, {
client_id: myOpts.conf.client_uri
, client_uri: myOpts.conf.client_uri
// maybe use inline instead?
, windowType: 'popup'
, scope: scope
}).then(function (session) {
return session;
});
}
, session: function () {
return myOpts.session;
}
, refresh: function (session) {
return OAUTH3.implicitGrant(myOpts.directives, {
client_id: myOpts.conf.client_uri
, client_uri: myOpts.conf.client_uri
, windowType: 'background'
}).then(function (_session) {
session = _session;
return session;
});
}
, logout: function () {
return OAUTH3.logout(myOpts.directives, {
client_id: myOpts.conf.client_uri
, client_uri: myOpts.conf.client_uri
});
}
, switchUser: function () {
// should open dialog with user selection dialog
}
}
}
window.navigator.auth = {
getUserAuthenticator: function (opts) {
var conf = {};
var directives;
var session;
opts = opts || {};
conf.client_uri = opts.client_uri || OAUTH3.clientUri(opts.location || window.location);
return OAUTH3.issuer({ broker: opts.issuer_uri || 'https://new.oauth3.org' }).then(function (issuer) {
conf.issuer_uri = issuer;
conf.provider_uri = issuer;
return OAUTH3.directives(conf.provider_uri, {
client_id: conf.client_uri
, client_uri: conf.client_uri
}).then(function (_directives) {
directives = _directives;
var myOpts = {
directives: directives
, conf: conf
};
return OAUTH3.implicitGrant(directives, {
client_id: conf.client_uri
, client_uri: conf.client_uri
, windowType: 'background'
}).then(function (_session) {
session = _session;
myOpts.session = session;
return create(myOpts);
}, function (err) {
console.error('[DEBUG] implicitGrant err:');
console.error(err);
return create(myOpts);
});
});
});
}
};
}());

View File

@ -169,7 +169,7 @@
} }
, scope: { , scope: {
parse: function (scope) { parse: function (scope) {
return (scope||'').split(/[+, ]+/g); return (scope||'').toString().split(/[+, ]+/g);
} }
, stringify: function (scope) { , stringify: function (scope) {
if (Array.isArray(scope)) { if (Array.isArray(scope)) {
@ -747,6 +747,21 @@
*/ */
return OAUTH3._browser.request(preq, opts); return OAUTH3._browser.request(preq, opts);
} }
, issuer: function (opts) {
if (!opts) { opts = {}; }
// TODO this will default to browserlogin.org
var broker = opts.broker || 'https://new.oauth3.org';
//var broker = opts.broker || 'https://broker.oauth3.org';
opts._rpc = "broker";
opts._scheme = "localstorage:";
opts._pathname = "issuer";
return OAUTH3._rpcHelper(broker, opts).then(function(issuer) {
return issuer;
});
}
, implicitGrant: function (directives, opts) { , implicitGrant: function (directives, opts) {
var promise; var promise;
var providerUri = directives.azp || directives.issuer || directives; var providerUri = directives.azp || directives.issuer || directives;
@ -857,12 +872,19 @@
}); });
}); });
} }
, logout: function(providerUri, opts) { , logout: function(issuerUri, opts) {
return OAUTH3.hooks.directives.get(providerUri).then(function (directives) { var directives;
if ('string' !== typeof issuerUri) {
directives = issuerUri;
return OAUTH3._logoutHelper(directives, opts);
}
return OAUTH3.hooks.directives.get(issuerUri).then(function (directives) {
return OAUTH3._logoutHelper(directives, opts); return OAUTH3._logoutHelper(directives, opts);
}); });
} }
, _logoutHelper: function(providerUri, directives, opts) { , _logoutHelper: function(directives, opts) {
var issuerUri = directives.issuer_uri || directives.provider_uri;
var logoutReq = OAUTH3.urls.logout( var logoutReq = OAUTH3.urls.logout(
directives directives
, { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location)) , { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location))
@ -885,10 +907,10 @@
if (params.error) { if (params.error) {
// TODO directives.audience // TODO directives.audience
return OAUTH3.PromiseA.reject(OAUTH3.error.parse(directives.issuer /*providerUri*/, params)); return OAUTH3.PromiseA.reject(OAUTH3.error.parse(directives.issuer /*issuerUri*/, params));
} }
OAUTH3.hooks.session.clear(providerUri); OAUTH3.hooks.session.clear(issuerUri);
return params; return params;
}); });
} }
@ -916,20 +938,20 @@
else { else {
return OAUTH3.request({ return OAUTH3.request({
method: 'GET' method: 'GET'
, url: OAUTH3.url.normalize(providerUri) + opts._pathname // '/.well-known/oauth3/' + discoverFile , url: OAUTH3.url.normalize(providerUri) + '/' + opts._pathname // '/.well-known/oauth3/' + discoverFile
}).then(function (resp) { }).then(function (resp) {
return resp.data; return resp.data;
}); });
} }
} }
if (!(opts.client_id || opts.client_uri).match(OAUTH3._browser.window.location.hostname)) { if (!(opts.client_id || opts.client_uri || '').match(OAUTH3._browser.window.location.hostname)) {
console.warn("It looks like your client_id doesn't match your current window..." console.warn("It looks like your client_id doesn't match your current window..."
+ " this probably won't end well"); + " this probably won't end well");
console.warn(opts.client_id || opts.client_uri, OAUTH3._browser.window.location.hostname); console.warn(opts.client_id || opts.client_uri, OAUTH3._browser.window.location.hostname);
} }
var discReq = OAUTH3.urls.rpc( var discReq = OAUTH3.urls[opts._rpc || 'rpc'](
providerUri providerUri
, { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location)) , { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location))
, windowType: opts.broker && opts.windowType || 'background' , windowType: opts.broker && opts.windowType || 'background'
@ -952,27 +974,36 @@
// TODO allow node to open a desktop browser window // TODO allow node to open a desktop browser window
opts._windowType = opts.windowType; opts._windowType = opts.windowType;
opts.windowType = opts.windowType || 'background'; opts.windowType = opts.windowType || 'background';
return OAUTH3._browser.frameRequest( return OAUTH3._browser.testPixel(providerUri).then(function () {
OAUTH3.url.resolve(providerUri, discReq.url) return OAUTH3._browser.frameRequest(
, discReq.state OAUTH3.url.resolve(providerUri, discReq.url)
// why not just pass opts whole? , discReq.state
, { windowType: opts.windowType // why not just pass opts whole?
, reuseWindow: opts.broker && '-broker' , { windowType: opts.windowType
, debug: opts.debug , reuseWindow: opts.broker && '-broker'
} , debug: opts.debug
).then(function (params) { }
opts.windowType = opts._windowType; ).then(function (params) {
opts.windowType = opts._windowType;
// caller will call OAUTH3._browser.closeFrame(discReq.state, { debug: opts.debug || params.debug }); // caller will call OAUTH3._browser.closeFrame(discReq.state, { debug: opts.debug || params.debug });
if (params.error) { if (params.error) {
// TODO directives.issuer || directives.audience // TODO directives.issuer || directives.audience
return OAUTH3.PromiseA.reject(OAUTH3.error.parse(providerUri, params)); return OAUTH3.PromiseA.reject(OAUTH3.error.parse(providerUri, params));
} }
// TODO params should have response_type indicating json, binary, etc // TODO params should have response_type indicating json, binary, etc
var result = JSON.parse(OAUTH3._base64.decodeUrlSafe(params.data || params.result || params.directives)); var result;
// caller will call OAUTH3.hooks.directives.set(providerUri, directives); try {
return result; result = JSON.parse(OAUTH3._base64.decodeUrlSafe(params.data || params.result || params.directives));
} catch(e) {
result = params.data || params.result;
}
console.log('result:', result);
// caller will call OAUTH3.hooks.directives.set(providerUri, directives);
return result;
});
}); });
} }
, request: function (preq, _sys) { , request: function (preq, _sys) {
@ -1071,6 +1102,28 @@
} }
}); });
} }
, testPixel: function (targetUri) {
var url = OAUTH3.url.resolve(OAUTH3.url.normalize(targetUri), '.well-known/oauth3/clear.gif');
return new OAUTH3.PromiseA(function (resolve, reject) {
var img = document.createElement('img');
img.addEventListener('load', function () {
resolve();
});
img.addEventListener('error', function () {
var err = new Error("OAuth3 support not detected: '" + url + "' not found");
err.code = 'E_NOT_SUPPORTED';
reject(err);
});
// works with CSP
img.style.position = 'absolute';
img.style.left = '-2px';
img.style.bottom = '-2px';
img.className = 'js-oauth3-discover';
img.src = url;
document.body.appendChild(img);
console.log('img', img);
});
}
, frameRequest: function (url, state, opts) { , frameRequest: function (url, state, opts) {
opts = opts || {}; opts = opts || {};
var previousFrame = OAUTH3._browser._frames[state]; var previousFrame = OAUTH3._browser._frames[state];
@ -1081,11 +1134,10 @@
} }
var timeout = opts.timeout; var timeout = opts.timeout;
if (opts.debug) { if ('background' === windowType) {
timeout = timeout || 3 * 60 * 1000; if (!timeout) {
} timeout = 7 * 1000;
else { }
timeout = timeout || ('background' === windowType ? 15 * 1000 : 3 * 60 * 1000);
} }
return new OAUTH3.PromiseA(function (resolve, reject) { return new OAUTH3.PromiseA(function (resolve, reject) {
@ -1107,14 +1159,16 @@
cleanup(); cleanup();
}; };
tok = setTimeout(function () { if (timeout) {
var err = new Error( tok = setTimeout(function () {
"the '" + windowType + "' request did not complete within " + Math.round(timeout / 1000) + "s" var err = new Error(
); "the '" + windowType + "' request did not complete within " + Math.round(timeout / 1000) + "s"
err.code = "E_TIMEOUT"; );
reject(err); err.code = "E_TIMEOUT";
cleanup(); reject(err);
}, timeout); cleanup();
}, timeout);
}
setTimeout(function () { setTimeout(function () {
if (!OAUTH3._browser._frames[state]) { if (!OAUTH3._browser._frames[state]) {
@ -1317,6 +1371,23 @@
OAUTH3.utils = { OAUTH3.utils = {
clientUri: OAUTH3.clientUri clientUri: OAUTH3.clientUri
, query: OAUTH3.query , query: OAUTH3.query
, parseSubject: function (sub) {
var parts = sub.split('@');
var issuer;
var subject;
if (/@/.test(sub)) {
// The username may have a single @, the provider may not
// user@thing.com@whatever.com -> user@thing.com, whatever.com
issuer = parts.pop();
subject = parts.join('@');
} else {
//subject = '';
issuer = parts.join('@');
}
return { subject: subject, issuer: issuer };
}
, scope: OAUTH3.scope , scope: OAUTH3.scope
, uri: OAUTH3.uri , uri: OAUTH3.uri
, url: OAUTH3.url , url: OAUTH3.url

View File

@ -218,6 +218,7 @@ OAUTH3.urls.grants = function (directive, opts) {
, session: opts.session , session: opts.session
}; };
}; };
//OAUTH3.urls.accessToken = function (directive, opts)
OAUTH3.urls.clientToken = function (directive, opts) { OAUTH3.urls.clientToken = function (directive, opts) {
var tokenDir = directive.access_token; var tokenDir = directive.access_token;
if (!tokenDir) { if (!tokenDir) {
@ -294,7 +295,7 @@ OAUTH3.urls.credentialMeta = function (directive, opts) {
.replace(':id', opts.email) .replace(':id', opts.email)
}; };
OAUTH3.authn = {}; OAUTH3.authn = OAUTH3.authn || {};
OAUTH3.authn.loginMeta = function (directive, opts) { OAUTH3.authn.loginMeta = function (directive, opts) {
var url = OAUTH3.urls.credentialMeta(directive, opts); var url = OAUTH3.urls.credentialMeta(directive, opts);
return OAUTH3.request({ return OAUTH3.request({
@ -370,8 +371,8 @@ OAUTH3.authn.resourceOwnerPassword = function (directive, opts) {
OAUTH3.authz = {}; OAUTH3.authz = {};
OAUTH3.authz.scopes = function (providerUri, session, clientParams) { OAUTH3.authz.scopes = function (providerUri, session, clientParams) {
var clientUri = OAUTH3.uri.normalize(clientParams.client_uri || OAUTH3._browser.window.document.referrer); var clientUri = OAUTH3.uri.normalize(clientParams.client_uri || OAUTH3._browser.window.document.referrer);
var scope = clientParams.scope || 'oauth3_authn'; var scope = clientParams.scope || 'authn@oauth3.org';
if ('oauth3_authn' === scope) { if ('authn@oauth3.org' === scope.toString()) {
// implicit ppid grant is automatic // implicit ppid grant is automatic
console.warn('[security] fix scope checking on backend so that we can do automatic grants'); console.warn('[security] fix scope checking on backend so that we can do automatic grants');
// TODO check user preference if implicit ppid grant is allowed // TODO check user preference if implicit ppid grant is allowed
@ -573,68 +574,85 @@ OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, s
}; };
OAUTH3.requests = {}; OAUTH3.requests = {};
//OAUTH3.accounts = {};
OAUTH3.requests.accounts = {}; OAUTH3.requests.accounts = {};
OAUTH3.requests.accounts.update = function (directive, session, opts) { OAUTH3.urls.accounts = {};
var dir = directive.update_account || { OAUTH3.urls.accounts._ = function (directives, directive, session, opts) {
method: 'POST' opts = opts || {};
, url: OAUTH3.url.normalize(directive.api) + '/api/issuer@oauth3.org/accounts/:accountId' var dir = directive || {
//url: OAUTH3.url.normalize(directives.api) + '/api/issuer@oauth3.org/accounts/:accountId'
url: OAUTH3.url.normalize(directives.api) + '/api/issuer@oauth3.org/acl/profiles/:accountId'
//, method: 'GET'
, bearer: 'Bearer' , bearer: 'Bearer'
}; };
var url = dir.url var url = dir.url
.replace(/:accountId/, opts.accountId) .replace(/:accountId/, opts.accountId || '')
.replace(/\/$/, '')
; ;
return OAUTH3.request({ return {
method: dir.method || 'POST' url: url
, url: url //, method: dir.method || 'POST'
, session: session
/*
, headers: { , headers: {
'Authorization': (dir.bearer || 'Bearer') + ' ' + session.accessToken 'Authorization': (dir.bearer || 'Bearer') + ' ' + (session.access_token || session.accessToken)
} }
, json: { */
name: opts.name
, comment: opts.comment
, displayName: opts.displayName
, priority: opts.priority
}
});
};
OAUTH3.requests.accounts.create = function (directive, session, account) {
var dir = directive.create_account || {
method: 'POST'
, url: OAUTH3.url.normalize(directive.api) + '/api/issuer@oauth3.org/accounts'
, bearer: 'Bearer'
}; };
var data = { };
OAUTH3.urls.accounts.get = function (directives, session) {
var urlObj = OAUTH3.urls.accounts._(directives, directives.account, session);
urlObj.method = (directives.account || { method: 'GET' }).method;
return urlObj;
};
OAUTH3.urls.accounts.update = function (directives, session, opts) {
var urlObj = OAUTH3.urls.accounts._(directives, directives.update_account, session, opts);
urlObj.method = (directives.update_account || { method: 'POST' }).method;
urlObj.json = {
name: opts.name
, comment: opts.comment
, displayName: opts.displayName
, priority: opts.priority
};
return urlObj;
};
OAUTH3.urls.accounts.create = function (directives, session, account) {
var urlObj = OAUTH3.urls.accounts._(directives, directives.create_account, session);
var profile = {
nick: account.display_name
// "name" is unique and what would be reserved in a url {{name}}.issuer.org or issuer.org/users/{{name}}
, name: account.name
, comment: account.comment
, display_name: account.display_name
, priority: account.priority
};
var credentials = [ { token: session.access_token } ];
urlObj.method = (directives.create_account || { method: 'POST' }).method;
urlObj.json = {
// TODO fix the server to just use one scheme // TODO fix the server to just use one scheme
// account = { nick, self: { comment, username } } // account = { nick, self: { comment, username } }
// account = { name, comment, display_name, priority } // account = { name, comment, display_name, priority }
account: { credentials: credentials
nick: account.display_name , profile: profile
, name: account.name // 'account' is deprecated in favor of 'profile'
, comment: account.comment , account: profile
, display_name: account.display_name // 'logins' is deprecated in favor of 'credentials'
, priority: account.priority , logins: credentials
, self: {
nick: account.display_name
, name: account.name
, comment: account.comment
, display_name: account.display_name
, priority: account.priority
}
}
, logins: [
{
token: session.access_token
}
]
}; };
return urlObj;
return OAUTH3.request({ };
method: dir.method || 'POST' OAUTH3.requests.accounts.get = function (directives, session) {
, url: dir.url var urlObj = OAUTH3.urls.accounts.get(directives, session);
, session: session return OAUTH3.request(urlObj);
, data: data };
}); OAUTH3.requests.accounts.update = function (directives, session, opts) {
var urlObj = OAUTH3.urls.accounts.update(directives, session, opts);
return OAUTH3.request(urlObj);
};
OAUTH3.requests.accounts.create = function (directive, session, account) {
var urlObj = OAUTH3.urls.accounts.create(directives, session, account);
return OAUTH3.request(urlObj);
}; };
OAUTH3.hooks.grants = { OAUTH3.hooks.grants = {

View File

@ -27,10 +27,10 @@
OAUTH3.authz.scopes = function () { OAUTH3.authz.scopes = function () {
return OAUTH3.PromiseA.resolve({ return OAUTH3.PromiseA.resolve({
pending: ['oauth3_authn'] // not yet accepted pending: [ 'authn@oauth3.org' ] // not yet accepted
, granted: [] // all granted, ever , granted: [] // all granted, ever
, requested: ['oauth3_authn'] // all requested, now , requested: [ 'authn@oauth3.org' ] // all requested, now
, accepted: [] // granted (ever) and requested (now) , accepted: [] // granted (ever) and requested (now)
}); });
}; };
OAUTH3.authz.grants = function (providerUri, opts) { OAUTH3.authz.grants = function (providerUri, opts) {

1
well-known Symbolic link
View File

@ -0,0 +1 @@
_apis