Compare commits
	
		
			No commits in common. "master" and "v1.2.4" have entirely different histories.
		
	
	
		
	
		
@ -1 +1 @@
 | 
			
		||||
_apis
 | 
			
		||||
well-known
 | 
			
		||||
							
								
								
									
										64
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								README.md
									
									
									
									
									
								
							@ -5,7 +5,7 @@ oauth3.js
 | 
			
		||||
| [issuer.html](https://git.oauth3.org/OAuth3/issuer.html)
 | 
			
		||||
| [issuer.rest.walnut.js](https://git.oauth3.org/OAuth3/issuer.rest.walnut.js)
 | 
			
		||||
| [issuer.srv](https://git.oauth3.org/OAuth3/issuer.srv)
 | 
			
		||||
| Sponsored by [ppl](https://ppl.family)
 | 
			
		||||
| Sponsored by [Daplie](https://daplie.com)
 | 
			
		||||
 | 
			
		||||
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!)
 | 
			
		||||
@ -29,7 +29,8 @@ 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)
 | 
			
		||||
5. Double-click to unzip the folder.
 | 
			
		||||
6. Copy the file `oauth3.core.js` into the folder `example.com/assets/oauth3.org/`
 | 
			
		||||
7. Copy the folder `_apis` into the folder `example.com/`
 | 
			
		||||
7. Copy the folder `well-known` 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="app.js"></script>` to your `index.html`
 | 
			
		||||
10. Create files in `example.com` called `app.js` and `index.html` and put this in it:
 | 
			
		||||
@ -58,13 +59,13 @@ If you have no idea what you're doing
 | 
			
		||||
`app.js`:
 | 
			
		||||
```js
 | 
			
		||||
var OAUTH3 = window.OAUTH3;
 | 
			
		||||
var oauth3 = OAUTH3.create(window.location); // use window.location to set Client URI (your app's id)
 | 
			
		||||
var auth = 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
 | 
			
		||||
// 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
 | 
			
		||||
  return oauth3.setIdentityProvider(providerUri);
 | 
			
		||||
}
 | 
			
		||||
@ -86,13 +87,11 @@ function onClickLogin() {
 | 
			
		||||
    console.info('Secure PPID (aka subject):', session.token.sub);
 | 
			
		||||
 | 
			
		||||
    return oauth3.request({
 | 
			
		||||
      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)
 | 
			
		||||
      url: 'https://oauth3.org/api/issuer@oauth3.org/inspect'
 | 
			
		||||
    , session: session
 | 
			
		||||
    }).then(function (resp) {
 | 
			
		||||
 | 
			
		||||
      console.info("Signing Public Key JWK:");
 | 
			
		||||
      console.info("Inspect Token:");
 | 
			
		||||
      console.log(resp.data);
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
@ -145,13 +144,13 @@ it might look like this:
 | 
			
		||||
example.com
 | 
			
		||||
│
 | 
			
		||||
│
 | 
			
		||||
├── _apis
 | 
			
		||||
│   └── oauth3.org
 | 
			
		||||
├── .well-known (hidden)
 | 
			
		||||
│   └── oauth3
 | 
			
		||||
│       ├── callback.html
 | 
			
		||||
│       ├── directives.json
 | 
			
		||||
│       └── index.html
 | 
			
		||||
├── assets
 | 
			
		||||
│   └── oauth3.org
 | 
			
		||||
│   └── org.oauth3
 | 
			
		||||
│       └── oauth3.core.js
 | 
			
		||||
│
 | 
			
		||||
│
 | 
			
		||||
@ -172,17 +171,17 @@ Installation (if you know what you're doing)
 | 
			
		||||
pushd /path/to/your/web/app
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# clone the project as assets/oauth3.org
 | 
			
		||||
# clone the project as assets/org.oauth3
 | 
			
		||||
mkdir -p assets
 | 
			
		||||
git clone git@git.oauth3.org:OAuth3/oauth3.js.git assets/oauth3.org
 | 
			
		||||
pushd assets/oauth3.org
 | 
			
		||||
git clone git@git.daplie.com:OAuth3/oauth3.js.git assets/org.oauth3
 | 
			
		||||
pushd assets/org.oauth3
 | 
			
		||||
git checkout v1
 | 
			
		||||
popd
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# symlink `_apis/oauth3.org` to `assets/oauth3.org/_apis/oauth3.org`
 | 
			
		||||
mkdir -p _apis
 | 
			
		||||
ln -sf  ../assets/oauth3.org/_apis/oauth3 _apis/oauth3.org
 | 
			
		||||
# 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`**
 | 
			
		||||
@ -192,17 +191,17 @@ ln -sf  ../assets/oauth3.org/_apis/oauth3 _apis/oauth3.org
 | 
			
		||||
bower install oauth3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# create a `_apis` folder and an `assets` folder
 | 
			
		||||
mkdir -p _apis assets
 | 
			
		||||
# create a `.well-known` folder and an `assets` folder
 | 
			
		||||
mkdir -p .well-known assets
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# symlink `_apis/oauth3.org` to `bower_components/oauth3.org/_apis/oauth3.org`
 | 
			
		||||
ln -sf  ../bower_components/oauth3.org/_apis/oauth3.org _apis/oauth3.org
 | 
			
		||||
# symlink `.well-known/oauth3` to `bower_components/oauth3/.well-known/oauth3`
 | 
			
		||||
ln -sf  ../bower_components/oauth3/.well-known/oauth3 .well-known/oauth3
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# symlink `assets/oauth3.org` to `bower_components/oauth3.org`
 | 
			
		||||
ln -sf  ../bower_components/oauth3.org/_apis/oauth3.org _apis/oauth3.org
 | 
			
		||||
ln -sf  ../bower_components/oauth3.org assets/oauth3.org
 | 
			
		||||
# 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
 | 
			
		||||
@ -211,7 +210,7 @@ Usage
 | 
			
		||||
Update your HTML to include the the following script tag:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<script src="assets/oauth3.org/oauth3.core.js"></script>
 | 
			
		||||
<script src="assets/org.oauth3/oauth3.core.js"></script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
You can create a very simple demo application like this:
 | 
			
		||||
@ -290,7 +289,7 @@ You're all set. Nothing else is needed.
 | 
			
		||||
We've created an `Oauth3` service just for you:
 | 
			
		||||
 | 
			
		||||
```html
 | 
			
		||||
<script src="assets/oauth3.org/oauth3.ng.js"></script>
 | 
			
		||||
<script src="assets/org.oauth3/oauth3.ng.js"></script>
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
@ -323,7 +322,7 @@ promise = oauth3.init(opts);                        // set and fetch your own si
 | 
			
		||||
// 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),
 | 
			
		||||
// promises the provider's config                   // gets the config for that site (from their _apis/oauth3.org),
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
promise = oauth3.setResourceProvider(url);          // changes the Resource Provider URI (the site you're getting stuff from)
 | 
			
		||||
@ -340,11 +339,12 @@ promise = oauth3.request({ url, method, data });    // make an (authorized) arbi
 | 
			
		||||
                                                    // (contacts, photos, whatever)
 | 
			
		||||
 | 
			
		||||
promise = oauth3.api(apiname, opts);                // make an (authorized) well-known api call to an audience
 | 
			
		||||
                                                    // Ex: oauth3.api('dns.list', { sld: 'example', tld: 'com' });
 | 
			
		||||
                                                    // See https://labs.daplie.com/docs/ for API schemas
 | 
			
		||||
                                                    // Ex: oauth3.api('dns.list', { sld: 'daplie', tld: 'com' });
 | 
			
		||||
 | 
			
		||||
// TODO
 | 
			
		||||
api = await oauth3.package(audience, schemaname);   // make an (authorized) well-known api call to an audience
 | 
			
		||||
                                                    // Ex: api = await oauth3.package('domains.example.com', 'dns@oauth3.org');
 | 
			
		||||
                                                    // Ex: api = await oauth3.package('domains.daplie.com', 'dns@oauth3.org');
 | 
			
		||||
                                                    //     api.list({ sld: 'mydomain', tld: 'com' });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -353,10 +353,6 @@ promise = oauth3.logout();                          // opens logout window for t
 | 
			
		||||
oauth3.session();                                   // returns the current session, if any
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
<!-- TODO
 | 
			
		||||
Track down the old https://labs.daplie.com/docs/ for API schemas
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Real API
 | 
			
		||||
----------
 | 
			
		||||
@ -498,5 +494,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)
 | 
			
		||||
and have the path always key off of the base URL - if oauth3 directives are to be found at
 | 
			
		||||
https://example.com/username/_apis/oauth3.org/index.json then /api/whatever would refer
 | 
			
		||||
https://example.com/username/.well-known/oauth3/directives.json then /api/whatever would refer
 | 
			
		||||
to https://example.com/username/api/whatever.
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 43 B  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 43 B  | 
@ -1,140 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <style>
 | 
			
		||||
      body {
 | 
			
		||||
        background-color: #ffcccc;
 | 
			
		||||
      }
 | 
			
		||||
    </style>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
  OAuth3 RPC
 | 
			
		||||
 | 
			
		||||
  <script src="../../assets/oauth3.org/oauth3.core.js"></script>
 | 
			
		||||
  <script>
 | 
			
		||||
    ;(function () {
 | 
			
		||||
    'use strict';
 | 
			
		||||
 | 
			
		||||
    // Taken from oauth3.core.js
 | 
			
		||||
 | 
			
		||||
    // TODO what about search within hash?
 | 
			
		||||
    var prefix = "(" + window.location.hostname + ") [.well-known/oauth3/]";
 | 
			
		||||
    var params = OAUTH3.query.parse(window.location.hash || window.location.search);
 | 
			
		||||
    var urlsafe64;
 | 
			
		||||
    var redirect;
 | 
			
		||||
    var err;
 | 
			
		||||
    var oldRpc;
 | 
			
		||||
    var sub = params.sub || params.subject;
 | 
			
		||||
    var subData;
 | 
			
		||||
 | 
			
		||||
    function doRedirect(redirect) {
 | 
			
		||||
      if (params.debug) {
 | 
			
		||||
        console.log(prefix, 'params.redirect_uri:', params.redirect_uri);
 | 
			
		||||
        console.log(prefix, 'redirect');
 | 
			
		||||
        console.log(redirect);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!params.debug) {
 | 
			
		||||
        window.location = redirect;
 | 
			
		||||
      } else {
 | 
			
		||||
        // yes, we're violating the security lint with purpose
 | 
			
		||||
        document.body.innerHTML += window.location.host + window.location.pathname
 | 
			
		||||
          + '<br/><br/>You\'ve passed the \'debug\' parameter so we\'re pausing'
 | 
			
		||||
          + ' to let you look at logs or whatever it is that you intended to do.'
 | 
			
		||||
          + '<br/><br/>Continue with redirect: <a href="' + redirect + '">' + redirect + '</' + 'a>';
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onError(err) {
 | 
			
		||||
      var redirect = params.redirect_uri + '?' + OAUTH3.query.stringify({
 | 
			
		||||
        state: params.state
 | 
			
		||||
      , error: err.code
 | 
			
		||||
      , error_description: err.message
 | 
			
		||||
      , error_uri: err.uri
 | 
			
		||||
      , debug: params.debug || undefined
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      doRedirect(redirect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onSuccess(urlsafe64, hasSub) {
 | 
			
		||||
      if (params.debug) {
 | 
			
		||||
        console.log(prefix, 'directives');
 | 
			
		||||
        console.log(resp);
 | 
			
		||||
 | 
			
		||||
        console.log(prefix, 'base64');
 | 
			
		||||
        console.log(urlsafe64);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // TODO try postMessage back to redirect_uri domain right here
 | 
			
		||||
      // window.postMessage();
 | 
			
		||||
 | 
			
		||||
      // TODO SECURITY make sure it's https NOT http
 | 
			
		||||
      // NOTE: this can be only up to 2,083 characters
 | 
			
		||||
      redirect = params.redirect_uri + '?' + OAUTH3.query.stringify({
 | 
			
		||||
        state: params.state
 | 
			
		||||
      , directives: oldRpc ? urlsafe64 : undefined
 | 
			
		||||
      , data: !oldRpc ? urlsafe64 : undefined
 | 
			
		||||
      , sub: hasSub && sub || undefined
 | 
			
		||||
      , debug: params.debug || undefined
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      doRedirect(redirect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (params.debug) {
 | 
			
		||||
      console.warn(prefix, "DEBUG MODE ENABLED. Automatic redirects disabled.");
 | 
			
		||||
 | 
			
		||||
      console.log(prefix, 'hash||search:');
 | 
			
		||||
      console.log(window.location.hash || window.location.search);
 | 
			
		||||
 | 
			
		||||
      console.log(prefix, 'params:');
 | 
			
		||||
      console.log(params);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ('rpc' !== params.response_type) {
 | 
			
		||||
      err = new Error("response_type '" + params.response_type + "' is not supported");
 | 
			
		||||
      err.code = "E_RESPONSE_TYPE";
 | 
			
		||||
      // TODO err.uri
 | 
			
		||||
      onError(err);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (params.action) {
 | 
			
		||||
      oldRpc = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var loco = window.location.href.replace(/\/\.well-known.*/, '');
 | 
			
		||||
    //var loco = 'sso.hellabit.com';
 | 
			
		||||
    var resp;
 | 
			
		||||
    if (/localstorage/i.test(params._scheme)) {
 | 
			
		||||
      if (sub) {
 | 
			
		||||
        subData = localStorage.getItem(sub + '@oauth3.org:issuer');
 | 
			
		||||
      }
 | 
			
		||||
      resp = subData || localStorage.getItem('oauth3.org:issuer') || loco;
 | 
			
		||||
      onSuccess(resp, subData && true);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var fileWhiteList = [
 | 
			
		||||
      '.well-known/oauth3/directives.json'
 | 
			
		||||
    , '.well-known/oauth3/scopes.json'
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    if (-1 === fileWhiteList.indexOf(params._pathname)) {
 | 
			
		||||
      err = new Error("No access to requested file: " + params._pathname);
 | 
			
		||||
      err.code = "E_ACCESS_DENIED"
 | 
			
		||||
      // TODO err.uri
 | 
			
		||||
      onError(err);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    OAUTH3.request({ url: params._pathname.replace(/^\.well-known\/oauth3\//, '') }).then(function (resp) {
 | 
			
		||||
      urlsafe64 = OAUTH3._base64.encodeUrlSafe(JSON.stringify(resp.data, null, 0));
 | 
			
		||||
 | 
			
		||||
      onSuccess(urlsafe64);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    }());
 | 
			
		||||
  </script>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
@ -1,26 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
      "oauth3_authn": "Basic secure authentication"
 | 
			
		||||
    , "auth@oauth3.org": "Basic secure authentication"
 | 
			
		||||
    , "wallet": "Access to payments and subscriptions"
 | 
			
		||||
    , "bucket": "Access to file storage"
 | 
			
		||||
    , "db": "Access to app data"
 | 
			
		||||
    , "domains": "Domain registration (and Glue and NS records)"
 | 
			
		||||
    , "domains@oauth3.org": "Domain registration (and Glue and NS records)" 
 | 
			
		||||
    , "domains:glue": "Glue Record management (for vanity nameservers)"
 | 
			
		||||
    , "domains:ns": "Name Server management"
 | 
			
		||||
    , "dns": "DNS records (A/AAAA, TXT, SRV, MX, etc)"
 | 
			
		||||
 | 
			
		||||
    , "hello@example.com": "Hello World Example Access"
 | 
			
		||||
    , "authn@oauth3.org": "Basic secure authentication"
 | 
			
		||||
    , "wallet@oauth3.org": "Access to payments and subscriptions"
 | 
			
		||||
    , "bucket@oauth3.org": "Access to file storage"
 | 
			
		||||
    , "db@oauth3.org": "Access to app data"
 | 
			
		||||
    , "domains@oauth3.org": "Domain registration (and Glue and NS records)" 
 | 
			
		||||
    , "domains:glue@oauth3.org": "Glue Record management (for vanity nameservers)"
 | 
			
		||||
    , "domains:ns@oauth3.org": "Name Server management"
 | 
			
		||||
    , "dns@oauth3.org": "DNS records (A/AAAA, TXT, SRV, MX, etc)"
 | 
			
		||||
    , "www@daplie.com": "Websites and webapps"
 | 
			
		||||
 | 
			
		||||
    , "*": "FULL ACCOUNT ACCESS"
 | 
			
		||||
    }
 | 
			
		||||
@ -1,96 +0,0 @@
 | 
			
		||||
(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);
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}());
 | 
			
		||||
							
								
								
									
										266
									
								
								oauth3.core.js
									
									
									
									
									
								
							
							
						
						
									
										266
									
								
								oauth3.core.js
									
									
									
									
									
								
							@ -1,4 +1,4 @@
 | 
			
		||||
/ * global Promise */
 | 
			
		||||
/* global Promise */
 | 
			
		||||
;(function (exports) {
 | 
			
		||||
  'use strict';
 | 
			
		||||
 | 
			
		||||
@ -169,7 +169,7 @@
 | 
			
		||||
    }
 | 
			
		||||
  , scope: {
 | 
			
		||||
      parse: function (scope) {
 | 
			
		||||
        return (scope||'').toString().split(/[+, ]+/g);
 | 
			
		||||
        return (scope||'').split(/[+, ]+/g);
 | 
			
		||||
      }
 | 
			
		||||
    , stringify: function (scope) {
 | 
			
		||||
        if (Array.isArray(scope)) {
 | 
			
		||||
@ -294,46 +294,34 @@
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  , urls: {
 | 
			
		||||
      rpc: function (providerUri, opts) {
 | 
			
		||||
      discover: function (providerUri, opts) {
 | 
			
		||||
        if (!providerUri) {
 | 
			
		||||
          throw new Error("cannot run rpc without providerUri");
 | 
			
		||||
          throw new Error("cannot discover without providerUri");
 | 
			
		||||
        }
 | 
			
		||||
        if (!opts.client_id) {
 | 
			
		||||
          throw new Error("cannot run rpc without options.client_id");
 | 
			
		||||
          throw new Error("cannot discover without options.client_id");
 | 
			
		||||
        }
 | 
			
		||||
        var clientId = OAUTH3.url.normalize(opts.client_id || opts.client_uri);
 | 
			
		||||
        providerUri = OAUTH3.url.normalize(providerUri);
 | 
			
		||||
 | 
			
		||||
        var params = {
 | 
			
		||||
          state: opts.state || OAUTH3.utils.randomState()
 | 
			
		||||
          action: 'directives'
 | 
			
		||||
        , state: opts.state || OAUTH3.utils.randomState()
 | 
			
		||||
        , redirect_uri: clientId + (opts.client_callback_path || '/.well-known/oauth3/callback.html#/')
 | 
			
		||||
        , response_type: 'rpc'
 | 
			
		||||
        , _method: 'GET'
 | 
			
		||||
        , _scheme: opts._scheme
 | 
			
		||||
        , _pathname: opts._pathname
 | 
			
		||||
        , _pathname: '.well-known/oauth3/directives.json'
 | 
			
		||||
        , debug: opts.debug || undefined
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        var toRequest = {
 | 
			
		||||
        var result = {
 | 
			
		||||
          url: providerUri + '/.well-known/oauth3/#/?' + OAUTH3.query.stringify(params)
 | 
			
		||||
        , state: params.state
 | 
			
		||||
        , method: 'GET'
 | 
			
		||||
        , query: params
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return toRequest;
 | 
			
		||||
      }
 | 
			
		||||
    , broker: function (providerUri, opts) {
 | 
			
		||||
        opts._scheme = "localstorage:";
 | 
			
		||||
        opts._pathname = "issuer";
 | 
			
		||||
        return OAUTH3.urls.rpc(providerUri, opts);
 | 
			
		||||
      }
 | 
			
		||||
    , discover: function (providerUri, opts) {
 | 
			
		||||
        return OAUTH3.urls.directives(providerUri, opts);
 | 
			
		||||
      }
 | 
			
		||||
    , directives: function (providerUri, opts) {
 | 
			
		||||
        opts._pathname = ".well-known/oauth3/scopes.json";
 | 
			
		||||
        return OAUTH3.urls.rpc(providerUri, opts);
 | 
			
		||||
        return result;
 | 
			
		||||
      }
 | 
			
		||||
    , implicitGrant: function (directive, opts) {
 | 
			
		||||
        //
 | 
			
		||||
@ -542,14 +530,6 @@
 | 
			
		||||
          return OAUTH3.PromiseA.resolve(OAUTH3._hooks.directives.clear());
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    , scopes: {
 | 
			
		||||
        get: function(providerUri) {
 | 
			
		||||
          //TODO: retrieve cached scopes
 | 
			
		||||
        }
 | 
			
		||||
      , set: function(providerUri, scopes) {
 | 
			
		||||
          //TODO: cache scopes
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    , session: {
 | 
			
		||||
        refresh: function (oldSession, newSession) {
 | 
			
		||||
          var providerUri = oldSession.provider_uri;
 | 
			
		||||
@ -678,29 +658,9 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  , discoverScopes: function (providerUri, opts) {
 | 
			
		||||
      return OAUTH.scopes(providerUri, opts);
 | 
			
		||||
    }
 | 
			
		||||
  , scopes: function (providerUri, opts) {
 | 
			
		||||
      if (!providerUri) {
 | 
			
		||||
        throw new Error('oauth3.discoverScopes(providerUri, opts) received providerUri as :', providerUri);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      opts = opts || {};
 | 
			
		||||
      opts._pathname = ".well-known/oauth3/scopes.json";
 | 
			
		||||
 | 
			
		||||
      //TODO: add caching
 | 
			
		||||
 | 
			
		||||
      return OAUTH3._rpcHelper(providerUri, opts).then(function(scopes) {
 | 
			
		||||
        return scopes;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  , discover: function (providerUri, opts) {
 | 
			
		||||
      return OAUTH3.directives(providerUri, opts);
 | 
			
		||||
    }
 | 
			
		||||
  , directives: function (providerUri, opts) {
 | 
			
		||||
      if (!providerUri) {
 | 
			
		||||
        throw new Error('oauth3.discover(providerUri, opts) received providerUri as :', providerUri);
 | 
			
		||||
        throw new Error('oauth3.discover(providerUri, opts) received providerUri as ' + providerUri);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return OAUTH3.hooks.directives.get(providerUri).then(function (directives) {
 | 
			
		||||
@ -708,8 +668,7 @@
 | 
			
		||||
          return directives;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        opts._pathname = ".well-known/oauth3/directives.json";
 | 
			
		||||
        return OAUTH3._rpcHelper(providerUri, opts).then(function (directives) {
 | 
			
		||||
        return OAUTH3._discoverHelper(providerUri, opts).then(function (directives) {
 | 
			
		||||
          directives.azp = directives.azp || OAUTH3.url.normalize(providerUri);
 | 
			
		||||
          directives.issuer = directives.issuer || OAUTH3.url.normalize(providerUri);
 | 
			
		||||
          directives.api = OAUTH3.url.normalize((directives.api||':hostname').replace(/:hostname/, OAUTH3.uri.normalize(directives.issuer) || OAUTH3.uri.normalize(providerUri)));
 | 
			
		||||
@ -718,8 +677,8 @@
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  , _rpcHelper: function(providerUri, opts) {
 | 
			
		||||
      return OAUTH3._browser.rpc(providerUri, opts);
 | 
			
		||||
  , _discoverHelper: function(providerUri, opts) {
 | 
			
		||||
      return OAUTH3._browser.discover(providerUri, opts);
 | 
			
		||||
    }
 | 
			
		||||
  , request: function (preq, opts) {
 | 
			
		||||
      function fetch() {
 | 
			
		||||
@ -747,21 +706,6 @@
 | 
			
		||||
      */
 | 
			
		||||
      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) {
 | 
			
		||||
      var promise;
 | 
			
		||||
      var providerUri = directives.azp || directives.issuer || directives;
 | 
			
		||||
@ -872,19 +816,12 @@
 | 
			
		||||
        });
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  , logout: function(issuerUri, opts) {
 | 
			
		||||
      var directives;
 | 
			
		||||
      if ('string' !== typeof issuerUri) {
 | 
			
		||||
        directives = issuerUri;
 | 
			
		||||
        return OAUTH3._logoutHelper(directives, opts);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return OAUTH3.hooks.directives.get(issuerUri).then(function (directives) {
 | 
			
		||||
  , logout: function(providerUri, opts) {
 | 
			
		||||
      return OAUTH3.hooks.directives.get(providerUri).then(function (directives) {
 | 
			
		||||
        return OAUTH3._logoutHelper(directives, opts);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  , _logoutHelper: function(directives, opts) {
 | 
			
		||||
      var issuerUri = directives.issuer_uri || directives.provider_uri;
 | 
			
		||||
  , _logoutHelper: function(providerUri, directives, opts) {
 | 
			
		||||
      var logoutReq = OAUTH3.urls.logout(
 | 
			
		||||
        directives
 | 
			
		||||
      , { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location))
 | 
			
		||||
@ -907,10 +844,10 @@
 | 
			
		||||
 | 
			
		||||
        if (params.error) {
 | 
			
		||||
          // TODO directives.audience
 | 
			
		||||
          return OAUTH3.PromiseA.reject(OAUTH3.error.parse(directives.issuer /*issuerUri*/, params));
 | 
			
		||||
          return OAUTH3.PromiseA.reject(OAUTH3.error.parse(directives.issuer /*providerUri*/, params));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        OAUTH3.hooks.session.clear(issuerUri);
 | 
			
		||||
        OAUTH3.hooks.session.clear(providerUri);
 | 
			
		||||
        return params;
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
@ -921,50 +858,40 @@
 | 
			
		||||
    //
 | 
			
		||||
  , _browser: {
 | 
			
		||||
      window: 'undefined' !== typeof window ? window : null
 | 
			
		||||
    , rpc: function(providerUri, opts) {
 | 
			
		||||
      // TODO we don't need to include this if we're using jQuery or angular
 | 
			
		||||
    , discover: function(providerUri, opts) {
 | 
			
		||||
        opts = opts || {};
 | 
			
		||||
        providerUri = OAUTH3.url.normalize(providerUri);
 | 
			
		||||
 | 
			
		||||
        // TODO SECURITY should we whitelist our own self?
 | 
			
		||||
        if (OAUTH3.uri.normalize(providerUri).replace(/\/.*/, '') === OAUTH3.uri.normalize(OAUTH3._browser.window.location.hostname)) {
 | 
			
		||||
          console.warn("It looks like you're a provider trying to run rpc on yourself,"
 | 
			
		||||
          console.warn("It looks like you're a provider checking for your own directive,"
 | 
			
		||||
            + " so we we're just gonna use"
 | 
			
		||||
            + " OAUTH3.request({ method: 'GET', url: "
 | 
			
		||||
            + "'" + opts._pathname + "' })");
 | 
			
		||||
 | 
			
		||||
          if (/localstorage/i.test(opts._scheme)) {
 | 
			
		||||
            return OAUTH3.PromiseA.resolve(localStorage.getItem(opts._pathname));
 | 
			
		||||
          }
 | 
			
		||||
          else {
 | 
			
		||||
            return OAUTH3.request({
 | 
			
		||||
              method: 'GET'
 | 
			
		||||
            , url: OAUTH3.url.normalize(providerUri) + '/' + opts._pathname // '/.well-known/oauth3/' + discoverFile
 | 
			
		||||
            }).then(function (resp) {
 | 
			
		||||
              return resp.data;
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
            + " OAUTH3.request({ method: 'GET', url: '.well-known/oauth3/directive.json' })");
 | 
			
		||||
          return OAUTH3.request({
 | 
			
		||||
            method: 'GET'
 | 
			
		||||
          , url: OAUTH3.url.normalize(providerUri) + '/.well-known/oauth3/directives.json'
 | 
			
		||||
          }).then(function (resp) {
 | 
			
		||||
            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..."
 | 
			
		||||
            + " this probably won't end well");
 | 
			
		||||
          console.warn(opts.client_id || opts.client_uri, OAUTH3._browser.window.location.hostname);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var discReq = OAUTH3.urls[opts._rpc || 'rpc'](
 | 
			
		||||
        var discReq = OAUTH3.urls.discover(
 | 
			
		||||
          providerUri
 | 
			
		||||
        , { client_id: (opts.client_id || opts.client_uri || OAUTH3.clientUri(OAUTH3._browser.window.location))
 | 
			
		||||
          , windowType: opts.broker && opts.windowType || 'background'
 | 
			
		||||
          , broker: opts.broker
 | 
			
		||||
          , state: opts._state || undefined
 | 
			
		||||
          , debug: opts.debug
 | 
			
		||||
          , _scheme: opts._scheme
 | 
			
		||||
          , _pathname: opts._pathname
 | 
			
		||||
          , _method: opts._method
 | 
			
		||||
          }
 | 
			
		||||
        );
 | 
			
		||||
        opts._state = discReq.state;
 | 
			
		||||
        //var discReq = OAUTH3.urls.rpc(providerUri, opts);
 | 
			
		||||
        //var discReq = OAUTH3.urls.discover(providerUri, opts);
 | 
			
		||||
 | 
			
		||||
        // hmm... we're gonna need a broker for this since switching windows is distracting,
 | 
			
		||||
        // popups are obnoxious, iframes are sometimes blocked, and most servers don't implement CORS
 | 
			
		||||
@ -974,36 +901,27 @@
 | 
			
		||||
        // TODO allow node to open a desktop browser window
 | 
			
		||||
        opts._windowType = opts.windowType;
 | 
			
		||||
        opts.windowType = opts.windowType || 'background';
 | 
			
		||||
        return OAUTH3._browser.testPixel(providerUri).then(function () {
 | 
			
		||||
          return OAUTH3._browser.frameRequest(
 | 
			
		||||
            OAUTH3.url.resolve(providerUri, discReq.url)
 | 
			
		||||
          , discReq.state
 | 
			
		||||
            // why not just pass opts whole?
 | 
			
		||||
          , { windowType: opts.windowType
 | 
			
		||||
            , reuseWindow: opts.broker && '-broker'
 | 
			
		||||
            , debug: opts.debug
 | 
			
		||||
            }
 | 
			
		||||
          ).then(function (params) {
 | 
			
		||||
            opts.windowType = opts._windowType;
 | 
			
		||||
        return OAUTH3._browser.frameRequest(
 | 
			
		||||
          OAUTH3.url.resolve(providerUri, discReq.url)
 | 
			
		||||
        , discReq.state
 | 
			
		||||
          // why not just pass opts whole?
 | 
			
		||||
        , { windowType: opts.windowType
 | 
			
		||||
          , reuseWindow: opts.broker && '-broker'
 | 
			
		||||
          , debug: opts.debug
 | 
			
		||||
          }
 | 
			
		||||
        ).then(function (params) {
 | 
			
		||||
          opts.windowType = opts._windowType;
 | 
			
		||||
 | 
			
		||||
            // caller will call OAUTH3._browser.closeFrame(discReq.state, { debug: opts.debug || params.debug });
 | 
			
		||||
            if (params.error) {
 | 
			
		||||
              // TODO directives.issuer || directives.audience
 | 
			
		||||
              return OAUTH3.PromiseA.reject(OAUTH3.error.parse(providerUri, params));
 | 
			
		||||
            }
 | 
			
		||||
          // caller will call OAUTH3._browser.closeFrame(discReq.state, { debug: opts.debug || params.debug });
 | 
			
		||||
          if (params.error) {
 | 
			
		||||
            // TODO directives.issuer || directives.audience
 | 
			
		||||
            return OAUTH3.PromiseA.reject(OAUTH3.error.parse(providerUri, params));
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
            // TODO params should have response_type indicating json, binary, etc
 | 
			
		||||
            var result;
 | 
			
		||||
            try {
 | 
			
		||||
              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;
 | 
			
		||||
          });
 | 
			
		||||
          // TODO params should have response_type indicating json, binary, etc
 | 
			
		||||
          var directives = JSON.parse(OAUTH3._base64.decodeUrlSafe(params.result || params.directives));
 | 
			
		||||
          // caller will call OAUTH3.hooks.directives.set(providerUri, directives);
 | 
			
		||||
          return directives;
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    , request: function (preq, _sys) {
 | 
			
		||||
@ -1102,28 +1020,6 @@
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    , 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) {
 | 
			
		||||
        opts = opts || {};
 | 
			
		||||
        var previousFrame = OAUTH3._browser._frames[state];
 | 
			
		||||
@ -1134,10 +1030,11 @@
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var timeout = opts.timeout;
 | 
			
		||||
        if ('background' === windowType) {
 | 
			
		||||
          if (!timeout) {
 | 
			
		||||
            timeout = 7 * 1000;
 | 
			
		||||
          }
 | 
			
		||||
        if (opts.debug) {
 | 
			
		||||
          timeout = timeout || 3 * 60 * 1000;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          timeout = timeout || ('background' === windowType ? 15 * 1000 : 3 * 60 * 1000);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return new OAUTH3.PromiseA(function (resolve, reject) {
 | 
			
		||||
@ -1159,16 +1056,14 @@
 | 
			
		||||
            cleanup();
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          if (timeout) {
 | 
			
		||||
            tok = setTimeout(function () {
 | 
			
		||||
              var err = new Error(
 | 
			
		||||
                "the '" + windowType + "' request did not complete within " + Math.round(timeout / 1000) + "s"
 | 
			
		||||
              );
 | 
			
		||||
              err.code = "E_TIMEOUT";
 | 
			
		||||
              reject(err);
 | 
			
		||||
              cleanup();
 | 
			
		||||
            }, timeout);
 | 
			
		||||
          }
 | 
			
		||||
          tok = setTimeout(function () {
 | 
			
		||||
            var err = new Error(
 | 
			
		||||
              "the '" + windowType + "' request did not complete within " + Math.round(timeout / 1000) + "s"
 | 
			
		||||
            );
 | 
			
		||||
            err.code = "E_TIMEOUT";
 | 
			
		||||
            reject(err);
 | 
			
		||||
            cleanup();
 | 
			
		||||
          }, timeout);
 | 
			
		||||
 | 
			
		||||
          setTimeout(function () {
 | 
			
		||||
            if (!OAUTH3._browser._frames[state]) {
 | 
			
		||||
@ -1371,23 +1266,6 @@
 | 
			
		||||
  OAUTH3.utils = {
 | 
			
		||||
    clientUri: OAUTH3.clientUri
 | 
			
		||||
  , 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
 | 
			
		||||
  , uri: OAUTH3.uri
 | 
			
		||||
  , url: OAUTH3.url
 | 
			
		||||
@ -1555,25 +1433,23 @@
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    , logout: function (opts) {
 | 
			
		||||
        var me = this;
 | 
			
		||||
        me._session = false;
 | 
			
		||||
        this._session = false;
 | 
			
		||||
        opts = opts || {};
 | 
			
		||||
        return OAUTH3.hooks.session.get(me._identityProviderUri).then(function (session) {
 | 
			
		||||
          opts.client_uri = me._clientUri;
 | 
			
		||||
          opts.client_id = me._clientUri;
 | 
			
		||||
        return OAUTH3.hooks.session.get(this._identityProviderUri).then(function (session) {
 | 
			
		||||
          opts.client_uri = this._clientUri;
 | 
			
		||||
          opts.client_id = this._clientUri;
 | 
			
		||||
          opts.session = session;
 | 
			
		||||
 | 
			
		||||
          return OAUTH3.logout(me._identityProviderUri, opts);
 | 
			
		||||
          return OAUTH3.logout(this._identityProviderUri, opts);
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    , api: function (api, opts) {
 | 
			
		||||
        var me = this;
 | 
			
		||||
        opts = opts || {};
 | 
			
		||||
        return OAUTH3.hooks.session.get(me._identityProviderUri).then(function (session) {
 | 
			
		||||
        return OAUTH3.hooks.session.get(this._identityProviderUri).then(function (session) {
 | 
			
		||||
          opts.api = api;
 | 
			
		||||
          opts.session = session;
 | 
			
		||||
 | 
			
		||||
          return OAUTH3.api(me._resourceProviderDirectives.api, opts);
 | 
			
		||||
          return OAUTH3.api(this._resourceProviderDirectives.api, opts);
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
    , pkg: function (pkgname) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										125
									
								
								oauth3.issuer.js
									
									
									
									
									
								
							
							
						
						
									
										125
									
								
								oauth3.issuer.js
									
									
									
									
									
								
							@ -192,9 +192,8 @@ OAUTH3.urls.grants = function (directive, opts) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var url = OAUTH3.url.resolve(directive.api, grantsDir.url)
 | 
			
		||||
    .replace(/(:azp|:client_id)/g, OAUTH3.uri.normalize(opts.client_id || opts.client_uri))
 | 
			
		||||
    .replace(/(:sub|:account_id)/g, opts.session.token.sub || 'ISSUER:GRANT:TOKEN_SUB:UNDEFINED')
 | 
			
		||||
    .replace(/(:azp|:client_id)/g, !opts.all && OAUTH3.uri.normalize(opts.client_id || opts.client_uri) || '')
 | 
			
		||||
    .replace(/\/\/$/, '/') // if there's a double slash due to the sub not existing
 | 
			
		||||
    ;
 | 
			
		||||
  var data = {
 | 
			
		||||
    client_id: opts.client_id
 | 
			
		||||
@ -218,7 +217,6 @@ OAUTH3.urls.grants = function (directive, opts) {
 | 
			
		||||
  , session: opts.session
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
//OAUTH3.urls.accessToken = function (directive, opts)
 | 
			
		||||
OAUTH3.urls.clientToken = function (directive, opts) {
 | 
			
		||||
  var tokenDir = directive.access_token;
 | 
			
		||||
  if (!tokenDir) {
 | 
			
		||||
@ -295,7 +293,7 @@ OAUTH3.urls.credentialMeta = function (directive, opts) {
 | 
			
		||||
      .replace(':id', opts.email)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
OAUTH3.authn = OAUTH3.authn || {};
 | 
			
		||||
OAUTH3.authn = {};
 | 
			
		||||
OAUTH3.authn.loginMeta = function (directive, opts) {
 | 
			
		||||
  var url = OAUTH3.urls.credentialMeta(directive, opts);
 | 
			
		||||
  return OAUTH3.request({
 | 
			
		||||
@ -371,8 +369,8 @@ OAUTH3.authn.resourceOwnerPassword = function (directive, opts) {
 | 
			
		||||
OAUTH3.authz = {};
 | 
			
		||||
OAUTH3.authz.scopes = function (providerUri, session, clientParams) {
 | 
			
		||||
  var clientUri = OAUTH3.uri.normalize(clientParams.client_uri || OAUTH3._browser.window.document.referrer);
 | 
			
		||||
  var scope = clientParams.scope || 'authn@oauth3.org';
 | 
			
		||||
  if ('authn@oauth3.org' === scope.toString()) {
 | 
			
		||||
  var scope = clientParams.scope || 'oauth3_authn';
 | 
			
		||||
  if ('oauth3_authn' === scope) {
 | 
			
		||||
    // implicit ppid grant is automatic
 | 
			
		||||
    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
 | 
			
		||||
@ -434,7 +432,7 @@ OAUTH3.authz.grants = function (providerUri, opts) {
 | 
			
		||||
    }
 | 
			
		||||
    // the responses for GET and POST requests are now the same, so we should alway be able to
 | 
			
		||||
    // use the response and save it the same way.
 | 
			
		||||
    if (opts.all || ('GET' !== opts.method && 'POST' !== opts.method)) {
 | 
			
		||||
    if ('GET' !== opts.method && 'POST' !== opts.method) {
 | 
			
		||||
      return grants;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -574,85 +572,68 @@ OAUTH3.authz.redirectWithToken = function (providerUri, session, clientParams, s
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
OAUTH3.requests = {};
 | 
			
		||||
//OAUTH3.accounts = {};
 | 
			
		||||
OAUTH3.requests.accounts = {};
 | 
			
		||||
OAUTH3.urls.accounts = {};
 | 
			
		||||
OAUTH3.urls.accounts._ = function (directives, directive, session, opts) {
 | 
			
		||||
  opts = opts || {};
 | 
			
		||||
  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'
 | 
			
		||||
OAUTH3.requests.accounts.update = function (directive, session, opts) {
 | 
			
		||||
  var dir = directive.update_account || {
 | 
			
		||||
    method: 'POST'
 | 
			
		||||
  , url: OAUTH3.url.normalize(directive.api) + '/api/issuer@oauth3.org/accounts/:accountId'
 | 
			
		||||
  , bearer: 'Bearer'
 | 
			
		||||
  };
 | 
			
		||||
  var url = dir.url
 | 
			
		||||
    .replace(/:accountId/, opts.accountId || '')
 | 
			
		||||
    .replace(/\/$/, '')
 | 
			
		||||
    .replace(/:accountId/, opts.accountId)
 | 
			
		||||
  ;
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    url: url
 | 
			
		||||
    //, method: dir.method || 'POST'
 | 
			
		||||
  , session: session
 | 
			
		||||
    /*
 | 
			
		||||
  return OAUTH3.request({
 | 
			
		||||
    method: dir.method || 'POST'
 | 
			
		||||
  , url: url
 | 
			
		||||
  , headers: {
 | 
			
		||||
      'Authorization': (dir.bearer || 'Bearer') + ' ' + (session.access_token || session.accessToken)
 | 
			
		||||
      'Authorization': (dir.bearer || 'Bearer') + ' ' + session.accessToken
 | 
			
		||||
    }
 | 
			
		||||
    */
 | 
			
		||||
  };
 | 
			
		||||
  , json: {
 | 
			
		||||
      name: opts.name
 | 
			
		||||
    , comment: opts.comment
 | 
			
		||||
    , displayName: opts.displayName
 | 
			
		||||
    , priority: opts.priority
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
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
 | 
			
		||||
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'
 | 
			
		||||
  };
 | 
			
		||||
  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 = {
 | 
			
		||||
  var data = {
 | 
			
		||||
    // TODO fix the server to just use one scheme
 | 
			
		||||
    // account = { nick, self: { comment, username } }
 | 
			
		||||
    // account = { name, comment, display_name, priority }
 | 
			
		||||
    credentials: credentials
 | 
			
		||||
  , profile: profile
 | 
			
		||||
    // 'account' is deprecated in favor of 'profile'
 | 
			
		||||
  , account: profile
 | 
			
		||||
    // 'logins' is deprecated in favor of 'credentials'
 | 
			
		||||
  , logins: credentials
 | 
			
		||||
    account: {
 | 
			
		||||
      nick: account.display_name
 | 
			
		||||
    , name: account.name
 | 
			
		||||
    , comment: account.comment
 | 
			
		||||
    , display_name: account.display_name
 | 
			
		||||
    , priority: account.priority
 | 
			
		||||
    , 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;
 | 
			
		||||
};
 | 
			
		||||
OAUTH3.requests.accounts.get = function (directives, session) {
 | 
			
		||||
  var urlObj = OAUTH3.urls.accounts.get(directives, session);
 | 
			
		||||
  return OAUTH3.request(urlObj);
 | 
			
		||||
};
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
  return OAUTH3.request({
 | 
			
		||||
    method: dir.method || 'POST'
 | 
			
		||||
  , url: dir.url
 | 
			
		||||
  , session: session
 | 
			
		||||
  , data: data
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
OAUTH3.hooks.grants = {
 | 
			
		||||
 | 
			
		||||
@ -27,10 +27,10 @@
 | 
			
		||||
 | 
			
		||||
  OAUTH3.authz.scopes = function () {
 | 
			
		||||
    return OAUTH3.PromiseA.resolve({
 | 
			
		||||
      pending: [ 'authn@oauth3.org' ]     // not yet accepted
 | 
			
		||||
    , granted: []                         // all granted, ever
 | 
			
		||||
    , requested: [ 'authn@oauth3.org' ]   // all requested, now
 | 
			
		||||
    , accepted: []                        // granted (ever) and requested (now)
 | 
			
		||||
      pending: ['oauth3_authn']   // not yet accepted
 | 
			
		||||
    , granted: []                 // all granted, ever
 | 
			
		||||
    , requested: ['oauth3_authn'] // all requested, now
 | 
			
		||||
    , accepted: []                // granted (ever) and requested (now)
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
  OAUTH3.authz.grants = function (providerUri, opts) {
 | 
			
		||||
 | 
			
		||||
@ -1 +0,0 @@
 | 
			
		||||
_apis
 | 
			
		||||
							
								
								
									
										71
									
								
								well-known/oauth3/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								well-known/oauth3/index.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
  <head>
 | 
			
		||||
    <style>
 | 
			
		||||
      body {
 | 
			
		||||
        background-color: #ffcccc;
 | 
			
		||||
      }
 | 
			
		||||
    </style>
 | 
			
		||||
  </head>
 | 
			
		||||
  <body>
 | 
			
		||||
  OAuth3 RPC
 | 
			
		||||
 | 
			
		||||
  <script src="../../assets/oauth3.org/oauth3.core.js"></script>
 | 
			
		||||
  <script>
 | 
			
		||||
    ;(function () {
 | 
			
		||||
    'use strict';
 | 
			
		||||
 | 
			
		||||
    // Taken from oauth3.core.js
 | 
			
		||||
 | 
			
		||||
    // TODO what about search within hash?
 | 
			
		||||
    var prefix = "(" + window.location.hostname + ") [.well-known/oauth3/]";
 | 
			
		||||
    var params = OAUTH3.query.parse(window.location.hash || window.location.search);
 | 
			
		||||
    if (params.debug) {
 | 
			
		||||
      console.warn(prefix, "DEBUG MODE ENABLED. Automatic redirects disabled.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    console.log(prefix, 'hash||search:');
 | 
			
		||||
    console.log(window.location.hash || window.location.search);
 | 
			
		||||
 | 
			
		||||
    console.log(prefix, 'params:');
 | 
			
		||||
    console.log(params);
 | 
			
		||||
 | 
			
		||||
    OAUTH3.request({ url: 'directives.json' }).then(function (resp) {
 | 
			
		||||
      var urlsafe64 = OAUTH3._base64.encodeUrlSafe(JSON.stringify(resp.data, null, 0));
 | 
			
		||||
      var redirect;
 | 
			
		||||
 | 
			
		||||
      console.log(prefix, 'directives');
 | 
			
		||||
      console.log(resp);
 | 
			
		||||
 | 
			
		||||
      console.log(prefix, 'base64');
 | 
			
		||||
      console.log(urlsafe64);
 | 
			
		||||
 | 
			
		||||
      // TODO try postMessage back to redirect_uri domain right here
 | 
			
		||||
      // window.postMessage();
 | 
			
		||||
 | 
			
		||||
      // TODO make sure it's https NOT http
 | 
			
		||||
      // NOTE: this can be only up to 2,083 characters
 | 
			
		||||
      console.log(prefix, 'params.redirect_uri:', params.redirect_uri);
 | 
			
		||||
      redirect = params.redirect_uri + '?' + OAUTH3.query.stringify({
 | 
			
		||||
        state: params.state
 | 
			
		||||
      , directives: urlsafe64
 | 
			
		||||
      , debug: params.debug || undefined
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      console.log(prefix, 'redirect');
 | 
			
		||||
      console.log(redirect);
 | 
			
		||||
      if (!params.debug) {
 | 
			
		||||
        window.location = redirect;
 | 
			
		||||
      } else {
 | 
			
		||||
        // yes, we're violating the security lint with purpose
 | 
			
		||||
        document.body.innerHTML += window.location.host + window.location.pathname
 | 
			
		||||
          + '<br/><br/>You\'ve passed the \'debug\' parameter so we\'re pausing'
 | 
			
		||||
          + ' to let you look at logs or whatever it is that you intended to do.'
 | 
			
		||||
          + '<br/><br/>Continue with redirect: <a href="' + redirect + '">' + redirect + '</' + 'a>';
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    }());
 | 
			
		||||
  </script>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user