1/* 2jankko-sso-client (modern) 3version: 8450d220 4generated: 2026-09-16T08:28:21.556Z 5*/ 6!function(t){function e(t){return p(t)||u(t)?"6Lda1bcmAAAAACQsKUrRKI7mvqMn6yOwAp_oHhZv":"6LeR1ognAAAAACeEgYID8sIvr9IvZbbc93xhppj7"}function i(t){const e=new URL(t,window.location.origin),i=e.searchParams,n=new URLSearchParams,s=i.get("gaa_at"),o=i.get("gaa_ts"),a=i.get("gaa_n"),r=i.get("gaa_sig");s&&o&&a&&r&&(n.set("gaa_at",s),n.set("gaa_ts",o),n.set("gaa_n",a),n.set("gaa_sig",r));const l=i.get("limit-active-products");return l&&n.set("limit-active-products",l),e.search=""+n,e.hash="",""+e}function n(t,e){return`https://${t}/logout?returnUrl=${encodeURIComponent(i(e))}`}function s(t,e){return`https://${t}/landing-page?orig_url=${btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}`}function o(t,e){return`https://${t}/loginForm?returnUrl=${encodeURIComponent(i(e))}&errorReturnUrl=${encodeURIComponent(i(window.location.href))}`}function a(t,e){return`https://${t}/verify-account?returnUrl=${encodeURIComponent(i(e))}`}function r(t,e){return`https://${t}/send-verify-email?returnUrl=${encodeURIComponent(i(e))}`}function l(t,e){try{e=new URL(e).searchParams.get("returnUrl")??e}catch(t){console.error(t)}const n=new URL(`https://${t}/loginregistration`);n.searchParams.set("returnUrl",i(e));const s=function(){const t=window.JankkoSSOConfig;if(t&&t.accountOrigin)return window.JankkoSSOConfig.accountOrigin}();return s&&n.searchParams.set("accountOrigin",s),""+n}function d(t){return`https://${t}/Account/MyAccount`}function c(t,e){const n=`https://${t}/passwordResetForm?returnUrl=${encodeURIComponent(i(e))}`;return"true"===f("skipRecaptcha")?n+"&skipRecaptcha=true":n}function u(t){return"sso.localhost:4000"===t||"localhost:4000"===t}function p(t){return t.endsWith(".diks.fi")||t.endsWith(".diks.fi:4000")}function m(t){return u(t)?"/assets/password-reset-demo.html":"/palauta-salasana/"}function k(t){return u(t)?"/assets/demo.html":"/kirjaudu/"}function f(t){return new URLSearchParams(location.search).get(t)??""}function h(){return"error"===f("status")?{status:f("status"),code:f("code")}:null}function g(t){if("invalid_username_or_password"===t.code||"invalid_credentials"===t.code)return"Käyttäjätunnus tai salasana on virheellinen.";if("invalid_otp"===t.code||"otp_expired"===t.code)return"Antamasi kirjautumiskoodi on virheellinen tai vanhentunut.";if(t.code.match(/^account_frozen:\d+$/)){const e=t.code.split(":")[1],i=1e3*parseInt(e,10);return`Käyttäjätunnuksesi on tilapäisesti lukittu, koska syötit salasanan väärin liian monta kertaa. Lukitus poistuu ${new Intl.DateTimeFormat("fi",{dateStyle:"short",timeStyle:"short"}).format(i)}.`}return"Palvelussa tapahtui virhe. Yritä hetken päästä uudelleen."}class w{constructor(t){this.ssoHost="",this.ssoHost=t}refreshSession(){if(this.sessionPromise)return this.sessionPromise;const t="true"===new URLSearchParams(window.location.search).get("forceAccessTokenRefresh"),e=new URL(`https://${this.ssoHost}/refreshSession`);return t&&e.searchParams.set("forceAccessTokenRefresh","true"),this.sessionPromise=new Promise((t,i)=>{fetch(e,{method:"POST",credentials:"include",mode:"cors",cache:"no-cache"}).then(t=>(200!==t.status&&i(`${t.status} ${t.statusText}`),t)).then(t=>{if("true"===t.headers.get("x-jankko-sso-landing-page")){const t=s(this.ssoHost,window.location.href);console.log("x-jankko-sso-landing-page",t),window.location.href=t}return t}).then(e=>{t(e.json())}).catch(t=>{i(t)})}),this.sessionPromise}}class v{getOtpLink(){const t=new URL(window.location.href);return t.searchParams.set("mode","otp"),t.searchParams.delete("status"),t.searchParams.delete("code"),t.searchParams.delete("step"),t.pathname+t.search}getLoginUI(t,e,i){return`<div class="diks-login__inner-wrapper">\n <form id="diks-login-form" class="diks-form diks-form--fluid" action="${t}" method="post">\n <div class="diks-form__field-wrapper diks-form__field-wrapper--required">\n <label id="diks-login-form-email-label" class="diks-form__label" for="diks-login-form-email">Sähköposti</label>\n <input autocomplete="username" class="diks-form__field" type="email" name="username" id="diks-login-form-email" aria-labelledby="diks-login-form-email-label" required>\n </div>\n\n <div class="diks-form__field-wrapper diks-form__field-wrapper--required">\n <label id="diks-login-form-password-label" class="diks-form__label" for="diks-login-form-password">Salasana</label>\n <div class="diks-form__password-field-wrapper">\n <input autocomplete="current-password" class="diks-form__field" type="password" name="password" id="diks-login-form-password" aria-labelledby="diks-login-form-password-label" required>\n <button class="diks-button diks-button--ghost" id="diks-login-form-password-visibility-toggle" type="button" aria-label="Näytä salasana">
6\n <span class="diks-icon" id="diks-login-form-password-visibility-toggle-icon" aria-hidden="true"></span>\n </button>\n </div>\n </div>\n\n <div class="diks-form__field-wrapper">\n <input class="diks-form__inline-field diks-form__checkbox" type="checkbox" name="persist" id="diks-login-form-persist" checked>\n <label class="diks-form__inline-label" for="diks-login-form-persist">Muista minut</label>\n </div>\n\n <p>\n <a class="diks-login__link" href="${i}">Olen unohtanut salasanani</a>\n </p>\n\n <button class="diks-button diks-button--primary" type="submit">Kirjaudu sisään</button>\n\n <p style="margin-top: 1rem;">\n <a class="diks-login__link diks-button diks-button--primary-ghost" href="${this.getOtpLink()}">Kirjaudu ilman salasanaa</a>\n </p>\n </form>\n </div>\n <div class="diks-login__bottom">\n <div class="diks-login__inner-wrapper">\n <a class="diks-button diks-button--outline" href="${e}">Luo Mediatunnus</a>\n </div>\n </div>`}getOtpEmailUI(t,i,n){return`<div class="diks-login__inner-wrapper">\n <form id="diks-otp-form" class="diks-form diks-form--fluid" action="${t}" method="post">\n <p>Kirjaudu sisään tunnukseesi liitetyllä sähköpostiosoitteella.</p>\n\n <div class="diks-form__field-wrapper diks-form__field-wrapper--required">\n <label id="diks-otp-form-email-label" class="diks-form__label" for="diks-otp-form-email">Sähköposti</label>\n <input autocomplete="username" class="diks-form__field" type="email" name="email" id="diks-otp-form-email" aria-labelledby="diks-otp-form-email-label" required>\n </div>\n\n <div id="recaptcha" class="g-recaptcha" data-sitekey="${e(this.ssoHost)}" data-callback="onSubmit" data-size="invisible"></div>\n <button class="diks-button diks-button--primary" type="submit" id="diks-otp-form-submit" style="margin-top: 1rem;">Jatka</button>\n\n <p style="margin-top: 1rem;">\n <a class="diks-login__link diks-button diks-button--primary-ghost" href="${i}">Kirjaudu salasanalla</a>\n </p>\n </form>\n </div>\n <div class="diks-login__bottom">\n <div class="diks-login__inner-wrapper">\n <a class="diks-button diks-button--outline" href="${n}">Luo Mediatunnus</a>\n </div>\n </div>`}getOtpCodeUI(t,e){return`<div class="diks-login__inner-wrapper">\n <form id="diks-otp-verify-form" class="diks-form diks-form--fluid" action="${t}" method="post">\n <p>Kirjautumiskoodi lähetettiin sähköpostiisi. Jos et saanut koodia, tarkista myös roskapostilaatikko.</p>\n\n <div class="diks-form__field-wrapper diks-form__field-wrapper--required">\n <label id="diks-otp-verify-form-code-label" class="diks-form__label" for="diks-otp-verify-form-code">Kirjautumiskoodi</label>\n <input autocomplete="one-time-code" class="diks-form__field" type="text" name="code" id="diks-otp-verify-form-code" aria-labelledby="diks-otp-verify-form-code-label" inputmode="numeric" required>\n </div>\n\n <button class="diks-button diks-button--primary" type="submit" style="margin-top: 1rem;">Vahvista</button>\n\n <p style="margin-top: 1rem;">\n <a class="diks-login__link diks-button diks-button--primary-ghost" href="${e}?mode=otp">Palaa takaisin</a>\n </p>\n </form>\n </div>`}getLogoutUI(t,e,i,n){return`<div class="diks-login__inner-wrapper">\n <p>${n?`Olet kirjautuneena tunnuksella <strong>${i}</strong>, mutta voimassa olevaa lukuoikeutta ei löytynyt. Tarkista tilauksesi sisältö omista tiedoista tai kirjaudu sisään toisella tunnuksella.`:`Olet kirjautuneena tunnuksella <strong>${i}</strong>`}</p>\n <form id="diks-logout-form" class="diks-form diks-form--fluid" action="${t}" method="post">\n <button class="diks-button diks-button--primary" type="submit">Kirjaudu ulos</button>\n <a class="diks-button diks-button--outline" href="${e}">Omat tiedot</a>\n </form>\n </div>`}getDefaultPasswordResetUI(t,i){return`<div class="diks-login__inner-wrapper">\n <p>Jos olet unohtanut Mediatunnuksesi salasanan, täytä sähköpostiosoitteesi tähän ja klikkaa lähetä-nappia. Saat sähköpostiviestin, joka sisältää linkin ja ohjeet kuinka nollaat salasanasi. Sähköpostiin tuleva linkki on kertakäyttöinen.</p>\n <form id="diks-password-reset-form" class="diks-form diks-form--fluid" action="${t}" method="post">\n <div class="diks-form__field-wrapper diks-form__field-wrapper--required ${i?"diks-form__field-wrapper--error":""}">\n <label class="diks-form__label" for="diks-password-reset-form-email">Sähköposti</label>\n <input class="diks-form__field" type="email" name="email" id="diks-password-reset-form-email" required>\n </div>\n\n <div id="recaptcha" class="g-recaptcha" data-sitekey="${e(this.ssoHost)}" data-callback="onSubmit" data-size="invisible"></div>\n <button class="diks-button diks-button--primary" type="submit" id="diks-password-reset-form-submit">Lähetä</button>\n </form>\n </div>\n <div class="diks-login__bottom">\n <a class="diks-login__navigation-link" href="${k(this.ssoHost)}">Kirjaudu sisään</a>\n </div>`}getSuccessPasswordResetUI(){return`<div class="diks-login__inner-wrapper">\n <p>Saat kohta sähköpostiviestin, joka sisältää linkin ja ohjeet kuinka nollaat salasanasi. Sähköpostiin tuleva linkki on kertakäyttöinen. Mikäli ongelma ei ratkea, ota yhteyttä asiakaspalveluun.</p>\n <p><a class="diks-login__navigation-link" href="${m(this.ssoHost)}">Palaa takaisin</a></p>\n </div>`}getErrorMessageUI(t){return`<div class="diks-login__inner-wrapper">\n <div class="diks-alert diks-alert--danger" role="alert">\n <div class="diks-alert__text-wrapper">${t}</div>\n </div>\n </div>`}constructor(t){this.ssoHost="",this.ssoHost=t}getUI(t,e,i,s,a){let r="";
6const c=h();return c&&(r+=this.getErrorMessageUI(g(c))),r+=t?this.getLogoutUI(n(this.ssoHost,e),d(a),t,s):this.getLoginUI(o(this.ssoHost,i||e),l(this.ssoHost,e),m(this.ssoHost)),r}getOtpUI(t,e){let i="";const n=h();if(n&&(i+=this.getErrorMessageUI(g(n))),"code"===t){const t=f("returnUrl")||`${window.location.origin}${k(this.ssoHost)}`;i+=this.getOtpCodeUI(`https://${this.ssoHost}/otpVerify?returnUrl=${encodeURIComponent(t)}&errorReturnUrl=${encodeURIComponent(e)}`,k(this.ssoHost))}else{let t=`https://${this.ssoHost}/otpRequest?returnUrl=${encodeURIComponent(e)}`;"true"===f("skipRecaptcha")&&(t+="&skipRecaptcha=true"),i+=this.getOtpEmailUI(t,k(this.ssoHost),l(this.ssoHost,e))}return i}getPasswordResetUI(t,e,i){let n="";const s=h();return s&&(n+=this.getErrorMessageUI(g(s))),n+="success"===i?this.getSuccessPasswordResetUI():this.getDefaultPasswordResetUI(c(this.ssoHost,e||t),"error"===f("status")),n}}const b=new class{constructor(){var t;this.appContainerID="jankko-sso-client-container",this.scriptTagID="jankko-sso-script",this.ssoHost="",this.tuloHost="",this.ssoHost=function(t){const e=document.getElementById(t);if(e){const t=e.getAttribute("src");if(t){let e;try{e=new URL(t)}catch(t){return console.warn("Script src is relative. Using fallback"),"localhost"===document.location.hostname?(console.warn(`Using 'sso.${document.location.host}' as ssoHost`),"sso."+document.location.host):(console.warn(`Using '${document.location.host}' as ssoHost`),document.location.host)}if(e)return e.host}}return console.error("Cannot find script tag with id: "+t),""}(this.scriptTagID),this.tuloHost=p(t=this.ssoHost)||u(t)?"media.payway-portal.stage.adeprimo.se":"media.portal.worldoftulo.com",this.api=new w(this.ssoHost),this.ui=new v(this.ssoHost)}getServiceUrls(t){return{login:o(this.ssoHost,t),logout:n(this.ssoHost,t),loginRegistration:l(this.ssoHost,t),myAccount:d(this.tuloHost),ticketOut:(e=this.ssoHost,`https://${e}/ticket-out`),passwordReset:c(this.ssoHost,t),landingPage:s(this.ssoHost,t),verifyAccount:a(this.ssoHost,t),resendVerification:r(this.ssoHost,t),loginRegistrationAndVerification:l(this.ssoHost,window.location.origin+"/kirjaudu/")};var e}async getSession(){try{return await this.api.refreshSession()}catch(t){return console.error("refreshSession error: ",t),console.error("There was a connection error of some sort"),console.error(t),null}}generateReCAPTCHAElements(){const t=document.createElement("script");t.src="https://www.recaptcha.net/recaptcha/api.js",t.async=!0,t.defer=!0;const e=document.createElement("script");e.innerHTML='function onSubmit(token) {var form = document.getElementById("diks-password-reset-form");var tokenInput = document.createElement("input");tokenInput.type = "hidden";tokenInput.name = "token";tokenInput.value = token;form.appendChild(tokenInput);form.submit();}function validate(event) {event.preventDefault();var email = document.getElementById("diks-password-reset-form-email");if (email) {if (!email.checkValidity()) {var wrapper = email.parentElement;wrapper.classList.add("diks-form__field-wrapper--error");} else {grecaptcha.execute();}}}function onload() {var element = document.getElementById("diks-password-reset-form-submit");if (element) {element.onclick = validate;}}onload();';const i=document.createElement("style");i.innerHTML=".grecaptcha-badge { visibility: hidden; }";const n=document.createElement("div");return n.append(e,t,i),n}generateOtpReCAPTCHAElements(){const t=document.createElement("script");t.src="https://www.recaptcha.net/recaptcha/api.js",t.async=!0,t.defer=!0;const e=document.createElement("script");e.innerHTML='function onSubmit(token) {var form = document.getElementById("diks-otp-form");var tokenInput = document.createElement("input");tokenInput.type = "hidden";tokenInput.name = "token";tokenInput.value = token;form.appendChild(tokenInput);form.submit();}function validate(event) {event.preventDefault();var email = document.getElementById("diks-otp-form-email");if (email) {if (!email.checkValidity()) {var wrapper = email.parentElement;wrapper.classList.add("diks-form__field-wrapper--error");} else {grecaptcha.execute();}}}function onload() {var element = document.getElementById("diks-otp-form-submit");if (element) {element.onclick = validate;}}onload();';const i=document.createElement("style");i.innerHTML=".grecaptcha-badge { visibility: hidden; }";const n=document.createElement("div");return n.append(e,t,i),n}generatePasswordVisibilityToggleScript(){const t=document.createElement("script");return t.innerHTML='\n const form = document.getElementById("diks-login-form");\n const toggle = document.getElementById("diks-login-form-password-visibility-toggle");\n const input = document.getElementById("diks-login-form-password");\n if (form && toggle && input) {\n form.addEventListener("submit", function() {\
6n input.type = "password";\n });\n toggle.addEventListener("click", function() {\n if (input.type === "password") {\n input.type = "text";\n toggle.classList.add("visible");\n toggle.setAttribute("aria-label", "Piilota salasana");\n } else {\n input.type = "password";\n toggle.classList.remove("visible");\n toggle.setAttribute("aria-label", "Näytä salasana");\n }\n });\n }\n ',t}renderPasswordReset(t,e,i){const n=f("state"),s="true"===f("skipRecaptcha");console.log("Recaptcha",{skipRecaptcha:s}),t.innerHTML=this.ui.getPasswordResetUI(e,i,n),s||t.appendChild(this.generateReCAPTCHAElements())}init(){this.api.refreshSession().then(t=>{const e=document.getElementById(this.appContainerID);if(i=t,(i?.companyUserChanged||i?.permissionsChanged)&&("true"!==new URLSearchParams(location.search).get("forceInsideIframe")&&window.self===window.top?"true"!==new URLSearchParams(location.search).get("reload")?(()=>{console.log("JankkoSSOClient: location.reload() triggered");const t=new URL(location.href);t.searchParams.set("reload","true"),location.replace(""+t)})():console.log("JankkoSSOClient: skip reload because already reloaded"):console.log("JankkoSSOClient: skip reload because inside iframe")),e){const i=e.getAttribute("data-template"),n=window.location.href,s=f("returnUrl");if("passwordReset"===i)this.renderPasswordReset(e,n,s);else if("otp"!==f("mode")||t?.personal?.personal_email||t?.personal?.personal_user_id){let i;t?.personal?.personal_email?i=t.personal.personal_email:t?.personal?.personal_user_id&&(i=t.personal.personal_user_id);const o="true"===f("noSubscription");e.innerHTML=this.ui.getUI(i,n,s,o,this.tuloHost),e.appendChild(this.generatePasswordVisibilityToggleScript())}else{const t="verify"===f("step")?"code":"email",i="true"===f("skipRecaptcha");e.innerHTML=this.ui.getOtpUI(t,n),"email"!==t||i||e.appendChild(this.generateOtpReCAPTCHAElements())}}var i}).catch(t=>{console.error("refreshSession error: ",t),console.error("There was a connection error of some sort"),console.error(t);const e=document.getElementById(this.appContainerID);if(e){const t=e.getAttribute("data-template"),i=window.location.href,n=f("returnUrl");if("passwordReset"===t)this.renderPasswordReset(e,i,n);else if("otp"===f("mode")&&"verify"===f("step"))e.innerHTML=this.ui.getOtpUI("code",i);else if("otp"===f("mode")){const t="true"===f("skipRecaptcha");e.innerHTML=this.ui.getOtpUI("email",i),t||e.appendChild(this.generateOtpReCAPTCHAElements())}else{const t=window.location.href,i=f("returnUrl"),n="true"===f("noSubscription");e.innerHTML=this.ui.getUI(null,t,i,n,this.tuloHost),e.appendChild(this.generatePasswordVisibilityToggleScript())}}})}};document.addEventListener("DOMContentLoaded",t=>{b.init()});const _=b.getServiceUrls(window.location.href);t.createTicketAuthLink=function(t){return`${_.ticketOut}?redirectUrl=${encodeURIComponent(t)}`},t.getSession=async function(){return await b.getSession()},t.serviceUrls=_}(this.JankkoSSOClient=this.JankkoSSOClient||{});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.