(function () { 'use strict'; window.ngOauth3App = angular.module('oauth3Playground', [ 'oauth3.org' ]) //window.ngOauth3App = angular.module('oauth3Playground', [ 'ui.router' ]) /* ngOauth3App.config(function($stateProvider) { var helloState = { name: 'hello', url: '/hello', template: '

hello world!

' } var aboutState = { name: 'about', url: '/about', template: '

Its the UI-Router hello world app!

' } $stateProvider.state(helloState); $stateProvider.state(aboutState); }); */ .controller('PlaygroundCtrl', [ '$timeout', 'azp@oauth3.org', function ($timeout, OAUTH3) { // NOTE: This OAUTH3 is the same as window.OAUTH3, but with angular's promise injected // TODO: how to load more than one version of oauth3 on the page (i.e. a vanilla version without angular entaglement) var vm = this; vm.clientUri = OAUTH3.clientUri(window.location); 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 = {}; // // Convenience for our app // vm.fn = {}; vm.fn._debounce = {}; vm.fn.debounceUi = function () { if (vm.debouncing.user || vm.debouncing.provider) { vm.locks['login'] = true; } else { vm.locks['login'] = false; } }; vm.fn.debounce = function (name, time) { vm.debouncing[name] = true; vm.fn.debounceUi(); $timeout.cancel(vm.fn._debounce[name]); vm.fn._debounce[name] = $timeout(function () { vm.debouncing[name] = false; vm.fn.debounceUi(); // do nothing, just use promise return; }, time || 250); return vm.fn._debounce[name]; } vm.fn.changeUser = function () { var parts = vm.form.id.split('@'); var user; var provider; if (/@/.test(vm.form.id)) { // The username may have a single @, the provider may not // user@thing.com@whatever.com -> user@thing.com, whatever.com provider = parts.pop(); user = parts.join(''); } else { //vm.form.hasUser = false; user = ''; provider = parts.join(''); } vm.form.subject = vm.form.id; return vm.fn.debounce('provider', 250).then(function () { var parts = vm.form.provider.split('.'); if (!vm.form.providerIndependent) { vm.form.provider = provider; } vm.form.userProvider = provider; // Careful: don't use state within a debounce function // uses vm.form.provider for lookup if (parts.length >= 2 && parts[parts.length - 1].length >= 2 && parts.every(function (p) {return p.length})) { return vm.api.discover().then(function () { console.log('[changeUser] vm.directives:'); console.log(vm.directives); console.log(provider); console.log(OAUTH3.uri.normalize(vm.directives.issuer)); if (vm.directives && provider === OAUTH3.uri.normalize(vm.directives.issuer)) { vm.form.subject = user; } else { vm.form.subject = vm.form.id; } }); } }); }; vm.fn.changeProvider = function () { vm.form.providerIndependent = true; var parts = vm.form.provider.split('.'); vm.fn.debounce('provider', 250).then(function () { // Careful: don't use state within a debounce function if (parts.length >= 2 && parts[parts.length - 1].length >= 2 && parts.every(function (p) {return p.length})) { return vm.api.discover(); } }); }; vm.fn.toggleAdvanced = function () { vm.advanced = !vm.advanced; vm.form.provider = vm.form.userProvider; if (!vm.advanced) { vm.form.providerIndependent = false; 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; }; vm.fn.unlock = function () { vm._working = false; }; vm.fn.clearError = function () { vm.error = null; }; vm.fn.clearDirectives = function () { vm.directives = null; }; // // Wrap around the OAUTH3 APIs // vm.api = {}; vm.api.providerUri = function () { console.log('[DEBUG] providerUri:', vm.providerUri); try { vm.providerUri = OAUTH3.uri.normalize(vm.providerUri); vm.conf.provider_uri = vm.providerUri; } catch(e) { vm.error = e; } }; vm.api.clientUri = function () { console.log('[DEBUG] clientUri:', vm.clientUri); try { vm.clientUri = OAUTH3.clientUri({ host: vm.clientUri }); if (vm.clientUri) { console.log('[DEBUG] clientUri:', vm.clientUri); vm.conf.client_uri = vm.clientUri; vm.conf.client_id = vm.clientUri; } } catch(e) { vm.error = e; } }; 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 = ''; vm.api._discoverCount += 1; var latest = vm.api._discoverCount; var provider = vm.form.provider; // shouldn't be mutable during this time but... vm.fn.lock(); vm.discoveryObj = OAUTH3.urls.discover(provider, vm.conf); vm.directivesUrl = OAUTH3.url.normalize(provider) + '/' + vm.discoveryObj.query._pathname; vm.discoveryUrl = vm.discoveryObj.method + ' ' + vm.discoveryObj.url; console.log('about to discover'); return OAUTH3.discover(provider, vm.conf).then(function (dir) { if (latest !== vm.api._discoverCount) { console.log('[DEBUG] ignoring stale discover response for', provider); return; } console.log('[DEBUG] directives:'); console.log(dir); vm.validated.provider = provider; vm.directives = dir; vm.api.urls.implicitGrant(provider); //JSON.stringify(dir, null, 2); }, function (err) { vm.form.provider = vm.defaults.provider; vm.validated.provider = vm.defaults.provider; vm.directives = vm.defaults.directives; if (latest !== vm.api._discoverCount) { console.warn('[DEBUG] ignoring stale discover error for', provider); console.warn(err); return; } console.log('error on discover'); vm.error = err; }).then(function () { 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.conf.debug || undefined , scope: vm.form.scopes || undefined }; console.log('[DEBUG] vm.directives'); console.log(vm.directives); vm.implicitGrantObj = OAUTH3.urls.implicitGrant(vm.directives, opts); console.log('[DEBUG] vm.implicitGrantObj'); console.log(vm.implicitGrantObj); vm.implicitGrantUrl = (OAUTH3.url.normalize(provider) + '/' + vm.implicitGrantObj.url); return OAUTH3.implicitGrant(vm.directives, opts).then(function (session) { vm.session = session; }); }; vm.form.provider = vm.defaults.provider; vm.validated.provider = vm.defaults.provider; vm.api.discover().then(function () { vm.defaults.directives = vm.directives; }); vm.fn.updateScopes(); } ] ); }());