Zum Inhalt

Signieren mit dem WebSigner

Der WebSigner bringt qualifizierte elektronische Signaturen in deine Anwendung, ohne dass sie Signaturkarten, PINs oder Freigabe-Apps kennen muss. Dein System legt einen Signaturvorgang mit den Dokumenten an und bekommt einen Link. Der Mensch, der signiert, öffnet ihn, wählt sein Signaturmittel und gibt die Signatur bei seinem Vertrauensdiensteanbieter frei. Danach holt dein System die signierten Dokumente ab.

Vorschau

Der WebSigner steht noch nicht in der Produktion bereit. Für die Testumgebung schaltet dich der ZEDAL-Support frei (erp-tools@zedal.de). Die hier gezeigten SDK-Methoden gibt es ab Zedal.Sdk 1.3.0.

Wann du ihn brauchst

  • eANV: Begleitscheine und Übernahmescheine verlangen eine qualifizierte Signatur jedes Beteiligten (§ 19 NachwV). Wie das in den Ablauf eines Begleitscheins passt, steht unter Begleitschein je Rolle; was dort heute schon geht, unter BMU-Begleitscheine.
  • PDF: Lieferscheine, Verträge, Protokolle, auf Wunsch mit sichtbarem Signaturvermerk.

Der Ablauf

Dein System braucht fünf Aufrufe. Alles dazwischen erledigt der Mensch in der Web-Oberfläche des WebSigners.

sequenceDiagram
    autonumber
    participant App as Deine Anwendung
    participant S as WebSigner (SignerApi)
    actor M as Mensch
    participant V as Vertrauensdiensteanbieter

    App->>S: CreateSigningProcess (Dokumente)
    App->>S: SubmitSigningProcess
    S-->>App: signing_url
    App->>M: Link anzeigen (Browser, WebView, QR-Code)
    M->>S: öffnet den Link, wählt das Signaturmittel
    M->>V: gibt die Signatur frei (zweiter Faktor)
    V-->>S: Signatur
    opt Sichtprüfung eingeschaltet
        M->>S: prüft das Ergebnis und gibt es frei
    end
    App->>S: GetSigningProcess, bis ein Endzustand erreicht ist
    App->>S: GetResults
    S-->>App: signierte Dokumente mit Prüfergebnis

Gerätewahl, Freigabe und Sichtprüfung gehören bewusst der Web-Oberfläche: Deine Anwendung sieht weder das Signaturmittel noch die Freigabe, und sie muss es auch nicht.

Zustände

Ein Signaturvorgang hat genau einen Zustand (SigningProcessState) und dazu einen maschinenlesbaren Grund (state_reason). Den Text in state_detail zeigst du an, verzweigen sollst du darauf nicht.

stateDiagram-v2
    direction TB
    [*] --> BUILD: CreateSigningProcess
    BUILD --> PENDING_DEVICE: SubmitSigningProcess
    PENDING_DEVICE --> PENDING_AUTHORIZATION: Signaturmittel gewählt
    PENDING_AUTHORIZATION --> SIGNING: freigegeben
    SIGNING --> REVIEW: Sichtprüfung eingeschaltet
    SIGNING --> COMPLETED: Sichtprüfung ausgeschaltet
    REVIEW --> COMPLETED: freigegeben
    COMPLETED --> [*]

Das ist der reguläre Weg. Daneben endet ein Vorgang in PARTIALLY_COMPLETED, wenn nur ein Teil der Dokumente signiert werden konnte, in REJECTED, wenn der Mensch die Freigabe verweigert, in FAILED bei einem technischen Fehler, in CANCELLED, wenn ihn jemand abbricht oder in der Sichtprüfung verwirft, und in EXPIRED, wenn seine Frist abläuft.

Zustand Bedeutung Ergebnisse abholbar
BUILD Zusammenstellung; Dokumente lassen sich hinzufügen und entfernen nein
PENDING_DEVICE vorgelegt, wartet auf die Wahl des Signaturmittels nein
PENDING_AUTHORIZATION wartet auf die Freigabe beim Vertrauensdiensteanbieter nein
SIGNING die Signatur wird angebracht nein
REVIEW signiert, wartet auf die Sichtprüfung des Menschen nein
COMPLETED alle Dokumente signiert ja
PARTIALLY_COMPLETED ein Teil signiert, der Rest mit Einzelfehler (SOME_DOCUMENTS_FAILED) ja, je Dokument prüfen
REJECTED der Mensch hat die Freigabe verweigert (AUTHORIZATION_DENIED) nein
CANCELLED abgebrochen durch dich (CANCELLED_BY_CREATOR), den Menschen (CANCELLED_BY_SIGNER) oder verworfen in der Sichtprüfung (DISCARDED_IN_REVIEW) nein
EXPIRED Frist abgelaufen (DEADLINE_REACHED) nein
FAILED technischer Fehler ohne verwertbares Ergebnis, etwa Anbieter gestört (PROVIDER_UNAVAILABLE) oder unerwartetes Zertifikat (CERTIFICATE_MISMATCH) nein

Endzustände sind COMPLETED, PARTIALLY_COMPLETED, REJECTED, CANCELLED, EXPIRED und FAILED. Ob die Sichtprüfung läuft, entscheidet der Mensch in seinen Einstellungen, nicht dein Aufruf; plane REVIEW also immer ein. Einen unbekannten Grund behandelst du wie UNSPECIFIED: Neue Gründe kommen hinzu, ohne dass sich die Version ändert.

Mit dem .NET SDK

Den Code zu dieser Anleitung zeigt Signieren mit dem SDK.

Über gRPC und REST

