Synchronní podepisování souborů

Krok č. 1) Přihlášení

Pro přístup k API je nutné nejprve získat přístupový token pomocí koncového bodu pro přihlášení externího informačního systému pod identitou konkrétního uživatele.

Koncový bod: /api/sofa/v1/auth/extis/login-impersonate

Metoda: POST

Hlavičky:

  • Accept: application/json

  • Content-Type: application/json

Parametry:

  • login … uživatelské jméno externího informačního systému.

  • password … heslo externího informačního systému.

  • impersonateUserId … LDAP identifikátor uživatele, jehož identitou má externí informační systém vystupovat (návod na zjištění tohoto identifikátoru je uveden na konci dokumentu).

Příklad:

POST /api/sofa/v1/auth/extis/login-impersonate HTTP/1.1
Host: sofaws.602.cz
Accept: application/json
Content-Length: …
Content-Type: application/json

{
  "login": "48a0ecdd540849f0af416307406467f0",
  "password": "wau3S99vx2d_NW2P",
  "impersonateUserId": "9e5f2f76-fff5-44c3-b943-06a95fdc08e2"
}

Výsledek:

{
  "token": "eyJhbGciOiJBMjU2…"
}

Krok č. 2) Nahrání souborů

V dalším kroku je nutné nahrát dokumenty jeden po druhém do výchozího úložiště (default) pomocí koncového bodu File API. Výsledkem bude seznam identifikátorů souborů použitý v dalším kroku.

Koncový bod: /api/sofa/v2/file?storeId=default

Metoda: POST

Hlavičky:

  • Accept: application/json

  • Authorization: Bearer <token>

  • Content-Type: multipart/form-data

Parametry:

  • file … soubor dokumentu (ve verzi 2.0 se již nepoužívá hlavička FileId s parametry kódovanými ve formátu JSON, ale přenáší se standardní cestou pro upload souborů podle RFC 2854, tzn. že se název souboru uvádí v hlavičce Content-Disposition, velikost souboru v hlavičce Content-Length a typ souboru v hlavičce Content-Type).

Příklad:

POST /api/sofa/v2/file?storeId=default HTTP/1.1
Host: sofaws.602.cz
Accept: application/json
Authorization: Bearer eyJhbGciOiJBMjU2…
Content-Length: …
Content-Type: multipart/form-data; boundary="-----086735ab-f408-405e-9628-4eb525d56d71"

-------086735ab-f408-405e-9628-4eb525d56d71
Content-Disposition: form-data; name="file"; filename="Document.pdf"
Content-Length: …
Content-Type: application/pdf

…binary file content…
-------086735ab-f408-405e-9628-4eb525d56d71--

Výsledek:

{
  "fileId": "eyJhbGciOiJIUzI1…"
}

Krok č. 3) Spuštění GraphQL mutace

Pro podepisování dokumentů je nutné zavolat koncový bod GraphQL API s mutací pro podepisování souborů, které předáme identifikátor dokumentu a parametry podepisování. Výsledkem je identifikátor dokumentu opatřeného podpisem. Aktuálně jsou podporované následující parametry:

  • algorithmId … identifikátor algoritmu, např. SHA-256 nebo SHA-512 (výchozí hodnota: SHA-256).

  • certificateId … identifikátor certifikátu (HSM ID).

  • certificatePIN … PIN certifikátu.

  • signParameters

    • addTimestamp … příznak vložení časového razítka.

    • addVisualSignature … příznak doplnění vizuálního podpisu.

    • showParaphImage … příznak zobrazení obrázku parafy.

    • reason … důvod podpisu.

    • location … umístění.

    • contact … kontakt.

    • parametry vizuálního podpisu, pouze pokud addVisualSignature = true:

      Umístění:

      • page … číslo stránky počítáno od začátku dokumentu (kladná hodnota), respektive od konce dokumentu (záporná hodnota).

      • posX … souřadnice levého okraje vizuálního podpisu v rozlišení 72 DPI.

      • posY … souřadnice horního okraje vizuálního podpisu v rozlišení 72 DPI od dolního okraje stránky (kladná hodnota), respektive od horního okraje stránky (záporná hodnota).

      • sizeX … šířka vizuálního podpisu v rozlišení 72 DPI.

      • sizeY … výška vizuálního podpisu v rozlišení 72 DPI.

      Text:

      • text … text vizuálního podpisu.

      • textHeader … textová hlavička vizuálního podpisu.

      Obrázek:

      • image … obrázek vizuálního podpisu (Base-64 kódovaný PNG soubor).

  • signingProperties

    • signerName … jméno podepisujícího.

    • signerPhoneNumber … telefonní číslo podepisujícího.

    • signatureAutoLocationWidth … šířka automatického umístění vizuálního podpisu.

    • signatureAutoLocationHeight … výška automatického umístění vizuálního podpisu.

    • signatureAutoLocationSearchText … text automatického umístění vizuálního podpisu.

Koncový bod: /api/sofa/v1/graphql

Metoda: POST

Hlavičky:

  • Accept: application/json

  • Authorization: Bearer <token>

  • Content-Type: application/json

GraphQL operace:

mutation signFile($file: SignOperationParameters!) {
  signing {
    signFile(file: $file)
  }
}

Příklad:

POST /api/sofa/v1/graphql HTTP/1.1
Host: sofaws.602.cz
Accept: application/json
Authorization: Bearer eyJhbGciOiJBMjU2…
Content-Length: …
Content-Type: application/json

