diff --git a/packages/auth/assets/silent-check-sso.html b/packages/auth/assets/silent-check-sso.html
new file mode 100644
index 0000000000000000000000000000000000000000..94fe2268cbd7ff3f752f2093bb3cddd6d10b6388
--- /dev/null
+++ b/packages/auth/assets/silent-check-sso.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+    <script>
+        parent.postMessage(location.href, location.origin)
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/packages/auth/package.json b/packages/auth/package.json
index b0714cceb589e36e44c6980fbb522740062ce0e2..7ce234678f0abf5645071cdd354259b4f2212b6a 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -28,6 +28,7 @@
     "vpu-common": "file:./vendor/common"
   },
   "dependencies": {
+    "keycloak-js": "^8.0.0",
     "lit-element": "^2.1.0"
   },
   "scripts": {
diff --git a/packages/auth/rollup.config.js b/packages/auth/rollup.config.js
index 37a3abb0c6fe23f9eb1493e790bbaa6285549ef6..549369f1059c07c88259ff3ac437e006d8724ed3 100644
--- a/packages/auth/rollup.config.js
+++ b/packages/auth/rollup.config.js
@@ -22,6 +22,13 @@ export default {
         format: 'esm',
         sourcemap: true
     },
+    onwarn: function (warning, warn) {
+        // keycloak bundled code uses eval
+        if (warning.code === 'EVAL') {
+            return;
+        }
+        warn(warning);
+    },
     plugins: [
         del({
             targets: 'dist/*'
@@ -43,6 +50,7 @@ export default {
         copy({
             targets: [
                 {src: 'assets/index.html', dest:'dist'},
+                {src: 'assets/silent-check-sso.html', dest:'dist'},
                 {src: 'assets/favicon.ico', dest:'dist'},
                 {src: 'node_modules/vpu-common/assets/icons/*.svg', dest: 'dist/local/vpu-common/icons'},
             ]
diff --git a/packages/auth/src/keycloak.js b/packages/auth/src/keycloak.js
index 616c4ed8dcd3320677cea47fe6c456a635649ab9..98bc0cf999c3436175443b1b39b525115932f94c 100644
--- a/packages/auth/src/keycloak.js
+++ b/packages/auth/src/keycloak.js
@@ -1,29 +1,3 @@
-/**
- * Imports the keycloak JS API as if it was a module.
- *
- * @param baseUrl {string}
- */
-async function importKeycloak(baseUrl) {
-    const keycloakSrc = baseUrl + '/js/keycloak.js';
-    // Importing will write it to window so we take it from there
-    await import(keycloakSrc);
-    if (importKeycloak._keycloakMod !== undefined)
-        return importKeycloak._keycloakMod;
-    importKeycloak._keycloakMod = {Keycloak: window.Keycloak};
-    delete window.Keycloak;
-    return importKeycloak._keycloakMod;
-}
-
-
-async function kcMakeAsync(promise) {
-    // the native keycloak promise implementation is broken, wrap it instead
-    // https://stackoverflow.com/questions/58436689/react-keycloak-typeerror-kc-updatetoken-success-is-not-a-function
-    return new Promise(function(resolve, reject) {
-        promise.success((...args) => { resolve(...args); }).error((...args) => { reject(...args); });
-    });
-}
-
-
 /**
  * Wraps the keycloak API to support async/await, adds auto token refreshing and consolidates all
  * events into one native "changed" event
@@ -32,7 +6,7 @@ async function kcMakeAsync(promise) {
  */
 export class KeycloakWrapper extends EventTarget {
 
-    constructor(baseURL, realm, clientId) {
+    constructor(baseURL, realm, clientId, silentCheckSsoUri) {
         super();
 
         this._baseURL = baseURL;
@@ -40,6 +14,7 @@ export class KeycloakWrapper extends EventTarget {
         this._clientId = clientId;
         this._keycloak = null;
         this._initDone = false;
+        this._silentCheckSsoUri = silentCheckSsoUri;
     }
 
     _onChanged() {
@@ -62,7 +37,7 @@ export class KeycloakWrapper extends EventTarget {
         let refreshed = false;
 
         try {
-            refreshed = await kcMakeAsync(this._keycloak.updateToken(5));
+            refreshed = await this._keycloak.updateToken(5);
         } catch (error) {
             console.log('Failed to refresh the token', error);
             return;
@@ -79,9 +54,9 @@ export class KeycloakWrapper extends EventTarget {
         if (this._keycloak !== null)
             return;
 
-        const module = await importKeycloak(this._baseURL);
+        const Keycloak = await import('keycloak-js').then((mod) => { return mod.default; });
 
-        this._keycloak = module.Keycloak({
+        this._keycloak = Keycloak({
             url: this._baseURL,
             realm: this._realm,
             clientId: this._clientId,
@@ -101,7 +76,14 @@ export class KeycloakWrapper extends EventTarget {
         if (this._initDone)
             return;
         this._initDone = true;
-        await kcMakeAsync(this._keycloak.init());
+
+        const options = {promiseType: 'native'};
+        if (this._silentCheckSsoUri) {
+            options['onLoad'] = 'check-sso';
+            options['silentCheckSsoRedirectUri'] = this._silentCheckSsoUri;
+        }
+
+        await this._keycloak.init(options);
     }
 
     /**
@@ -119,9 +101,9 @@ export class KeycloakWrapper extends EventTarget {
         const language = options['lang'] || 'en';
 
         if (!this._keycloak.authenticated) {
-            await kcMakeAsync(this._keycloak.login({
+            await this._keycloak.login({
                 kcLocale: language,
-            }));
+            });
         }
     }
 
diff --git a/packages/auth/src/vpu-auth-demo.js b/packages/auth/src/vpu-auth-demo.js
index a4ed4482e436590f2f0a9551f99e30f617e2197a..d6e59e6b8ffe4994d1dd35f15efab926120796ae 100644
--- a/packages/auth/src/vpu-auth-demo.js
+++ b/packages/auth/src/vpu-auth-demo.js
@@ -27,6 +27,7 @@ class AuthDemo extends LitElement {
 
     render() {
         commonUtils.initAssetBaseURL('vpu-auth-src');
+        const silentCheckSsoUri = commonUtils.getAssetURL('silent-check-sso.html');
         return html`
             <style>
                /* from BULMA.CSS */
@@ -49,7 +50,7 @@ class AuthDemo extends LitElement {
                     <h1 class="title">Auth-Demo</h1>
                 </div>
                 <div class="container">
-                    <vpu-auth lang="${this.lang}" client-id="${commonUtils.setting('keyCloakClientId')}" load-person remember-login></vpu-auth>
+                    <vpu-auth lang="${this.lang}" client-id="${commonUtils.setting('keyCloakClientId')}" silent-check-sso-uri="${silentCheckSsoUri}" load-person remember-login></vpu-auth>
                 </div>
             </section>
         `;
diff --git a/packages/auth/src/vpu-auth.js b/packages/auth/src/vpu-auth.js
index e0e099f9f3664b1445b7a4010080e0ee416f5150..6479ab574a3458a380729f299c5e7b6ecd2b6b04 100644
--- a/packages/auth/src/vpu-auth.js
+++ b/packages/auth/src/vpu-auth.js
@@ -146,6 +146,7 @@ class VPUAuth extends VPULitElement {
             rememberLogin: { type: Boolean, attribute: 'remember-login' },
             loadPerson: { type: Boolean, attribute: 'load-person' },
             clientId: { type: String, attribute: 'client-id' },
+            silentCheckSsoUri: { type: String, attribute: 'silent-check-sso-uri' },
             name: { type: String, attribute: false },
             token: { type: String, attribute: false },
             subject: { type: String, attribute: false },
@@ -160,7 +161,7 @@ class VPUAuth extends VPULitElement {
 
         const baseURL = commonUtils.setting('keyCloakBaseURL');
         const realm = commonUtils.setting('keyCloakRealm');
-        this._kcwrapper = new KeycloakWrapper(baseURL, realm, this.clientId);
+        this._kcwrapper = new KeycloakWrapper(baseURL, realm, this.clientId, this.silentCheckSsoUri);
         this._kcwrapper.addEventListener('changed', this._onKCChanged);