UNPKG

oidc-lib

Version:

A library for creating OIDC Service Providers

41 lines 15.4 kB
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.WebCredentialHandler=t():e.WebCredentialHandler=t()}(window,(function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var o=t[i]={i:i,l:!1,exports:{}};return e[i].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(i,o,function(t){return e[t]}.bind(null,o));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t); /*! * Utilities for Web Request RPC. * * Copyright (c) 2017 Digital Bazaar, Inc. All rights reserved. */ const i={ParseError:{message:"Parse error",code:-32700},InvalidRequest:{message:"Invalid Request",code:-32600},MethodNotFound:{message:"Method not found",code:-32601},InvalidParams:{message:"Invalid params",code:-32602},InternalError:{message:"Internal Error",code:-32603},ServerError:{message:"Server error",code:-32e3}};function o(e,t){if(void 0===t&&(t=window.location.href),"function"==typeof URL)return new URL(e,t);if("string"!=typeof e)throw new TypeError('"url" must be a string.');e.includes(":")||(e=t.startsWith("http")&&!e.startsWith("/")?t+"/"+e:t+e);const n=document.createElement("a");n.href=e;let i=(n.protocol||window.location.protocol)+"//";n.host?"http:"===n.protocol&&"80"===n.port||"https:"===n.protocol&&"443"===n.port?i+=n.hostname:i+=n.host:i+=window.location.host;let o=n.pathname;return o.startsWith("/")||(o="/"+o),{host:n.host||window.location.host,hostname:n.hostname,origin:i,protocol:n.protocol,pathname:o}}function r(e,t){for(t=e="";e++<36;t+=51*e&52?(15^e?8^Math.random()*(20^e?16:4):4).toString(16):"-");return t}function s(e){return e&&"object"==typeof e&&"2.0"===e.jsonrpc&&e.id&&"string"==typeof e.id}function a({listener:e,origin:t,handle:n,expectRequest:i}){if(l(n)){const e=n;n=!1,e.then(e=>n=e)}return o=>{o.source===n&&o.origin===t&&(i&&function(e){return s(e)&&Array.isArray(e.params)}(o.data)||!i&&function(e){return s(e)&&!!("result"in e^"error"in e)&&(!("error"in e)||(t=e.error)&&"object"==typeof t&&"number"==typeof t.code&&"string"==typeof t.message);var t}(o.data))&&e(o.data,o)}}function l(e){try{return"function"==typeof e.then}catch(e){}return!1} /*! * Copyright (c) 2017 Digital Bazaar, Inc. All rights reserved. */const d=3e4;class c{constructor(){this.origin=null,this._handle=null,this._listener=null,this._pending=new Map}async connect(e,t){if(this._listener)throw new Error("Already connected.");t=t||{};this.origin=o(e).origin,this._handle=t.handle||window.parent||window.opener;const n=this._pending;return this._listener=a({origin:this.origin,handle:this._handle,expectRequest:!1,listener:e=>{if(!n.has(e.id))return;const{resolve:t,reject:i,cancelTimeout:o}=n.get(e.id);if(o(),"result"in e)return t(e.result);i(function(e){let t;return"DOMException"===e.constructor?t=new DOMException(e.message,e.name):(t=new Error(e.message),"code"in e&&(t.code=e.code)),e.details&&(t.details=e.details),t}(e.error))}}),window.addEventListener("message",this._listener),new h(this)}async send(e,t,{timeout:n=d}){if(!this._listener)throw new Error("RPC client not connected.");const i=this,o={jsonrpc:"2.0",id:r(),method:e,params:t};if(l(i._handle)){(await i._handle).postMessage(o,i.origin)}else i._handle.postMessage(o,i.origin);return new Promise((e,t)=>{const r=i._pending;let s;if(n>0){const e=setTimeout(()=>{r.delete(o.id),t(new Error("RPC call timed out."))},n);s=()=>{r.delete(o.id),clearTimeout(e)}}else s=()=>{r.delete(o.id)};r.set(o.id,{resolve:e,reject:t,cancelTimeout:s})})}close(){if(this._listener){window.removeEventListener("message",this._listener),this._handle=this.origin=this._listener=null;for(const e of this._pending.values())e.reject(new Error("RPC client closed."));this._pending=new Map}}}class h{constructor(e){this.client=e,this._apis=new Map}define(e,t){if(!e||"string"!=typeof e)throw new TypeError("`name` must be a non-empty string.");if(!t||"object"!=typeof t||!Array.isArray(t.functions))throw new TypeError("`definition.function` must be an array of function names or function definition objects to be defined.");const n=this,i={};return t.functions.forEach(t=>{"string"==typeof t&&(t={name:t,options:{}}),i[t.name]=async function(){return n.client.send(e+"."+t.name,[...arguments],t.options)}}),n._apis[e]=i,i}get(e,t){if(!this._apis[e]){if(t)return this.define(e,t);throw new Error(`API "${e}" has not been defined.`)}return this._apis[e]}} /*! * Copyright (c) 2017 Digital Bazaar, Inc. All rights reserved. */ /*! * Copyright (c) 2017 Digital Bazaar, Inc. All rights reserved. */ class u{constructor(){this.origin=null,this._handle=null,this._apis=new Map}define(e,t){if(!e||"string"!=typeof e)throw new TypeError("`name` must be a non-empty string.");if(!t||"object"===t)throw new TypeError("`api` must be an object.");if(e in this._apis)throw new Error(`The "${e}" API is already defined.`);this._apis[e]=t}async listen(e,t){if(this._listener)throw new Error("Already listening.");t=t||{};const n=this;n.origin=o(e).origin,n._handle=t.handle||window.parent||window.opener;const r="true"===t.ignoreUnknownApi||!1;n._listener=a({origin:n.origin,handle:n._handle,expectRequest:!0,listener:e=>{const{name:t,method:o}=function(e){let[t,...n]=e.split(".");const i=n.pop();return{name:t=[t,...n].join("."),method:i}}(e.method),s=n._apis[t];if(o&&o.startsWith("_"))return f(n._handle,n.origin,e);if(!s&&r)return;if(!s||"function"!=typeof s[o])return f(n._handle,n.origin,e);const a=s[o];(async()=>{const t={jsonrpc:"2.0",id:e.id};try{t.result=await a.apply(s,e.params)}catch(e){t.error=function(e){const t={message:e.message};return"Error"!==e.constructor.name&&(t.constructor=e.constructor.name),"name"in e&&(t.name=e.name),t.code="code"in e?e.code:i.ServerError.code,"details"in e&&(t.details=e.details),t}(e)}n._handle&&(l(n._handle)?n._handle.then(e=>e.postMessage(t,n.origin)):n._handle.postMessage(t,n.origin))})()}}),window.addEventListener("message",n._listener)}close(){this._listener&&(window.removeEventListener("message",this._listener),this._handle=this.origin=this._listener=null)}}function f(e,t,n){const o={jsonrpc:"2.0",id:n.id,error:Object.assign({},i.MethodNotFound)};return l(e)?e.then(e=>e.postMessage(o,t)):e.postMessage(o,t)} /*! * A WebApp is a remote application that runs in a WebAppContext. * * Copyright (c) 2017 Digital Bazaar, Inc. All rights reserved. */class p{constructor(e){this.relyingOrigin=o(e).origin,this.client=null,this.injector=null,this.client=new c,this.server=new u,this._control=null,this._connected=!1}async connect(){return this.injector=await this.client.connect(this.relyingOrigin),this._connected=!0,this._control=this.injector.define("core.control",{functions:["ready","show","hide"]}),this.server.listen(this.relyingOrigin),this.injector}async ready(){if(!this._connected)throw new Error('WebApp not connected. Did you call ".connect()"?');return await this._control.ready(),this}close(){this._connected&&(this.server.close(),this.client.close(),this._connected=!1)}async show(){if(!this._connected)throw new Error('Cannot "show" yet; not connected. Did you call ".connect()"?');return this._control.show()}async hide(){if(!this._connected)throw new Error('Cannot "hide" yet; not connected. Did you call ".connect()?"');return this._control.hide()}} /*! * Copyright (c) 2017-2018 Digital Bazaar, Inc. All rights reserved. */const w=6e4;class m{constructor(e,{timeout:t=w,handle:n,iframe:i,windowControl:o,className:r=null,customize:s=null}={}){if(this.visible=!1,this.dialog=null,this.iframe=null,this.handle=null,this.windowControl=null,this._ready=!1,this._private={},this._timeoutId=null,this._private._readyPromise=new Promise((e,n)=>{this._timeoutId=setTimeout(()=>n(new DOMException("Loading Web application window timed out.","TimeoutError")),t),this._private._resolveReady=t=>{clearTimeout(this.timeoutId),this._timeoutId=null,e(t)},this._private._rejectReady=e=>{clearTimeout(this.timeoutId),this._timeoutId=null,n(e)}}),this._private.isReady=async()=>this._private._readyPromise,this._private.destroy=()=>{this._timeoutId&&this._private._rejectReady(new DOMException("Web application window closed before ready.","AbortError")),this.dialog&&(this.dialog.parentNode.removeChild(this.dialog),this.dialog=null)},i){if("object"!=typeof i||!i.contentWindow)throw new TypeError("`options.iframe` must be an iframe element.");return this.windowControl={handle:i.contentWindow,show(){i.style.visibility="visible"},hide(){i.style.visibility="hidden"}},this.iframe=i,void(this.handle=this.iframe.contentWindow)}if(o)return this.windowControl=o,void(this.handle=this.windowControl.handle);if(n)return void(this.handle=n);this.dialog=document.createElement("dialog"),g(this.dialog,{position:"fixed",top:0,left:0,width:"100%",height:"100%",display:"none",margin:0,padding:0,border:"none",background:"transparent",color:"black","box-sizing":"border-box",overflow:"hidden","z-index":1e6}),this.dialog.className="web-app-window","string"==typeof r&&(this.dialog.className=this.dialog.className+" "+r);const a=document.createElement("style");if(a.appendChild(document.createTextNode("dialog.web-app-window::backdrop {\n background-color: transparent;\n }")),this.container=document.createElement("div"),g(this.container,{position:"relative",width:"100%",height:"100%",margin:0,padding:0,display:"flex","flex-direction":"column"}),this.container.className="web-app-window-backdrop",this.iframe=document.createElement("iframe"),this.iframe.src=e,this.iframe.scrolling="auto",g(this.iframe,{position:"fixed",top:0,left:0,width:"100%",height:"100%",border:"none",background:"transparent",overflow:"hidden",margin:0,padding:0,"flex-grow":1}),this.dialog.appendChild(a),this.container.appendChild(this.iframe),this.dialog.appendChild(this.container),this.dialog.addEventListener("cancel",e=>{e.preventDefault(),this.hide()}),document.body.appendChild(this.dialog),this.handle=this.iframe.contentWindow,s)try{s({dialog:this.dialog,container:this.container,iframe:this.iframe,webAppWindow:this})}catch(e){console.error(e)}}ready(){this._ready=!0,this._private._resolveReady(!0)}show(){if(!this.visible){this.visible=!0;const e=document.querySelector("body");this._bodyOverflowStyle=e.style.overflow,e.style.overflow="hidden",this.dialog?(this.dialog.style.display="block",this.dialog.showModal&&this.dialog.showModal()):this.windowControl.show&&this.windowControl.show()}}hide(){if(this.visible){this.visible=!1;const e=document.querySelector("body");if(this._bodyOverflowStyle?e.style.overflow=this._bodyOverflowStyle:e.style.overflow="",this.dialog){if(this.dialog.style.display="none",this.dialog.close)try{this.dialog.close()}catch(e){console.error(e)}}else this.windowControl.hide&&this.windowControl.hide()}}}function g(e,t){for(const n in t)e.style[n]=t[n]} /*! * Copyright (c) 2017 Digital Bazaar, Inc. All rights reserved. */const y=1e4;class v{constructor(){this.client=new c,this.server=new u,this.injector=null,this.control=null,this.loaded=!1,this.closed=!1}async createWindow(e,{timeout:t=y,iframe:n,handle:i,windowControl:r,className:s,customize:a}={}){if(this.loaded)throw new Error("AppContext already loaded.");this.loaded=!0,this.control=new m(e,{timeout:t,iframe:n,handle:i,windowControl:r,className:s,customize:a}),this.server.define("core.control",this.control);const l=o(e).origin;return this.server.listen(l,{handle:this.control.handle,ignoreUnknownApi:!0}),await this.control._private.isReady(),this.injector=await this.client.connect(l,{handle:this.control.handle}),this.injector}close(){this.closed||(this.closed=!0,this.control._private.destroy(),this.server.close(),this.client.close())}} /*! * JSON-RPC for Web Request Polyfills. * * Copyright (c) 2017 Digital Bazaar, Inc. All rights reserved. */ /*! * Copyright (c) 2017-2018 Digital Bazaar, Inc. All rights reserved. */const _=6e4;class b extends p{constructor(){super(window.location.origin)}async receive(){const e=this;return await e.connect(),new Promise((t,n)=>{const i=setTimeout(()=>{n(new Error("Timed out waiting to receive event."))},_);e.server.define("credentialEventProxy",{send:async e=>(t(e),clearTimeout(i),new Promise((t,n)=>{e.respondWith=e=>{try{t(e)}catch(e){n(e)}}}))}),e.ready()})}}n.d(t,"installHandler",(function(){return j})),n.d(t,"uninstallHandler",(function(){return C})),n.d(t,"getHandlerRegistration",(function(){return P})),n.d(t,"activateHandler",(function(){return x})),n.d(t,"receiveCredentialEvent",(function(){return M})); /*! * Copyright (c) 2018-2019 Digital Bazaar, Inc. All rights reserved. */ const E="https://authn.io";async function j({url:e}){const t=navigator.credentialsPolyfill.CredentialManager;if("granted"!==await t.requestPermission())throw new Error("Permission denied.");const n=await P({url:e});if(!n)throw new Error("Credential handler not registered.");return n}async function C({url:e}){const t=navigator.credentialsPolyfill.CredentialHandlers,n=navigator.credentialsPolyfill.CredentialManager;if("granted"!==await n.requestPermission())throw new Error("Permission denied.");await t.unregister(e)}async function P({url:e}){const t=navigator.credentialsPolyfill.CredentialHandlers;let n;try{n=await t.register(e)}catch(e){}return n}async function x({mediatorOrigin:e=E,get:t,store:n}){if(!t&&!n)throw new Error('"get" or "store" function(s) must be specified.');const i=new(0,navigator.credentialsPolyfill.CredentialHandler)(e);if(t){if("function"!=typeof t)throw new TypeError('"get" must be a function.');i.addEventListener("credentialrequest",e=>T({event:e,get:t}))}if(n){if("function"!=typeof n)throw new TypeError('"store" must be a function.');i.addEventListener("credentialstore",e=>T({event:e,store:n}))}await i.connect()}async function M(){return(new b).receive()}function T({event:e,get:t,store:n}){e.respondWith(async function({event:e,get:t,store:n}){const i=await(t||n)({event:e});if(!i||"object"!=typeof i)throw new TypeError('Return value of "get" or "store" hook must be an object.');if("response"===i.type)return{dataType:i.dataType,data:i.data};if("redirect"===i.type){const t=new v,n=e.openWindow(i.url),o=t.createWindow(i.url,{handle:n,timeout:6e5});return await n,(await o).get("credentialEventProxy",{functions:[{name:"send",options:{timeout:0}}]}).send({type:e.type,credentialRequestOptions:e.credentialRequestOptions,credentialRequestOrigin:e.credentialRequestOrigin,credential:e.credential,hintKey:e.hintKey})}throw new Error('Return value of "get" or "store" must have a type of "response" or "redirect".')}({event:e,get:t,store:n}))}}])})); //# sourceMappingURL=web-credential-handler.min.js.map