Der Dienst heißt infotech.signer.sign.v1.api.SignerApi. Über REST ist jede Operation außer WatchSigningProcess als POST /infotech.signer.sign.v1.api.SignerApi/<Operation> mit JSON-Körper erreichbar; Anmeldung und Header wie unter REST / JSON.

Operation Zweck
CreateSigningProcess Vorgang mit Dokumenten anlegen (Zustand BUILD)
AddDocuments, RemoveDocument, ListDocuments Zusammenstellung ändern, nur in BUILD
SubmitSigningProcess vorlegen; liefert die signing_url
GetSigningProcess aktueller Zustand
WaitForSigningProcess Zustand abfragen wie GetSigningProcess; damit wartet SignAsync im SDK
WatchSigningProcess Zustandsstrom, nur gRPC
GetResults signierte Dokumente mit Prüfergebnis, nach dem Abschluss
CancelSigningProcess abbrechen, solange kein Endzustand erreicht ist

Die übrigen Operationen des Dienstes bedient die Web-Oberfläche des WebSigners; deine Anwendung braucht sie nicht. SubmitSigningProcess darfst du wiederholen: Ein zweiter Aufruf liefert dieselbe signing_url. CreateSigningProcess legt bei jeder Wiederholung einen neuen Vorgang an. Das kostet nichts, solange der Vorgang nicht vorgelegt wird; er verfällt mit seiner Frist.

Dokumente und Optionen

Jedes Dokument ist ein DocumentInput mit display_name, kind und dem Inhalt in content.

DocumentKind Signatur
DOCUMENT_KIND_PDF PDF-Signatur; mit oder ohne sichtbaren Signaturvermerk
DOCUMENT_KIND_BMU_XML XML-Signatur für eANV-Dokumente, siehe BMU-Begleitscheine
DOCUMENT_KIND_XML XML-Signatur über das ganze Dokument

Optionen gelten für den ganzen Vorgang (CreateSigningProcessRequest.options) oder je Dokument (DocumentInput.options). reason ist der Grund der Signatur in Klartext.

Den sichtbaren Signaturvermerk eines PDF legt PdfSigningOptions.visible_signature fest: Seite (page, 0 heißt letzte Seite), Position und Größe in PDF-Punkten (1/72 Zoll) mit dem Ursprung unten links. Im SDK baut VisibleSignatures.Create(page, x, y, width, height) den Wert. Das Aussehen kommt aus einer Stempelvorlage des Menschen: stamp_template_id wählt eine, ohne Angabe gilt seine Standardvorlage. Mit invisible = true signierst du ohne Vermerk.

In deine Anwendung einbinden

  • Den Link zeigen: im Browser, in einer WebView deiner Anwendung oder als QR-Code, damit der Mensch auf dem Telefon signiert. Die Freigabe beim Vertrauensdiensteanbieter läuft auf dessen eigener Seite; eine WebView muss diesen Seitenwechsel zulassen.
  • Den Link vertraulich behandeln. Wer ihn hat, kann den Vorgang bis zu seiner Frist ansehen, abbrechen und die signierten Dokumente abholen. Signieren kann er ohne das Signaturmittel und den zweiten Faktor des Menschen nicht. Schreib den Link nicht in Logs und verschick ihn nur über Wege, die du auch für Passwörter akzeptieren würdest.
  • Den Zustand abfragen: Einen Rücksprung in deine Anwendung nach dem Signieren gibt es noch nicht. Frag deshalb GetSigningProcess in Abständen von einigen Sekunden ab, solange der Mensch signiert, oder nutz über gRPC WatchSigningProcess. Lass redirect_url beim Anlegen leer.
  • Fristen einplanen: Ohne deadline_at läuft ein Vorgang 24 Stunden. Die signierten Dokumente hält der Dienst nach dem Abschluss nur begrenzt vor, in der Regel 48 Stunden. Hol sie direkt nach dem Abschluss ab und speicher sie in deinem System.

Die Fernsignatur von A-Trust richtet der Mensch einmal ein; wie, beschreibt das Handbuch A-Trust CSC.

BMU-Begleitscheine

Für eANV-Dokumente kommt es darauf an, welcher Layer in welcher Rolle signiert wird: Jeder Beteiligte schließt seinen eigenen Layer ab (Verfahren und Rollen).

Layer-genaue Signaturen folgen

Der WebSigner signiert ein DOCUMENT_KIND_BMU_XML als Ganzes. Eine Signatur, die genau einen Layer für eine bestimmte Rolle abschließt, folgt; BmuSigningOptions im Vertrag ist dafür vorgesehen und wird derzeit nicht ausgewertet. Begleitscheine, die du für das eANV signieren musst, signierst du deshalb noch nicht über den WebSigner.

Fehler

Fehler kommen als gRPC-Status, über REST als HTTP-Status nach der Tabelle unter REST.

Status Typische Ursache
INVALID_ARGUMENT Pflichtangabe fehlt, Dokumentart unbekannt, redirect_url nicht freigegeben
UNAUTHENTICATED kein oder abgelaufenes Access-Token
PERMISSION_DENIED fremder Vorgang, oder dein Account ist für diese Funktion nicht freigeschaltet
NOT_FOUND Vorgang unbekannt
FAILED_PRECONDITION Aufruf in der falschen Phase, etwa GetResults vor dem Abschluss oder RemoveDocument nach dem Vorlegen
UNIMPLEMENTED noch nicht unterstützte Option, etwa Dokumente als Referenz (object_reference) statt inline

Eine abgelaufene Frist ist kein Fehler: GetSigningProcess liefert dann den Zustand EXPIRED. Ebenso ist ein negatives Prüfergebnis kein Fehler, sondern ein erfolgreicher Aufruf mit negativem Ergebnis.

Weiter