Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API specifikacia #1

Closed
jsuchal opened this issue Apr 4, 2021 · 28 comments
Closed

API specifikacia #1

jsuchal opened this issue Apr 4, 2021 · 28 comments
Assignees
Projects
Milestone

Comments

@jsuchal
Copy link
Member

jsuchal commented Apr 4, 2021

Tu diskutujeme ako bude fungovat API:

Zatial je zhoda, ze to bude fungovat nejako takto:

  • zistime, ze pouzivatel nema nainstalovany podpisovac resp, zlej/starej verzie. (ako?)
  • pouzivatel si nainstaluje aplikaciu, ktora mu zaregistruje custom app protocol.
  • pouzivatel na nejakom portali klikne na linku "podpisat", spusti sa mu cez custom app protokol aplikacia, JS to zisti (asi cez nejake "version API" a nasledne na "sign" API posle naformatovany http request, ze chce podpisat nejaky subor.
  • podpisovac zobrazi vizualizaciu vyzve pouzivatela na BOK (ak treba), ZEP PIN a nasledne zasle ako odpoved JSON? podpisany subor (base64) alebo chybovu hlasku (nepodpisane, alebo cokolvek co moze nastat)

Pre slovenske xml, potrebujeme na vstup poslat: XML subor, XSLT podpisovu transformaciu, XSD schemu validacie. Toto sa musi (!) poslat na podpisovac, aby niekto nepodvrhol inu transformaciu. Z tohto sa vyrobi v podpisovaci slovensky "datacontainer", ktory sa podpisuje.

Otvorene otazky postrehy, ktore maju dosah na architekturu/api:

  • aky format bude na vstupe a vystupe? JSON ci plain old multipart HTTP?
  • co ak chcem podpisat viac dokumentov naraz? Scenar: Poklikam si "do tabov" viac dokumetov na podpisanie.
  • slovensky standard vyzaduje dost specificke nastavenie DSS, je ziaduce, aby API malo okrem nizkourovnovich flagov aj nejaky "template" flag, sk-signing, ktory by nastavil vsetko ako treba, pripadne ked sa situacia v buducnosti zmeni nemusel to konzument podpisovaca sledovat. Jednoducho bude pouzivat sk-signing template vo svojej aplikacii.
  • aplikacia sa otvara na nahodnom porte navrhnutom konzumentom?
  • je vhodne pre nejake scenare (podpisuje viac dokumentov naraz) nechat bezat aplikaciu chvilu na pozadi, aby si pri kazdom podpisovani nepytala BOK na pristup k certifikatom.

Bolo by dobre vytvorit nejake swagger API, ked si povieme ake endpointy ako budu fungovat. Voci nim sa potom daju robit mocks na extensions aj na portali.

@jsuchal jsuchal added this to the Discovery milestone Apr 4, 2021
@jsuchal jsuchal self-assigned this Apr 4, 2021
@jsuchal jsuchal added this to To do in Podpisovač Apr 4, 2021
@jsuchal jsuchal moved this from To do to In progress in Podpisovač Apr 4, 2021
@jsuchal
Copy link
Member Author

jsuchal commented Apr 4, 2021

@durasj ono ked ta aplikacia nebezi stale na pozadi, tak by asi nemuselo vadit ani keby sme mali nejaky staticky port nie? Dost by to zjednodusilo pouzivanie clientside, lebo vies okamzite zistit ci to bezi. To by riesilo problem co si mal ty, ze to mal iny user pustene a drzalo to port.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 5, 2021

Ešte skúsme rozlúsknuť tie ďalšie otázky ohľadom api. @pomali máš na to nejaký vyhranený názor? Multipart či json? Ako response dáva zmysel skor json lebo sa stým lepšie robí v js, čiže asi má zmysel to isté robiť aj na vstupe aj keď súbor bude treba nejako encodnut (base64), čo ho nafúkne ale lokálne to vôbec nevadí.

@durasj ty to vidíš ako?

@pomali
Copy link
Contributor

pomali commented Apr 5, 2021

JSON/multipart
to zalezi od toho ci ideme riesit aj inych klientov, v js je praca s FormData celkom ok, ale riesit multipart ak by som chcel ist nie z browseru by asi bolo horsie. Vieme urobit aj to ze file sa bude posielat v inom requeste, ak by base64 bol problem.

utility/daemon
V diskusii o statickych portoch asi ide o filozofiu ci chceme aby to bola skor unix utilita, alebo aplikacia/service/daemon. Napriklad usecase "podpisovanie viacero dokumentov" asi priklana ku daemon, kedze ak by kazde okno/spustenie bolo samostatne tak by trebalo zadavat vzdy BOK (ak tomu dobre rozumiem).

Protokol pri spustani z browseru
Ak pouzijeme protocol handler aby sme vyziadali spustenie appky, tak budeme musiet pollovat aby sme zistili ci appka uz bezi. Alternativou by mohol byt nejaky nejaky callback ale neprisiel som na dobry sposob. Pollovanie ma aj tu vyhodu, ze pouzivatel nemusi odklikavat dialog o otvoreni appky ak uz bezi.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 6, 2021

Mne to vychádza tiež na polling, keď tam nechceme ťahať websockets. Zatiaľ to vidím na nejake api /info /sign pričom to prvé bude polling a vráti aj verziu. Druhé podpíše ak to beží inak to vyvolá spustenie a počká. Ešte máme jeden scenár kde sa môže stať že človek má viac kľúčov na podpisovanie ale to asi zatiaľ neriešime.

@durasj ty to ako vidíš s tou kostrou? Aby sme to vedeli prípadne začať plniť implementáciou. Defacto len potrebujeme aby to začalo na nejakom porte počúvať a otváralo okná. Zvyšok už si vieme rozdeliť.

@pomali
Copy link
Contributor

pomali commented Apr 6, 2021

Websockets ani ti nepomozu na zistenie toho ci uz bezi server.

VIacero klucov browser nejako riesi? Tu by mi prislo lepsie, ze ak ma browser nejake poziadavky na to cim to ma byt podpisane tak nech to ide v sign requeste (napr. aky cert, ake meno ma mat ta entita a pod.), a vyber certu robi user podla toho co mu "poradi" appka.

@durasj
Copy link
Contributor

durasj commented Apr 6, 2021

Ja som 100% za JSON. Multipart form data dava zmysel len na web appkach a mimo toho vseobecne APIs velmi nevidam s multipart form data. Ale samozrejme da sa neskor pridat podpora, ved len budeme respektovat dalsi Content-Type. Base64 nie je problem. Momentalne to uz mam spravene cez JSON a base64. Vedeli by sme akceptovat aj plaintext XML ako to posielaju oni cez WS, ale base64 bude istejsie do buducnosti pre binarne formary nech je to jednotne. Ten overhead prezijeme, ved to ide cez loopback.

Co sa tyka tych requestov tak suhlasim s @jsuchal. Tiez to vidim zatial na GET /info a POST /sign. Ten port by mohol byt default preddefinovany (planujem to dat do .properties alebo tak nejak) a pri vyvolani cez protokol by sa mohol zmenit, takze napr. po zavolani signer://listen/9876 by pocuval na 9876, pri zavolani signer://listen na defaulte. Takto by sa dal vyriesit problem ak by sa nedala zapnut appka s default portom - netreba robit nastavenia navyse, ale len spustit s nejakym inym portom cez web a bude to fungovat cez viac userov.

Co sa tyka pristupu service, tam som popravde proti tomu, lebo:

  1. Ide to proti jednoduchosti.
  2. Je to intruzivne - bezi mi nieco na pozadi aj ked UI nevidim.

Ak ide o zrychlenie startu, tak podla mna samostatna appka nabehne dost rychlo a to listovanie klucov a tieto inicializacne veci by sme mohli radsej cacheovat. Ze sa to prednadstavi na to co bolo naposledy a prinajhorsom to zlyha ked clovek medzitym zmenil veci a bude si musiet vybrat znova. Samozrejme da sa ten caching nejak nastavit aj inteligentnejsie. Ale za mna urcite nech sa to proste zapne ked to ma ist a vypne ked sa skonci.

@durasj
Copy link
Contributor

durasj commented Apr 6, 2021

@jsuchal "Ešte máme jeden scenár kde sa môže stať že človek má viac kľúčov na podpisovanie ale to asi zatiaľ neriešime." Toto nie je problem, pretoze momentalne predselectnem prvy kluc. Ak sa pouzivatelovi nebude pacit tak si vyberie zo zoznamu iny pred stlacenim tlacidal podpisat. EDIT: Respt. to zapametanie ako som pisal vyssie. Ak nebude spravny ten co si pamatame tak si pickne.

@pomali
Copy link
Contributor

pomali commented Apr 6, 2021

Service som nemyslel tak, ze bude bezat stale, len to ze bude jeden proces ktory prijima requesty a vie zobrazit viacero okien, realne vsak podpisuje iba jeden proces vs to ze sa spusta viacero procesov ktore kazdy riesi podpisovanie samostatne. Oba pripady mozu byt kratko beziace, ci uz ze sa vypnu hned po doruceni podpisaneho dokumentu alebo budu mat grace period ak by si chcel podpisat este nieco v nablizsich 5 minutach, inak sa vypnu.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 6, 2021 via email

@durasj
Copy link
Contributor

durasj commented Apr 6, 2021

@pomali @jsuchal To znie ok, takze by bezal HTTP server a drzal referenciu na token a private key. Potom akurat je otazka co s tym volenim kluca. Momentalne je v UI nad podpisovanym suborom. Takze ak by ho clovek zmenil v jednom okne, mal by sa zmenit v ostatnych alebo sa zmeni len v tomto okne?

@jsuchal
Copy link
Member Author

jsuchal commented Apr 6, 2021 via email

@durasj
Copy link
Contributor

durasj commented Apr 6, 2021

Okej tak zatial pojdeme zmenou vsade a neskor sa moze pridat do toho dialogu sekundarne tlacidlo "zmenit pre toto okno" ak by sa zistilo, ze ich je viac.

To vratenie klucov cez API by som radsej osobne zatial nerobil ak na to nie je poziadavka. Zatial API nevie pustit nic citlive. Ak niekto nieco podvrhne na podpisanie tak to musi clovek explicitne akceptnut podpisanim. Ale ak by sme pridali ten listing klucov tak to uz je nebezpecnejsie. Ak uz bude zoznam vopred nacitany tak to jednoducho dostane utocnik bez toho, ze by to clovek vedel. Tak s tym radsej asi zatial opatrne a implementujme s dobrym premyslenim neskor. Nech sa to deje radsej pred podpisom v GUI ako je to teraz zatial.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 6, 2021 via email

@jsuchal
Copy link
Member Author

jsuchal commented Apr 6, 2021

@durasj inak da sa mozno spravit taka vec, ze proste kazdy request bude musiet mat v hlavicke nejaky token/uuid ktore sa posle do podpisovaca pri spusteni. To je kvazi csrf nahrada a podpisovac nebude proste odpovedat na requesty, ktore nemaju platny uuid. defacto by to vsak znamenalo este vsetko zabalit do takehoto kontextu, neviem ci si to chceme takto komplikovat. Asi to pre alfa verziu vypustime.

@durasj
Copy link
Contributor

durasj commented Apr 7, 2021

@jsuchal To som presne rozmyslal a podla mna by to bolo fajn neskor zvazit ako by sa to dalo robit. Ja som chcel (myslim, ze je to aj v popise prototypu ais2 podpisovaca) tiez robit "parovanie" podpisovaca cez ten custom protocol. Potom komunikacia by musela mat HMAC. Pri requestoch z browsera ale co sa tyka hlaviciek bude treba IMHO riesit CORS preflight requesty, takze by som zvazil skor zabalenie body ako header. Ono by to ciastocne riesilo aj MitM, ktory mi teraz pride neprijemny v tom listening server mode. Problem s tymto pristupom je ale ked si clovek spusti aplikaciu manualne - tj. nie cez custom protocol. Taktiez to co si spominal - aby to fungovalo spustene viackrat tak treba nejaky "kontext" na oboch stranach.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 8, 2021

@durasj podla mna nejakemu lahkemu JS wrapperu sa nevyhneme, cize tam uz ci si on ulozi do localstorage/cookie nejaky port alebo uuid je jedno.

@durasj
Copy link
Contributor

durasj commented Apr 8, 2021

@jsuchal Jop, ono by to az tak veci nemuselo komplikovat. Len to manualne otvorenie aplikacie - nie cez custom protocol - by mohlo komplikovat. Potom by sa musel vediet vyplnit v appke manualne ten pairing key ak by to bolo vyzadovane. Situaciu na ktoru myslim ked spominam manualne otvorenie mimo protokol je ked custom protocol by z nejakeho dovodu nefungoval.

Da sa to samozrejme urobit volitelne, ze ked je zapnuta s, tak ho vyzaduje, ak bez, tak nevyzaduje. Akurat to trocha defeatne purpose.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 8, 2021

Ono situaciu, ze si niekto pusti aplikaciu len tak by som asi neriesil. Preco by to vlastne niekto robil?

@durasj
Copy link
Contributor

durasj commented Apr 8, 2021

@jsuchal Pre situaciu co som spomenul. Nefunguje z nejakeho dovodu custom protocol. Napr. na Windowse ked sa presunie aplikacia alebo zmeni zaznam v registroch, alebo ked si omylom pouzivatel odmietne otvorenie aplikacie a potom sa nevie dopracovat spat k povoleniu. Intuitivna akcia podla mna bude otvorit si aplikaciu manualne. V tom pripade by sla na default porte a jednoducho by to slo lebo client by vedel ceknut default port najprv.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 8, 2021

D.Signer sa inak tiez neda pustit len tak a neviem o tom, ze by to vadilo.

@durasj
Copy link
Contributor

durasj commented Apr 8, 2021

Okej, asi to teda zatial zbytocne komplikujem pokrytim toho edgecasu. Tak potom tie nastavenia pri spusteni custom protocolom mozu vyzerat takto?

signer://listen/generatedKey/origin napr. signer://listen/asd123/navody.slovensko.sk

Ten posledny argument je povoleny origin, ktory by sa dal do CORS hlavicky, takze browser nedovoli ani strkat do toho nos inym strankam ako ta co to spustila. generatedKey sa moze pouzit v jednoduchom HMACu body, ktory sa bude vzdy ocakavat v request body aj v response body. Client si ho teda cekovat nemusi, ale mal by.

Predpokladame, ze launch cez protokol je secure channel. HTTP uz nie a nemusi vdaka HMAC lebo key sa z toho snoopnut neda.

@jsuchal
Copy link
Member Author

jsuchal commented Apr 9, 2021

CORS je fajn napad, HMAC ako optional tiez.

@jsuchal jsuchal closed this as completed Apr 9, 2021
@jsuchal jsuchal reopened this Apr 9, 2021
@pomali
Copy link
Contributor

pomali commented Apr 9, 2021

dlauncher pouziva domenu dlauncher.ditec.sk a certifikaty ktore ti prida do systemu aby mali TLS
image

@jsuchal
Copy link
Member Author

jsuchal commented Apr 15, 2021

Len pre info. dohodli sme sa @durasj, ze swagger spravi on.

@durasj
Copy link
Contributor

durasj commented May 1, 2021

API specifikacia je done na https://whitelabel.octosign.com/server-api

Je v repozitari spolu s appkou. Po spusteni appky sa tiez hostuje lokalne na /documentation takze sa da lahko skusat vypalovat requesty hned. Su tam zdokumentovane aj parametre podpisu ale realne sa zatial neberu do uvahy v appke. Oh a HMAC sa tiez zatial neriesi, ale uz su pripravene zarezy.

Spravil som JS klienta, ktoru ju implementuje. @pomali ma invite. Na npm nie je zatial publishnuta lebo sa to musi najprv dostat do polostabilneho stavu. Verejna dokumentacia je na stranke kde je aj Server HTTP API dokumentacia. JS klient ukazuje ako sa to da spravit bez triggovania CORS preflight. Funguje to v pohode na Chrome, Firefox, Edge(ium) aj zo secure origin.

Safari nefunguje pre mixed content - ak je stranka na HTTPS a robi request na HTTP localhost tak sa WebKit z toho posklada. Toto by tak nemalo byt a maju bug na ktorom aktivne pracuju ale aj tak to tak skoro teda asi nebude. Loopback by mal byt safe podla specky a ostatni to dodrziavaju ale Safari nie. Riesenie je skarede - self-signed cert + dns rule ako spominal hore @pomali ale tym sa zasahuje do setupu pouzivatela. Osobne nemam motivaciu to pridavat. Planujem len eventualne pridat podporu HTTPS a klient je uz teraz konfigurovatelny.

Maly sneak peek z klienta kym otvorite:

import { apiClient } from '@octosign/client';
const client = apiClient();

// Launch URL that should be used by user to launch the signer application
console.log(client.getLaunchURL());

await client.waitForStatus('READY');

const content =
    '<?xml version="1.0"?><Document><Title>Lorem Ipsum</Title></Document>';
console.log(await client.sign({ content }));
// => { content: '<?xml version="1.0"?><Document><Title>Lorem Ipsum</Title>...</Document>' }

@jsuchal
Copy link
Member Author

jsuchal commented May 3, 2021

ak je stranka na HTTPS a robi request na HTTP localhost tak sa WebKit z toho posklada.

Toto je ale showstopper pre MAC nie?

@durasj
Copy link
Contributor

durasj commented May 3, 2021

@jsuchal Je to showstopper len pre macOS + Safari kombinaciu. Chrome, Firefox, Edge su fajn na macOS.

EDIT: Este vlastne k tomu co to znamena. Pre Safari by sa to dalo spravit docasne dvojkrokovo - 1. povedat pouzivatelovi, ze nech pls pouzije iny browser 2. dat mu kroky manualne pridat ten cert/nechat spustit dodatocny script a na strane implemnetacie (nie mojho clienta) spravit if (safari) configure for https. Pocuvanie na https sa da dat do custom protokolu tam kde je momentalne port - tj. bol by to bud port alebo cely hostname.

@jsuchal
Copy link
Member Author

jsuchal commented May 3, 2021

Pridat certifikat pri instalacii na strane klienta pre Mac mi nepride nejaka ohavnost. DNS - toto asi neviem od pasa posudit, ci ist stylom D.Signeru je nejaky problem. DNS zaznam vyrobit viem v pohode aj s certifikatom :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Podpisovač
In progress
Development

No branches or pull requests

4 participants