diff --git a/index.html b/index.html
index 6f813ae..f88a83c 100644
--- a/index.html
+++ b/index.html
@@ -166,7 +166,7 @@
             
             
             
-            
+            
           
         
 
@@ -244,6 +244,40 @@
               
             
 
+            
+              
+              
+              
+                Scopes: 
+                
+                (these are used to lookup the descriptions of grant permissions)
+              
+              
+                
+                
+
+                
+
+                
OAUTH3.urls.scope(directives, opts);
+                
+                
+
+                
OAUTH3.discoverScopes(directives, opts);
+
+                
+                
+              
+            
               
               
diff --git a/js/playground.js b/js/playground.js
index b1e7c2d..46ed82a 100644
--- a/js/playground.js
+++ b/js/playground.js
@@ -27,17 +27,25 @@
 		var vm = this;
 
     vm.clientUri = OAUTH3.clientUri(window.location);
-    vm.conf = { client_id: vm.clientUri, client_uri: vm.clientUri, provider_uri: vm.clientUri };
+    vm.conf = { debug: undefined, client_id: vm.clientUri, client_uri: vm.clientUri, provider_uri: vm.clientUri };
     vm.providerUri = vm.conf.client_uri;
     // map of things being debounced presently
     vm.debouncing = {};
     vm.defaults = { provider: vm.conf.provider_uri, directives: null };
+		vm.defaults.scopes = [
+			{ name: 'oauth3_authn', desc: "Basic secure authentication", checked: true }
+			//{ name: 'authn@oauth3.org', desc: "Basic secure authentication" }
+		, { name: 'photos@daplie.com', desc: "Access to photos" }
+		, { name: 'dns', desc: "DNS records (A/AAAA, TXT, SRV, MX, etc)" }
+		, { name: '*', desc: "FULL ACCOUNT ACCESS" }
+		];
 
     vm.form = {};
     vm.form.id = '';
     vm.form.subject = '';
     vm.form.userProvider = '';
     vm.form.provider = '';
+    vm.form.scopes = '';
 
     vm.locks = {};
     vm.validated = {};
@@ -126,6 +134,34 @@
         vm.fn.changeUser();
       }
     };
+    vm.fn.updateDebug = function () {
+      if (!vm.conf.debug) {
+        vm.conf.debug = undefined;
+      }
+    };
+    vm.fn.updateScopes = function () {
+      var scopes = {};
+
+      (vm.scopes && vm.scopes.split(',') || []).forEach(function (name) {
+        scopes[name] = true;
+      });
+
+      vm.defaults.scopes.forEach(function (scope) {
+        if (scope.checked) {
+          scopes[scope.name] = true;
+        } else {
+          scopes[scope.name] = false;
+        }
+      });
+
+      vm.form.scopes = Object.keys(scopes).filter(function (key) {
+        return scopes[key];
+      }).map(function (key) {
+        return key;
+      }).join(',');
+
+      vm.api.urls.implicitGrant();
+    };
 
     vm.fn.lock = function () {
       vm._working = true;
@@ -167,6 +203,21 @@
       }
     };
     vm.api._discoverCount = 0;
+    vm.api.urls = {};
+    vm.api.urls.implicitGrant = function (provider) {
+      if (!vm.directives) {
+        console.log('[DEBUG] skipping implicit grant due to missing directives');
+        return;
+      }
+      var opts = {
+        client_uri: vm.conf.client_uri
+      , subject: vm.form.subject || undefined
+      , debug: vm.conf.debug || undefined
+      , scope: vm.form.scopes || undefined
+      };
+      var implicitGrantObj = OAUTH3.urls.implicitGrant(vm.directives, opts);
+      vm.implicitGrantUrl = (OAUTH3.url.normalize(provider || vm.form.provider) + '/' + implicitGrantObj.url).replace(implicitGrantObj.state, '{{random}}');
+    }
     vm.api.discover = function () {
       vm.directives = null;
       vm.validated.provider = '';
@@ -192,13 +243,7 @@
         vm.validated.provider = provider;
         vm.directives = dir;
 
-        var opts = {
-          client_uri: vm.conf.client_uri
-        , subject: vm.form.subject || undefined
-        , debug: vm.debug || undefined
-        };
-        vm.implicitGrantObj = OAUTH3.urls.implicitGrant(vm.directives, opts);
-        vm.implicitGrantUrl = (OAUTH3.url.normalize(provider) + '/' + vm.implicitGrantObj.url).replace(vm.implicitGrantObj.state, '{{random}}');
+        vm.api.urls.implicitGrant(provider);
         //JSON.stringify(dir, null, 2);
       }, function (err) {
         vm.form.provider = vm.defaults.provider;
@@ -215,12 +260,64 @@
         vm.fn.unlock();
       });
     };
+    vm.api.discoverScopes = function () {
+      var scopes = vm.form.scopes && vm.form.scopes.split(',') || [];
+      vm.scopesObj = [];
+
+      function nextScope() {
+        var scopename = scopes.shift();
+        if (!scopename) {
+          return;
+        }
+
+        // something like https://example.com/.well-known/oauth3.org/scopes/:scopename.json
+        var scopeUrlObj = OAUTH3.urls.discoverScope(vm.form.provider, {
+          client_uri: vm.conf.client_uri
+        , scope: scopename
+        , debug: vm.conf.debug || undefined
+        });
+        vm.scopeUrl = OAUTH3.url.normalize(provider) + '/' + scopeUrlObj.query._pathname;
+
+        // something like the discovery url that loads in an iframe
+        var discoverScopeObj = OAUTH3.urls.discoverScope(vm.form.provider, {
+          client_uri: vm.conf.client_uri
+        , scope: scopename
+        , debug: vm.conf.debug || undefined
+        });
+        vm.discoverScopeUrl = OAUTH3.url.normalize(provider) + '/' + discoverScopeObj.url;
+
+        // Go and fetch!
+        return OAUTH3.discoverScopes(vm.form.provider, {
+          client_uri: vm.conf.client_uri
+        , scope: scopename
+        , debug: vm.conf.debug || undefined
+        }).then(function (scope) {
+          var allScopes = {};
+          vm.scopesObj.push(scope);
+          vm.defaults.scopes.push(scope);
+          vm.defaults.scopes = vm.defaults.scopes.filter(function (scope) {
+            if (allScopes[scope.name]) {
+              return false;
+            }
+            allScopes[scope.name] = true;
+            return true;
+          });
+        }, function (err) {
+          console.error("Error in discover scope:");
+          console.error(err);
+          vm.scopesObj.push({ name: scopename, desc: "Error, not found" });
+        });
+      }
+
+      return nextScope();
+    };
     vm.api.implicitGrant = function () {
       var provider = vm.validated.provider;
       var opts = {
         client_uri: vm.conf.client_uri
       , subject: vm.form.subject || undefined
-      , debug: vm.debug || undefined
+      , debug: vm.conf.debug || undefined
+      , scope: vm.form.scopes || undefined
       };
 
       console.log('[DEBUG] vm.directives');
@@ -240,5 +337,6 @@
       vm.defaults.directives = vm.directives;
     });
 
+    vm.fn.updateScopes();
 	} ] );
 }());