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
GetSigningProcessin Abständen von einigen Sekunden ab, solange der Mensch signiert, oder nutz über gRPCWatchSigningProcess. Lassredirect_urlbeim Anlegen leer. - Fristen einplanen: Ohne
deadline_atlä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¶
- Begleitschein je Rolle: wo die Signatur im Ablauf eines Begleitscheins steht
- .NET SDK: Client, Aufrufkontext, Zeitgrenzen
- REST / JSON: Anmeldung und Aufrufform