Document signing¶
The module that applies PAdES signatures to PDFs. Signing happens through
the eID Mongolia /v3 interface using the citizen's PIN2 certificate —
either in their own name or on behalf of an organisation they can represent.
UI: /me/eid/sign.
The flow¶
sequenceDiagram
participant U as Citizen
participant A as Gerege App
participant E as eID Mongolia /v3
U->>A: upload the PDF (POST /v1/sign/init)
A->>A: compute the PDF digest
A->>E: signature/notification/etsi — send the digest
E-->>U: PIN2 push on the phone
U->>E: approve with PIN2 ← the legal consent
loop poll
A->>E: session state?
end
E-->>A: signature confirmed
U->>A: GET /v1/sign/{id}/download
A-->>U: PDF with the PAdES signature
| Endpoint | What |
|---|---|
POST /v1/sign/init |
Upload a PDF and start a signing session |
POST /v1/sign/initiate |
Digest-based session (no file) |
GET /v1/sign/status/{sid} |
Session state |
GET /v1/sign/{id} |
Signature details |
GET /v1/sign/{id}/download |
Download the signed PDF |
Two kinds of stamp¶
At download time one of two paths applies:
- eID Mongolia's official stamp —
PAdES-Tplus a verification page. - The server's Document-Signer — a PAdES signature embedded into the PDF
with
digitorus/pdfsign, carrying the citizen's name and national ID in the signature field.
The Document-Signer is mandatory in production
Without SIGN_SIGNER_CERT_FILE and SIGN_SIGNER_KEY_FILE the module will
not load in production. In development a temporary certificate is generated.
Signing on behalf of an organisation¶
When signing for an organisation:
- The signature itself is still made with the citizen's PIN2 certificate (not a stamp).
- The eID session is bound to that organisation (
NTRMN-<regNo>) and the representation right is verified — without it,403. - On completion the confirmed organisation name is taken from the poll and the signature reason records "on behalf of …".
Representation rights come from the "authorised signers" registry in the eID PKI profile.
TSA (timestamping)
A standalone TSA connection is a later stage. Today the eID Mongolia stamp
provides the PAdES-T level.
The sign relay for third-party RPs¶
Third-party RPs (for example template.gerege.mn) have no eID Mongolia
signature RP credentials, so direct calls return 401. Gerege App fronts them
as a reverse proxy:
RP → https://<host>/rp/sign/v3/* → eidmongolia.mn /v3/*
Authorization: Bearer <SIGN_RELAY_TOKEN>
↓ swapped for ↓
Authorization: Bearer <the real EID_RP_SECRET>
| Property | Value |
|---|---|
| Path | /rp/sign/* (the prefix is stripped) |
| RP authentication | SIGN_RELAY_TOKEN, compared in constant time |
| The eID secret | Never exposed to the RP |
| Disabling | An empty SIGN_RELAY_TOKEN turns the relay off |
Relay calls appear in the gateway log.
Signature images and stamps¶
What appears on the document:
| Endpoint | What |
|---|---|
GET/PUT/DELETE /v1/me/signature |
Personal signature image |
GET/PUT/DELETE /v1/me/orgstamp/{regNo} |
Organisation stamp |
PUT /v1/me/latin-name · /org-name-latin/{regNo} |
Latin names |
SSRF protection when fetching remote images
The asset-fetch client refuses to reach internal addresses
(isDisallowedFetchIP) — loopback, private and link-local ranges are all
blocked.
Security notes¶
- Legal consent is the citizen's PIN2 on their phone — the server cannot substitute for it.
- Session state is held briefly in Redis.
EID_DISPLAY_TEXTcontrols the text shown on the phone; overly long values are clamped.- Every signing operation is written to the audit log.