{
  "operationName": "signFile",
  "query": "mutation signFile(\n  $file: …",
  "variables": {
    "file": {
      "fileId": "eyJhbGciOiJIUzI1…",
      "algorithmId": null,
      "certificateId": "3fbc87f3-f5fb-4211-934a-881b76ca52b6-x3x",
      "certificatePIN": "12345",
      "signParameters": {
        "addTimestamp": true,
        "addVisualSignature": true,
        "showParaphImage": true,
        "reason": null,
        "location": null,
        "contact": null,
        "page": 1,
        "posX": 10,
        "posY": -10,
        "sizeX": 250,
        "sizeY": 50,
        "text": "Text podpisu",
        "textHeader": null,
        "image": null
      },
      "signingProperties": {
        "signerName": "Test",
        "signerPhoneNumber": "Test",
        "signatureAutoLocationWidth": null,
        "signatureAutoLocationHeight": null,
        "signatureAutoLocationSearchText": null
      }
    }
  }
}

Výsledek:

{
  "data": {
    "signing": {
      "signFile": "eyJhbGciOiJIUzI1…"
    }
  }
}

Důležité poznámky:

  • Pro podepisování lokálními certifikáty je nutné využít služby podepisování pomocí formuláře.

  • PIN certifikátu je z bezpečnostních důvodů nutné vždy zadávat do proměnných (variables).

  • Na rozdíl od pečetění jsou některé parametry načítány z konfigurace podepisujícího (impersonovaného) uživatele, konkrétně se jedná o parametry: text, textHeader a image, takže je není nutné zadávat; pokud jsou uvedeny, mají vyšší prioritu před hodnotami načtenými z konfigurace.

  • Pro umístění vizuálního podpisu je možné využít služby automatického umístění na základě vyhledaného textu, případně ještě doplněné o šířku a výšku; v tomto případě není nutné zadávat poziční parametry: page, posX, posY, sizeX a sizeY, jelikož budou nahrazeny automaticky vypočítanými hodnotami.

Zjištění seznamu certifikátů

Pro zjištění seznamu certifikátů lze použít následující GraphQL dotazy, resp. jejich upravené verze:

GraphQL operace:

query getCertificates(
  $isDeleted: Boolean! = false
  $isExpired: Boolean! = false
  $isRevoked: Boolean! = false
) {
  certificates {
    certificates(
      where: {
        and: [
          { sys: { isDeleted: $isDeleted } }
          { sys: { isExpired: $isExpired } }
          { sys: { isRevoked: $isRevoked } }
        ]
      }
    ) {
      edges {
        node {
          id
          hsmId
          subject
          certificateName
          serialNumber
          isDeleted
          isExpired
          isRevoked
          user {
            id
            userName
            completeName
          }
        }
      }
    }
  }
}

GraphQL operace:

query getCertificatesForUser(
  $userId: String!
  $isDeleted: Boolean! = false
  $isExpired: Boolean! = false
  $isRevoked: Boolean! = false
) {
  certificates {
    certificates(
      where: {
        and: [
          { eqString: { left: { sys: USER_ID }, right: { const: $userId } } }
          { sys: { isDeleted: $isDeleted } }
          { sys: { isExpired: $isExpired } }
          { sys: { isRevoked: $isRevoked } }
        ]
      }
    ) {
      edges {
        node {
          id
          hsmId
          subject
          certificateName
          serialNumber
          isDeleted
          isExpired
          isRevoked
        }
      }
    }
  }
}

Všimněte si, že výsledek volání obsahuje dva identifikátory certifikátu: id a hsmId.

  • id se používá při volání mutace exportCertificate (popsána níže),

  • hsmId se používá při volání samotného podepisování.

Získání veřejné části certifikátu z HSM

Tato mutace umožňuje získat veřejnou část certifikátu pro certifikát, který je uložen v HSM.

mutation exportCertificate($request: Cm_ExportCertRequest!) {
  certificates {
    exportCertificate(request: $request) {
      certificateBase64
      filename
      __typename
    }
    __typename
  }
}

Příklad dat:

{"request":{
  "id": "c13b1fb6-64f0-43a3-80b1-12dd5f8dd7d2",
  "pin": null,
  "newPassword": null,
  "newPassword2": null
}
}

Výsledek:

{
    "data": {
        "certificates": {
            "exportCertificate": {
                "certificateBase64": "MIIGMjCCBRq...9Zc0",
                "filename": "157D.cer",
                "__typename": "Cm_ExportCertResponse"
            },
            "__typename": "Cm_Mutation"
        }
    }
}

Název souboru je pouze návrh jména souboru, do kterého pak mohou být získaná data uložena.

Krok č. 4) Stažení souborů

Posledním krokem je stažení podepsaných souborů jeden po druhém pomocí koncového bodu File API:

Koncový bod: /api/sofa/v2/file

Metoda: GET

Hlavičky:

  • Authorization: Bearer <token>

Parametry:

  • fileId … identifikátor stahovaného dokumentu.

Příklad:

GET /api/sofa/v2/file?fileId=eyJhbGciOiJIUzI1…
Host: sofaws.602.cz
Authorization: Bearer eyJhbGciOiJBMjU2…

Výsledek:

Výsledkem je stahovaný dokument.

Název souboru lze získat buď standardně z hlavičky Content-Disposition, nebo File API v2 nastavuje pro snazší zpracování hlavičku X-Sofa-FileName.