diff --git a/src/dbp-qualified-signature-pdf-upload.js b/src/dbp-qualified-signature-pdf-upload.js
index 1f7239a301423716a730992e8b5cdd3129e7edd1..5b337e21aca39211ba98eab23bede08082895ec6 100644
--- a/src/dbp-qualified-signature-pdf-upload.js
+++ b/src/dbp-qualified-signature-pdf-upload.js
@@ -19,6 +19,7 @@ import {send as notify} from '@dbp-toolkit/common/notification';
 import metadata from './dbp-qualified-signature-pdf-upload.metadata.json';
 import {Activity} from './activity.js';
 import {PdfAnnotationView} from "./dbp-pdf-annotation-view";
+import { ExternalSignIFrame } from './ext-sign-iframe.js';
 
 const i18n = createI18nInstance();
 
@@ -61,7 +62,6 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
         this.addAnnotationInProgress = false;
         this.activity = new Activity(metadata);
 
-        this._onReceiveIframeMessage = this.onReceiveIframeMessage.bind(this);
         this._onReceiveBeforeUnload = this.onReceiveBeforeUnload.bind(this);
     }
 
@@ -75,6 +75,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
           'dbp-button': Button,
           'dbp-textswitch': TextSwitch,
           'dbp-pdf-annotation-view': PdfAnnotationView,
+          'external-sign-iframe': ExternalSignIFrame,
         };
     }
 
@@ -120,18 +121,12 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
         // needs to be called in a function to get the variable scope of "this"
         setInterval(() => { this.handleQueuedFiles(); }, 1000);
 
-        this.updateComplete.then(()=>{
-            // see: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
-            window.addEventListener('message', this._onReceiveIframeMessage);
-
-            // we want to be able to cancel the leaving of the page
-            window.addEventListener('beforeunload', this._onReceiveBeforeUnload);
-        });
+        // we want to be able to cancel the leaving of the page
+        window.addEventListener('beforeunload', this._onReceiveBeforeUnload);
     }
 
     disconnectedCallback() {
         // remove event listeners
-        window.removeEventListener('message', this._onReceiveIframeMessage);
         window.removeEventListener('beforeunload', this._onReceiveBeforeUnload);
 
         super.disconnectedCallback();
@@ -299,36 +294,15 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
         return errorParsed;
     }
 
-    onReceiveIframeMessage(event) {
-        const data = event.data;
-
-        // check if this is really a postMessage from our iframe without using event.origin
-        if (data.type === 'pdf-as-error') {
-            let file = this.currentFile;
-            let error = data.error;
-            if (data.cause) {
-                error = `${error}: ${data.cause}`;
-            }
-            file.json = {"hydra:description" : this.parseError(error)};
-            this.addToErrorFiles(file);
-            this._("#iframe").src = "about:blank";
-            this.externalAuthInProgress = false;
-            this.endSigningProcessIfQueueEmpty();
-            return;
-        }
-
-        if (data.type !== 'pdf-as-callback') {
-            return;
-        }
-
-        const sessionId = data.sessionId;
+    _onIFrameDone(event) {
+        const sessionId = event.detail.id;
 
         // check if sessionId is valid
         if ((typeof sessionId !== 'string') || (sessionId.length < 15)) {
             return;
         }
 
-        console.log("Got iframe message for sessionId " + sessionId + ", origin: " + event.origin);
+        console.log("Got iframe message for sessionId " + sessionId);
         const that = this;
 
         // get correct file name
@@ -348,7 +322,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
                 .then(result => {
                     // hide iframe
                     that.externalAuthInProgress = false;
-                    this._("#iframe").src = "about:blank";
+                    this._("#iframe").reset();
                     this.endSigningProcessIfQueueEmpty();
 
                     if (!result.ok) throw result;
@@ -371,7 +345,16 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
                     this.addToErrorFiles(file);
                 });
         }, {}, that.lang);
+    }
 
+    _onIFrameError(event) {
+        let error = event.detail.message;
+        let file = this.currentFile;
+        file.json = {"hydra:description" : this.parseError(error)};
+        this.addToErrorFiles(file);
+        this._("#iframe").reset();
+        this.externalAuthInProgress = false;
+        this.endSigningProcessIfQueueEmpty();
     }
 
     endSigningProcessIfQueueEmpty() {
@@ -426,7 +409,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
 
             // we want to load the redirect url in the iframe
             let iframe = this._("#iframe");
-            iframe.src = entryPoint.url;
+            iframe.setUrl(entryPoint.url);
         }
     }
 
