michael@0: (function(global) { michael@0: "use strict"; michael@0: michael@0: function IDPJS() { michael@0: this.domain = window.location.host; michael@0: var p = window.location.pathname; michael@0: this.protocol = p.substring(p.lastIndexOf('/') + 1) + window.location.hash; michael@0: this.username = "someone@" + this.domain; michael@0: // so rather than create a million different IdP configurations and litter michael@0: // the world with files all containing near-identical code, let's use the michael@0: // hash/URL fragment as a way of generating instructions for the IdP michael@0: this.instructions = window.location.hash.replace("#", "").split(":"); michael@0: this.port = window.rtcwebIdentityPort; michael@0: this.port.onmessage = this.receiveMessage.bind(this); michael@0: this.sendResponse({ michael@0: type : "READY" michael@0: }); michael@0: } michael@0: michael@0: IDPJS.prototype.getDelay = function() { michael@0: // instructions in the form "delay123" have that many milliseconds michael@0: // added before sending the response michael@0: var delay = 0; michael@0: function addDelay(instruction) { michael@0: var m = instruction.match(/^delay(\d+)$/); michael@0: if (m) { michael@0: delay += parseInt(m[1], 10); michael@0: } michael@0: } michael@0: this.instructions.forEach(addDelay); michael@0: return delay; michael@0: }; michael@0: michael@0: function is(target) { michael@0: return function(instruction) { michael@0: return instruction === target; michael@0: }; michael@0: } michael@0: michael@0: IDPJS.prototype.sendResponse = function(response) { michael@0: // we don't touch the READY message unless told to michael@0: if (response.type === "READY" && !this.instructions.some(is("ready"))) { michael@0: this.port.postMessage(response); michael@0: return; michael@0: } michael@0: michael@0: // if any instruction is "error", return an error. michael@0: if (this.instructions.some(is("error"))) { michael@0: response.type = "ERROR"; michael@0: } michael@0: michael@0: window.setTimeout(function() { michael@0: this.port.postMessage(response); michael@0: }.bind(this), this.getDelay()); michael@0: }; michael@0: michael@0: IDPJS.prototype.receiveMessage = function(ev) { michael@0: var message = ev.data; michael@0: switch (message.type) { michael@0: case "SIGN": michael@0: if (message.username) { michael@0: var at = message.username.indexOf("@"); michael@0: if (at < 0) { michael@0: this.username = message.username + "@" + this.domain; michael@0: } else if (message.username.substring(at + 1) === this.domain) { michael@0: this.username = message.username; michael@0: } michael@0: } michael@0: this.sendResponse({ michael@0: type : "SUCCESS", michael@0: id : message.id, michael@0: message : { michael@0: idp : { michael@0: domain : this.domain, michael@0: protocol : this.protocol michael@0: }, michael@0: assertion : JSON.stringify({ michael@0: username : this.username, michael@0: contents : message.message michael@0: }) michael@0: } michael@0: }); michael@0: break; michael@0: michael@0: case "VERIFY": michael@0: var payload = JSON.parse(message.message); michael@0: var contents = payload.contents; michael@0: if (this.instructions.some(is("bad"))) { michael@0: contents = {}; michael@0: } michael@0: this.sendResponse({ michael@0: type : "SUCCESS", michael@0: id : message.id, michael@0: message : { michael@0: identity : payload.username, michael@0: contents : contents michael@0: } michael@0: }); michael@0: break; michael@0: michael@0: default: michael@0: this.sendResponse({ michael@0: type : "ERROR", michael@0: id : message.id, michael@0: error : JSON.stringify(message) michael@0: }); michael@0: break; michael@0: } michael@0: }; michael@0: michael@0: global.idp = new IDPJS(); michael@0: }(this));