Merge branch 'master' of git.daplie.com:OAuth3/oauth3.js

This commit is contained in:
Drew Warren 2017-07-05 16:16:58 -06:00
commit 9f9610b6f5
6 changed files with 128 additions and 50 deletions

View File

@ -20,7 +20,7 @@ If you have no idea what you're doing
1. Create a folder for your project named after your app, such as `example.com/` 1. Create a folder for your project named after your app, such as `example.com/`
2. Inside of the folder `example.com/` a folder called `assets/` 2. Inside of the folder `example.com/` a folder called `assets/`
3. Inside of the folder `example.com/assets` a folder called `org.oauth3/` 3. Inside of the folder `example.com/assets` a folder called `org.oauth3/`
4. Download [oauth.js-v1.zip](https://git.daplie.com/Daplie/oauth3.js/repository/archive.zip?ref=v1) 4. Download [oauth3.js-v1.zip](https://git.daplie.com/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/org.oauth3/` 6. Copy the file `oauth3.core.js` into the folder `example.com/assets/org.oauth3/`
7. Copy the folder `well-known` into the folder `example.com/` 7. Copy the folder `well-known` into the folder `example.com/`
@ -61,7 +61,7 @@ var auth = OAUTH3.create(window.location); // use window.location to set Client
// //
function onChangeProvider(_providerUri) { function onChangeProvider(_providerUri) {
// example https://oauth3.org // example https://oauth3.org
return auth.setProvider(providerUri); return oauth3.setIdentityProvider(providerUri);
} }
@ -69,7 +69,7 @@ function onChangeProvider(_providerUri) {
// //
function onClickLogin() { function onClickLogin() {
return auth.authenticate().then(function (session) { return oauth3.authenticate().then(function (session) {
console.info('Authentication was Successful:'); console.info('Authentication was Successful:');
console.log(session); console.log(session);
@ -80,7 +80,7 @@ function onClickLogin() {
// //
console.info('Secure PPID (aka subject):', session.token.sub); console.info('Secure PPID (aka subject):', session.token.sub);
return auth.request({ return oauth3.request({
url: 'https://oauth3.org/api/org.oauth3.provider/inspect' url: 'https://oauth3.org/api/org.oauth3.provider/inspect'
, session: session , session: session
}).then(function (resp) { }).then(function (resp) {
@ -102,7 +102,7 @@ function onClickLogin() {
// //
function onClickLogout() { function onClickLogout() {
return auth.logout().then(function () { return oauth3.logout().then(function () {
localStorage.clear(); localStorage.clear();
console.info('Logout was Successful'); console.info('Logout was Successful');
@ -167,7 +167,7 @@ pushd /path/to/your/web/app
# clone the project as assets/org.oauth3 # clone the project as assets/org.oauth3
mkdir -p assets mkdir -p assets
git clone git@git.daplie.com:Daplie/oauth3.js.git assets/org.oauth3 git clone git@git.daplie.com:OAuth3/oauth3.js.git assets/org.oauth3
pushd assets/org.oauth3 pushd assets/org.oauth3
git checkout v1 git checkout v1
popd popd
@ -284,29 +284,33 @@ We include a small wrapper function of just a few lines in the bottom of `oauth3
which exposes a `create` method to make using the underlying library require typing fewer keystrokes. which exposes a `create` method to make using the underlying library require typing fewer keystrokes.
``` ```
auth = OAUTH3.create(location); // takes a location object, such as window.location oauth3 = OAUTH3.create(location); // takes a location object, such as window.location
// to create the Client URI (your app's id) // to create the Client URI (your app's id)
// and save it to an internal state // and save it to an internal state
promise = auth.init(location); // set and fetch your own site/app's configuration details promise = oauth3.init(location); // set and fetch your own site/app's configuration details
// promises your site's config // promises your site's config
promise = auth.setProvider(url); // changes the 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 .well-known/oauth3),
// and caches it in internal state as the default // and caches it in internal state as the default
promise = auth.authenticate(); // opens login window for the provider and returns a session promise = oauth3.setResourceProvider(url); // changes the Resource Provider URI (the site you're getting stuff from)
// (must be called after the setProvider promise has completed)
promise = auth.authorize(permissions); // authenticates (if not authenticated) and opens a window to promise = oauth3.setProvider(url); // changes the both Identity and Resource Provider URI together
// authorize a particular scope (contacts, photos, whatever)
promise = auth.request({ url, method, data }); // make an (authorized) request to a provider's resource promise = oauth3.authenticate(); // opens login window for the provider and returns a session
// (contacts, photos, whatever) // (must be called after the setIdentityProvider promise has completed)
promise = auth.logout(); // opens logout window for the provider promise = oauth3.authorize(permissions); // authenticates (if not authenticated) and opens a window to
// authorize a particular scope (contacts, photos, whatever)
auth.session(); // returns the current session, if any promise = oauth3.request({ url, method, data }); // make an (authorized) request to a provider's resource
// (contacts, photos, whatever)
promise = oauth3.logout(); // opens logout window for the provider
oauth3.session(); // returns the current session, if any
``` ```
@ -437,7 +441,7 @@ Since we do not require the `protocol` to be specified, it is a URI
However, we do have a problem of disambiguation since a URI may look like a `path`: However, we do have a problem of disambiguation since a URI may look like a `path`:
1. https://example.com/api/org.oauth3.provider 1. https://example.com/api/org.oauth3.provider
2. example.com/api/org.oauth.provider/ (not unique) 2. example.com/api/org.oauth3.provider/ (not unique)
3. /api/org.oauth3.provider 3. /api/org.oauth3.provider
4. api/org.oauth3.provider (not unique) 4. api/org.oauth3.provider (not unique)

View File

@ -70,4 +70,17 @@ OAUTH3.api['account.addAddress'] = function (providerUri, opts) {
}); });
}; };
OAUTH3.api['account.removeAddress'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
method: 'DELETE'
, url: OAUTH3.url.normalize(providerUri)
+ '/api/com.daplie.me/accounts/' + session.token.sub + '/addresses/' + opts.addressId
, session: session
}).then(function (res) {
return res;
});
};
}('undefined' !== typeof exports ? exports : window)); }('undefined' !== typeof exports ? exports : window));

View File

@ -603,7 +603,7 @@
console.warn('[Warn] Please implement OAUTH3._hooks.sessions.get = function (providerUri[, id]) { return PromiseA<session>; }'); console.warn('[Warn] Please implement OAUTH3._hooks.sessions.get = function (providerUri[, id]) { return PromiseA<session>; }');
return JSON.parse(window.sessionStorage.getItem('session-' + providerUri + (id || '')) || 'null'); return JSON.parse(window.sessionStorage.getItem('session-' + providerUri + (id || '')) || 'null');
} }
return OAUTH3._hooks.directives.get(providerUri, id); return OAUTH3._hooks.sessions.get(providerUri, id);
} }
, _set: function (providerUri, newSession, id) { , _set: function (providerUri, newSession, id) {
if (!OAUTH3._hooks || !OAUTH3._hooks.sessions || !OAUTH3._hooks.sessions.set) { if (!OAUTH3._hooks || !OAUTH3._hooks.sessions || !OAUTH3._hooks.sessions.set) {
@ -612,7 +612,7 @@
window.sessionStorage.setItem('session-' + providerUri + (id || newSession.id || newSession.token.id || ''), JSON.stringify(newSession)); window.sessionStorage.setItem('session-' + providerUri + (id || newSession.id || newSession.token.id || ''), JSON.stringify(newSession));
return newSession; return newSession;
} }
return OAUTH3._hooks.directives.set(providerUri, newSession, id); return OAUTH3._hooks.sessions.set(providerUri, newSession, id);
} }
} }
} }
@ -1087,7 +1087,11 @@
var result = { var result = {
_clientUri: OAUTH3.clientUri(location) _clientUri: OAUTH3.clientUri(location)
, _providerUri: null , _identityProviderUri: null
, _resourceProviderUri: null
, _identityProviderDirectives: null
, _resourceProviderDirectives: null
//, _resourceProviderMap: null // map between xyz.com and org.oauth3.domains
, _init: function (location, opts) { , _init: function (location, opts) {
var me = this; var me = this;
if (location) { if (location) {
@ -1095,13 +1099,20 @@
} }
if (opts) { if (opts) {
if (opts.providerUri) { if (opts.providerUri) {
me._providerUri = opts.providerUri; me._identityProviderUri = opts.providerUri;
me._resourceProviderUri = opts.providerUri;
}
if (opts.identityProviderUri) {
me._identityProviderUri = opts.identityProviderUri;
}
if (opts.resourceProviderUri) {
me._resourceProviderUri = opts.resourceProviderUri;
} }
if (opts.session) { if (opts.session) {
if (!me._providerUri) { if (!me._identityProviderUri) {
throw new Error("'providerUri' was not supplied"); throw new Error("'providerUri' was not supplied");
} }
opts.session.provider_uri = me._providerUri; opts.session.provider_uri = me._identityProviderUri;
opts.session.client_uri = me._clientUri; opts.session.client_uri = me._clientUri;
me.session(opts.session, opts.sessionId); me.session(opts.session, opts.sessionId);
} }
@ -1109,35 +1120,62 @@
} }
, init: function (location/*, opts*/) { , init: function (location/*, opts*/) {
var me = this; var me = this;
var p = OAUTH3.PromiseA.resolve(); var p1 = OAUTH3.PromiseA.resolve();
var p2 = OAUTH3.PromiseA.resolve();
me._init(location, opts); me._init(location, opts);
if (me._providerUri) { if (me._identityProviderUri) {
// returns directives // returns directives
p = OAUTH3.discover(me._providerUri, { client_id: this._clientUri }); p1 = OAUTH3.discover(me._identityProviderUri, { client_id: this._clientUri });
}
if (me._resourceProviderUri) {
// returns directives
p2 = OAUTH3.discover(me._resourceProviderUri, { client_id: this._clientUri });
} }
return p.then(function () { return p1.then(function () {
return OAUTH3.discover(me._clientUri, { client_id: me._clientUri }).then(function (clientDirectives) { return p2.then(function () {
me._clientDirectives = clientDirectives; return OAUTH3.discover(me._clientUri, { client_id: me._clientUri }).then(function (clientDirectives) {
return clientDirectives; me._clientDirectives = clientDirectives;
return clientDirectives;
});
}); });
}); });
} }
, setProvider: function (providerUri) { , setProvider: function (providerUri) {
var me = this; var me = this;
me._providerUri = providerUri; return me.init().then(function () {
return me.setIdentityProvider(providerUri).then(function () {
// TODO how to say "Use xyz.com for org.oauth3.domains, but abc.com for org.oauth3.dns"?
return me.setResourceProvider(providerUri);
});
});
}
, setIdentityProvider: function (providerUri) {
var me = this;
me._identityProviderUri = providerUri;
return me.init().then(function () { return me.init().then(function () {
// this should be synchronous the second time around // this should be synchronous the second time around
return OAUTH3.discover(me._providerUri, { client_id: me._clientUri }).then(function (directives) { return OAUTH3.discover(me._identityProviderUri, { client_id: me._clientUri }).then(function (directives) {
me._providerDirectives = directives; me._identityProviderDirectives = directives;
return directives;
});
});
}
, setResourceProvider: function (providerUri) {
var me = this;
me._resourceProviderUri = providerUri;
return me.init().then(function () {
// this should be synchronous the second time around
return OAUTH3.discover(me._resourceProviderUri, { client_id: me._clientUri }).then(function (directives) {
me._resourceProviderDirectives = directives;
return directives; return directives;
}); });
}); });
} }
, checkSession: function () { , checkSession: function () {
return OAUTH3.hooks.session.get(this._providerUri); return OAUTH3.hooks.session.get(this._identityProviderUri);
} }
, login: function (opts) { , login: function (opts) {
var me = this; var me = this;
@ -1149,16 +1187,16 @@
opts = opts || {}; opts = opts || {};
opts.client_uri = me._clientUri; opts.client_uri = me._clientUri;
return OAUTH3.implicitGrant(me._providerDirectives, opts).then(function (session) { return OAUTH3.implicitGrant(me._identityProviderDirectives, opts).then(function (session) {
me._session = true; me._session = true;
return session; return session;
}); });
} }
, session: function (session, id) { , session: function (session, id) {
if (!session) { if (!session) {
return JSON.parse(JSON.stringify(OAUTH3.hooks.session._getCached(this._providerUri) || null)); return JSON.parse(JSON.stringify(OAUTH3.hooks.session._getCached(this._identityProviderUri) || null));
} }
return OAUTH3.hooks.session.set(this._providerUri, session, id); return OAUTH3.hooks.session.set(this._identityProviderUri, session, id);
} }
, request: function (preq, opts) { , request: function (preq, opts) {
opts = opts || {}; opts = opts || {};
@ -1166,10 +1204,10 @@
preq.client_id = this._clientUri; preq.client_id = this._clientUri;
preq.method = preq.method || 'GET'; preq.method = preq.method || 'GET';
if (this._session) { if (this._session) {
preq.session = preq.session || this.session(); // OAUTH3.hooks.session._getCached(this._providerUri); preq.session = preq.session || this.session(); // OAUTH3.hooks.session._getCached(this._identityProviderUri);
} }
// TODO maybe use a baseUrl from the directives file? // TODO maybe use a baseUrl from the directives file?
preq.url = OAUTH3.url.resolve(this._providerUri, preq.url); preq.url = OAUTH3.url.resolve(this._resourceProviderUri, preq.url);
return OAUTH3.request(preq, opts); return OAUTH3.request(preq, opts);
} }
@ -1178,16 +1216,16 @@
opts = opts || {}; opts = opts || {};
opts.client_uri = this._clientUri; opts.client_uri = this._clientUri;
opts.client_id = this._clientUri; opts.client_id = this._clientUri;
opts.session = OAUTH3.hooks.session._getCached(this._providerUri); opts.session = OAUTH3.hooks.session._getCached(this._identityProviderUri);
return OAUTH3.logout(this._providerUri, opts); return OAUTH3.logout(this._identityProviderUri, opts);
} }
, api: function (api, opts) { , api: function (api, opts) {
opts = opts || {}; opts = opts || {};
opts.api = api; opts.api = api;
opts.session = OAUTH3.hooks.session._getCached(this._providerUri); opts.session = OAUTH3.hooks.session._getCached(this._identityProviderUri);
return OAUTH3.api(this._providerDirectives.api, opts); return OAUTH3.api(this._resourceProviderDirectives.api, opts);
} }
}; };
result.authenticate = result.login; result.authenticate = result.login;

View File

@ -188,7 +188,9 @@
return OAUTH3.PromiseA.reject(new Error('JWK of type '+jwk.kty+' missing fields ' + missing)); return OAUTH3.PromiseA.reject(new Error('JWK of type '+jwk.kty+' missing fields ' + missing));
} }
var jwkStr = '{' + keys.map(function (name) { return name+':'+jwk[name]; }).join(',') + '}'; // I'm not actually 100% sure this behavior is guaranteed, but when we use an array as the
// replacer argument the keys are always in the order they appeared in the array.
var jwkStr = JSON.stringify(jwk, keys);
return OAUTH3.crypto.core.sha256(OAUTH3._binStr.binStrToBuffer(jwkStr)) return OAUTH3.crypto.core.sha256(OAUTH3._binStr.binStrToBuffer(jwkStr))
.then(OAUTH3._base64.bufferToUrlSafe); .then(OAUTH3._base64.bufferToUrlSafe);
}; };

View File

@ -45,6 +45,22 @@ OAUTH3.api['domains.list'] = function (providerUri, opts) {
}); });
}; };
// TODO: Manual Renew Function
OAUTH3.api['domains.extend'] = function (providerUri, opts) {
var session = opts.session;
return OAUTH3.request({
method: 'POST'
, url: OAUTH3.url.normalize(providerUri)
+ '/api/com.daplie.domains/accounts/' + session.token.sub + '/registrations/' + opts.data.tld + '/' + opts.data.sld + '/extend'
, session: session
, data: opts.data
}).then(function (res) {
return res;
});
};
OAUTH3.api['ns.list'] = function (providerUri, opts) { OAUTH3.api['ns.list'] = function (providerUri, opts) {
var session = opts.session; var session = opts.session;
var domain = opts.domain; var domain = opts.domain;
@ -77,7 +93,7 @@ OAUTH3.api['ns.list'] = function (providerUri, opts) {
}; };
OAUTH3.api['ns.add'] = function (providerUri, opts) { OAUTH3.api['ns.add'] = function (providerUri, opts) {
var session = opts.session var session = opts.session;
var server = opts.server; var server = opts.server;
var tld = opts.tld; var tld = opts.tld;
var sld = opts.sld; var sld = opts.sld;

View File

@ -9,6 +9,11 @@ var sessionsdir = path.join(oauth3dir, 'sessions');
var directivesdir = path.join(oauth3dir, 'directives'); var directivesdir = path.join(oauth3dir, 'directives');
var metadir = path.join(oauth3dir, 'meta'); var metadir = path.join(oauth3dir, 'meta');
// We can reasonably assume the existence of the home directory, but we can't assume
// that there will already be a `.oauth3` directory or anything inside of it.
if (!fs.existsSync(path.join(oauth3dir, '..'))) {
fs.mkdirSync(path.join(oauth3dir, '..'));
}
if (!fs.existsSync(oauth3dir)) { if (!fs.existsSync(oauth3dir)) {
fs.mkdirSync(oauth3dir); fs.mkdirSync(oauth3dir);
} }