@@ -725,7 +708,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
                 color: #e4154b;
             }
 
-            #external-auth iframe {
+            #external-auth #iframe {
                 margin-top: 0.5em;
             }
 
@@ -736,9 +719,6 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
             #iframe {
                 width: 100%;
                 height: 350px;
-                /* "overflow" should not be supported by browsers, but some seem to use it */
-                overflow: hidden;
-                border-width: 0;
                 /* keeps the A-Trust webpage aligned left */
                 max-width: 575px;
             }
@@ -974,7 +954,7 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
             return;
         }
 
-        this._("#iframe").src = "about:blank";
+        this._("#iframe").reset();
         this.signingProcessEnabled = false;
         this.externalAuthInProgress = false;
         this.signingProcessActive = false;
@@ -1162,8 +1142,10 @@ class QualifiedSignaturePdfUpload extends ScopedElementsMixin(DBPSignatureLitEle
                                             title="${i18n.t('qualified-pdf-upload.stop-signing-process-button')}"
                                             @click="${this.stopSigningProcess}"><dbp-icon name="close"></dbp-icon></button>
                                 </div>
-                                <!-- "scrolling" is deprecated, but still seem to help -->
-                                <iframe id="iframe" scrolling="no"></iframe>
+                                <external-sign-iframe id="iframe"
+                                    @signature-error="${this._onIFrameError}"
+                                    @signature-done="${this._onIFrameDone}"
+                                    ></external-sign-iframe>
                             </div>
                         </div>
                     </div>
diff --git a/src/ext-sign-iframe.js b/src/ext-sign-iframe.js
new file mode 100644
index 0000000000000000000000000000000000000000..93e9cb1260cfff8518cd944708e4854499445e5d
--- /dev/null
+++ b/src/ext-sign-iframe.js
@@ -0,0 +1,80 @@
+import {LitElement, html, css} from "lit-element";
+
+/**
+ * Set the URL via setUrl(), reset via reset().
+ * 
+ * Emits two custom events:
+ *  * signature-error with a "message"
+ *  * signature-done with an "id"
+ */
+export class ExternalSignIFrame extends LitElement {
+
+    constructor() {
+        super();
+        this._onReceiveIframeMessage = this._onReceiveIframeMessage.bind(this);
+    }
+
+    connectedCallback() {
+        super.connectedCallback();
+        window.addEventListener('message', this._onReceiveIframeMessage);
+    }
+
+    disconnectedCallback() {
+        window.removeEventListener('message', this._onReceiveIframeMessage);
+        super.disconnectedCallback();
+    }
+
+    _onReceiveIframeMessage(event) {
+        const data = event.data;
+        if (data.type === 'pdf-as-error') {
+            let error = data.error;
+            if (data.cause) {
+                error = `${error}: ${data.cause}`;
+            }
+            this.dispatchEvent(new CustomEvent('signature-error', {
+                detail: {
+                    message: error,
+                }
+            }));
+        } else if (data.type === 'pdf-as-callback') {
+            this.dispatchEvent(new CustomEvent('signature-done', {
+                detail: {
+                    id: data.sessionId,
+                }
+            }));
+        }
+    }
+
+    setUrl(url) {
+        let iframe = this.renderRoot.querySelector("#iframe");
+        iframe.src = url;
+    }
+
+    reset() {
+        this.setUrl("about:blank");
+    }
+
+    static get styles() {
+        return css`
+            :host {
+                display: inline-block;
+            }
+
+            #iframe {
+                /* "overflow" should not be supported by browsers,
+                  but some seem to use it */
+                overflow: hidden;
+                border-width: 0;
+                width: 100%;
+                height: 100%;
+            }
+        `;
+    }
+
+    render() {
+        return html`
+            <!-- "scrolling" is deprecated, but still seem to help -->
+            <iframe id="iframe" scrolling="no"></iframe>
+        `;
+    }
+}
\ No newline at end of file