window.customElements.define('d4s-boot-2', class extends HTMLElement { #keycloak = null #authorization = null #url = null #realm = "d4science" #clientId = null #redirectUrl = null #audience = null // loading attempts nr and timer between attempts #attempts = 6 #timer = 500 constructor() { super() //this.attachShadow({mode: "closed"}) } connectedCallback() { if (typeof Keycloak === 'undefined') { const script = document.createElement('script') script.src = this.#url + '/js/keycloak.js' script.type = 'text/javascript' script.addEventListener('load', () => { this.initKeycloak() }) document.head.appendChild(script) } else { this.initKeycloak() } } initKeycloak() { this.#keycloak = new Keycloak({ url: this.#url, realm: this.#realm, clientId: this.#clientId }) const keycloak = this.#keycloak const url = this.#url keycloak.init({ onLoad: 'login-required' , checkLoginIframe: false }).then((authenticated) => { console.log(authenticated ? 'Authenticated in ' + this.#realm : 'Not authenticated') if (typeof KeycloakAuthorization === 'undefined') { const authz = document.createElement('script') authz.src = url + '/js/keycloak-authz.js' authz.type = 'text/javascript' authz.addEventListener('load', () => { this.#authorization = new KeycloakAuthorization(keycloak) }) document.head.appendChild(authz) } else { this.#authorization = new KeycloakAuthorization(keycloak) } //console.log("expires: " + this.expirationDate(keycloak.tokenParsed.exp)) }).catch(function(err) { console.error("Failed to initialize d4science boot component") }) } parseJwt(token) { var base64Url = token.split('.')[1] var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/') var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) }).join('')) return JSON.parse(jsonPayload); } expirationDate(utc) { let d = new Date(0) d.setUTCSeconds(utc) return d } checkContext() { const parseJwt = this.parseJwt const expDt = this.expirationDate const audience = encodeURIComponent(this.#audience) this.#authorization.entitlement(audience).then(function (rpt) { // onGrant callback function. // If authorization was successful you'll receive an RPT // with the necessary permissions to access the resource server console.log(rpt) //console.log("rpt expires: " + expDt(parseJwt(rpt).exp)) }) } service(endpoint, method, params, onSuccess, onForbidden) { if (this.#authorization == null) { if (this.#attempts-- > 0) { setTimeout(() => this.service(endpoint, method, params, onSuccess, onForbidden), this.#timer) return } else { console.error("Impossible to initialize D4Science authorization component") throw "Fatal error" } } this.#keycloak.updateToken(30).then(() => { const audience = encodeURIComponent(this.#audience) this.#authorization.entitlement(audience).then(function (rpt) { var req = new XMLHttpRequest() req.open(method, endpoint, true) req.setRequestHeader('Accept', 'application/json') req.setRequestHeader('Authorization', 'Bearer ' + rpt) req.onreadystatechange = function () { if (req.readyState == 4) { if (req.status == 200) { onSuccess(req.response) } else if (req.status == 403) { onForbidden(req.statusText) } } } req.send(params) }) }).catch(function() { onForbidden('Failed to refresh token') }) } logout() { if (this.#keycloak) { if (!this.#redirectUrl) { console.error("Missing required @redirectUrl attribute in d4s-boot") } else { this.#keycloak.logout({ redirectUri: this.#redirectUrl }) } } } static get observedAttributes() { return ["url", "realm", "gateway", "redirect-url", "context"]; } attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue) { switch (name) { case "url": this.#url = newValue break case "realm": this.#realm = newValue break case "gateway": this.#clientId = newValue break case "redirect-url": this.#redirectUrl = newValue break case "context": this.#audience = newValue break } } } get url() { return this.#url } set url(url) { this.#url = url this.setAttribute("url", url) } get realm() { return this.#realm } set realm(realm) { this.#realm = realm this.setAttribute("realm", realm) } get clientId() { return this.#clientId } set clientId(clientId) { this.#clientId = clientId this.setAttribute("gateway", clientId) } get redirectUrl() { return this.#redirectUrl } set redirectUrl(redirectUrl) { this.#redirectUrl = redirectUrl this.setAttribute("redirect-url", redirectUrl) } get context() { return this.#audience } set context(context) { this.#audience = context this.setAttribute("context", context) } })