diff --git a/README.md b/README.md
index 7026037..17dcd44 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ Installation
**Advanced Installation with `git`**
-```
+```bash
# Navigate to your web site or web app
pushd /path/to/your/web/app
@@ -45,7 +45,7 @@ ln -sf ../assets/org.oauth3/.well-known/oauth3 .well-known/oauth3
**Advanced Installation with `bower`**
-```
+```bash
# Install to bower_components
bower install oauth3
@@ -66,35 +66,145 @@ ln -sf ../bower_components/oauth3 assets/org.oauth3
Usage
-----
-Update your HTML to include the the following script tags:
+Update your HTML to include the the following script tag:
-```
-
-
+```html
+
```
-If you use jQuery you should also include
+You can create a very simple demo application like this:
-```
-
+```javascript
+var providerUri;
+
+
+// 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) {
+ providerUri = _providerUri;
+ return OAUTH3.discover(providerUri); // just to cache
+}
+
+
+// This opens up the login window for the specified provider
+//
+function onClickLogin() {
+
+ var opts = { client_uri: OAuth3.clientUri(window.location) };
+ return OAUTH3.implicitGrant(providerUri, opts).then(function (session) {
+
+ console.info('Authentication was Successful:');
+ console.log(session);
+
+ // You can use the PPID (or preferrably a hash of it) as the login for your app
+ // (it securely functions as both username and password which is known only by your app)
+ // If you use a hash of it as an ID, you can also use the PPID itself as a decryption key
+ //
+ console.info('Secure PPID (aka subject):', session.token.sub);
+
+ return OAUTH3.request({
+ url: 'https://oauth3.org/api/org.oauth3.provider/inspect_token'
+ , session: session
+ }).then(function (resp) {
+
+ console.info("Inspect Token:");
+ console.log(resp.data);
+
+ });
+
+ }, function (err) {
+ console.error('Authentication Failed:');
+ console.log(err);
+ });
+
+}
+
+// initialize the provider to be oauth3.org (or any compatible provider)
+//
+onChangeProvider('oauth3.org');
```
+### Compatibility with Frameworks and Libraries
+
+**jQuery**:
+
+You're all set. Nothing else is needed.
+
+**Angular 1**:
+
+We've created an `Oauth3` service just for you:
+
+```html
+
+```
+
+You can include that in addition to the standard file or,
+if you don't want an extra request, just paste it into your `app.js`.
Stable API
----------
+
+
+* `OAUTH3.utils.clientUri(window.location);` produces the default `client_uri` of your app (also used as `client_id`)
+* `OAUTH3.discover(providerUri, { client_id: clientUri });` Promises the config file for the provider and caches it in memory.
+* `OAUTH3.implicitGrant(providerUri, { client_id: clientUri })` returns a `session` with `session.token.sub` as the secure ppid.
+ * `debug: true` will cause the windows to not refresh automatically
+ * `windowType: 'popup'` will use a popup window to ask user for new permissions, if any
+ * `windowType: 'background'` will automatically log the user in (if all permissions have been accepted)
+* `OAUTH3.request({ method: 'GET', url: '', session: '', data: '' })` make an authenticated request to a resource
+* `OAUTH3.logout(providerUri, { client_id: clientUri, session: session })` opens a popup to confirm logout from the provider
+ * Note: you should probably clear your own storage (i.e. localStorage, indexedDb) whenever you call this
+* `OAUTH3.urls.discover(providerUri, { client_id: clientUri })` generates a correctly parameterized url
+* `OAUTH3.urls.implicitGrant(directives, { client_id: clientUri })` generates a correctly parameterized url
+* `OAUTH3.urls.refreshToken(directives, opts)` generates a correctly parameterized url
+ * `opts.client_id = clientUri`
+ * `opts.access_token = `
+ * `opts.refresh_token = `
+
+
+
+
+
+
+Staging API
+----------
+
+These APIs are NOT yet public, stable APIs, but they are good to be aware of
+and may help with debugging.
+
+DO NOT rely on them. Many of them WILL change (we just wanted to publish with things as they are).
+
Public utilities for browser and node.js:
-* `querystringify(query)`
-* `stringifyscope(scope)`
+* `OAUTH3.jwt`
+ * `OAUTH3.jwt.decode(''); // { iat, iss, aud, sub, exp, ttl }
-URL generation:
+* `OAUTH3.utils`
+ * `OAUTH3.utils.query.stringify({ access_token: '...', debug: true }); // access_token=...&debug=true`
+ * `OAUTH3.utils.scope.stringify([ 'profile', 'contacts' ]); // 'profile,contacts'`
+ * `OAUTH3.utils.uri.normalize('https://oauth3.org/connect/'); // 'oauth3.org/connect'`
+ * `OAUTH3.utils.url.normalize('oauth3.org/connect/'); // 'https://oauth3.org/connect'`
+ * `OAUTH3.utils.url.resolve('oauth3.org/connect/', '/api/'); // 'https://oauth3.org/connect/api'`
+ * `OAUTH3.utils.atob(''); // '' (typically json ascii)`
-* `authorizationCode`
-* `authorizationRedirect`
-* `implicitGrant`
-* `loginCode`
-* `resourceOwnerPassword`
+Internal API
+------------
+
+This APIs will absolutely change before they are made public
+(at the very least the leading `_` will be removed)
+
+* `OAUTH3.jwt`
+ * `OAUTH3.jwt.freshness(tokenMeta, staletimeSeconds, _now); // returns 'fresh', 'stale', or 'expired' (by seconds before expiry / ttl)
+
+* `OAUTH3.utils`
+ * `OAUTH3.utils.url._normalizePath('oauth3.org/connect/'); // 'oauth3.org/connect'`
+ * `OAUTH3.utils._urlSafeBase64ToBase64(b64); // makes base64 safe for window.atob`
+ * `OAUTH3.utils.randomState(); // a 128-bit crypto-random string`
+ * `OAUTH3.utils._insecureRandomState(); // a fallback for randomState() in old browsers`
+
+* `OAUTH3._browser` a collection of things a browser needs to perform requests
Roadmap
-------
@@ -115,6 +225,16 @@ Roadmap
* v1.3 - features
* remove grants
+URL generation:
+
+* `authorizationCode`
+* `authorizationRedirect`
+* `implicitGrant`
+* `loginCode`
+* `resourceOwnerPassword`
+
+
+
URI vs URL
----------
diff --git a/oauth3.ng.js b/oauth3.ng.js
new file mode 100644
index 0000000..b5fdefb
--- /dev/null
+++ b/oauth3.ng.js
@@ -0,0 +1,38 @@
+;(function () {
+'use strict';
+
+angular
+ .module('oauth3', [])
+ .service('Oauth3', [
+ '$timeout'
+ , '$q'
+ , function Oauth3($timeout, $q) {
+
+ var OAUTH3 = window.OAUTH3;
+
+ // We need to make angular's $q appear to be a standard Promise/A+
+ // fortunately, this is pretty easy
+ function PromiseAngularQ(fn) {
+ var d = $q.defer();
+
+ $timeout(function () {
+ fn(d.resolve, d.reject);
+ }, 0);
+
+ //this.then = d.promise.then;
+ //this.catch = d.promise.catch;
+ return d.promise;
+ }
+
+ //PromiseAngularQ.create = PromiseAngularQ;
+ PromiseAngularQ.resolve = $q.when;
+ PromiseAngularQ.reject = $q.reject;
+ PromiseAngularQ.all = $q.all;
+
+ OAUTH3.PromiseA = PromiseAngularQ;
+
+ window.ngOauth3 = OAUTH3;
+
+ return OAUTH3;
+ }]);
+}());