(function (global) { "use strict"; // rather than create a million different IdP configurations and litter the // world with files all containing near-identical code, let's use the hash/URL // fragment as a way of generating instructions for the IdP var instructions = global.location.hash.replace("#", "").split(":"); function is(target) { return function (instruction) { return instruction === target; }; } function IDPJS() { this.domain = global.location.host; var path = global.location.pathname; this.protocol = path.substring(path.lastIndexOf("/") + 1) + global.location.hash; this.id = crypto.getRandomValues(new Uint8Array(10)).join("."); } IDPJS.prototype = { getLogin() { return fetch( "https://example.com/.well-known/idp-proxy/idp.sjs?" + this.id ).then(response => response.status === 200); }, checkLogin(result) { return this.getLogin().then(loggedIn => { if (loggedIn) { return result; } return Promise.reject({ name: "IdpLoginError", loginUrl: "https://example.com/.well-known/idp-proxy/login.html#" + this.id, }); }); }, borkResult(result) { if (instructions.some(is("throw"))) { throw new Error("Throwing!"); } if (instructions.some(is("fail"))) { return Promise.reject(new Error("Failing!")); } if (instructions.some(is("login"))) { return this.checkLogin(result); } if (instructions.some(is("hang"))) { return new Promise(r => {}); } dump("idp: result=" + JSON.stringify(result) + "\n"); return Promise.resolve(result); }, _selectUsername(usernameHint) { dump("_selectUsername: usernameHint(" + usernameHint + ")\n"); var username = "someone@" + this.domain; if (usernameHint) { var at = usernameHint.indexOf("@"); if (at < 0) { username = usernameHint + "@" + this.domain; } else if (usernameHint.substring(at + 1) === this.domain) { username = usernameHint; } } return username; }, generateAssertion(payload, origin, options) { dump( "idp: generateAssertion(" + payload + ", " + origin + ", " + JSON.stringify(options) + ")\n" ); var idpDetails = { domain: this.domain, protocol: this.protocol, }; if (instructions.some(is("bad-assert"))) { idpDetails = {}; } return this.borkResult({ idp: idpDetails, assertion: JSON.stringify({ username: this._selectUsername(options.usernameHint), contents: payload, }), }); }, validateAssertion(assertion, origin) { dump("idp: validateAssertion(" + assertion + ")\n"); var assertion = JSON.parse(assertion); if (instructions.some(is("bad-validate"))) { assertion.contents = {}; } return this.borkResult({ identity: assertion.username, contents: assertion.contents, }); }, }; if (!instructions.some(is("not_ready"))) { dump("registering idp.js" + global.location.hash + "\n"); var idp = new IDPJS(); global.rtcIdentityProvider.register({ generateAssertion: idp.generateAssertion.bind(idp), validateAssertion: idp.validateAssertion.bind(idp), }); } })(this);