Billberry OAuth 2.0

Billberry OAuth 2.0 kaudu saad paluda kliendil mugavalt sulle e-arvete ligipääsu jagada. Nii ei pea klient ise Billberrys API võtit genereerima ja sulle meilima, vaid saab seda turvaliselt teha paari klikiga. Kliendil ei pea enne isegi Billberrys kontot olema. OAuthi ja masinliidese kasutamine on rakendustele tasuta.

Billberry OAuth 2.0 tugi on tehtud OAuth 2.0 Authorization Framework (RFC 6749) standardi järgi. OAuthi kasutamine vajab Billberry partnerkontot, mida võid paluda ühendust võttes. Ülejäänud seadistuse saad juba teha ise.

OAuthi kliendirakendus

OAuth 2.0 standard kutsub kliendiks (client) rakendust, mis küsib lõppkasutaja ehk inimese nimel ligipääsu mingile ressursile (nt e-arvetele). See on praktikas veebirakendus, kuid võib olla ka desktop- või mobiilirakendus, millel oma serverikomponenti pole. Ilma serverikomponendita rakenduste voog ei ole veel Billberrys toetatud, kuid soovi korral saab teha.

Igale kliendirakendusele on OAuth 2.0-s ette nähtud identifikaator ja parool, millega rakendus end autoriseerimisserverile ehk Billberryle tuvastab. OAuthi standard kutsub id-d ja parooli vastavalt client id ja client secret-ks.

Oauth 2.0 client id ja client secret-i saad genereerida Billberry partneri lehel, mille lingi said ühendust võttes meilitsi. Praktikas on OAuth 2.0 seadistuste lehekülg järgmisel aadressil, asendades {partnerId} oma partneri identifikaatoriga:

Partneri OAuth 2.0 seadistuste leht
https://app.billberry.ee/partners/{partnerId}/oauth2
Testkeskkonna partneri OAuth 2.0 seadistuste leht
https://dev.billberry.ee/partners/{partnerId}/oauth2

Peale OAuth 2.0 id ja parooli saad seadistuste lehel määrata lubatud suunamiste aadresse (redirection endpoint). Kui kasutaja on Billberry lehel autenditud ja ligipääsu su rakendusega jaganud, suunatakse ta tagasi vaid eelnevalt lubatud aadressidele (konkreetse aadressi saad autentimisvoogu alustades kaasa anda). See on turvameede, et ei saaks ligipääsu küsida ühe rakenduse nimel, kuid suunata kasutaja tagasi muule aadressile. Toimiseks on vajalik määrta vähemalt üks lubatud aadress.

Autoriseerimisvoog

Billberry toetab OAuth 2.0 standardi "Authorization Code Grant" voogu. Laias laastus tähendab see, et suunad kliendi esindaja Billberry veebilehele, kus Billberry valideerib ta esindusõigust ja küsib luba, kas soovib jagada ligipääsu oma e-arvetele. Ligipääsu andes suunatakse inimene tagasi eelnevalt määratud aadressile, millega tuleb kaasa autoriseerimiskood (authorization code). Autoriseerimiskood tuleb vahetada Billberry API sessioonivõtme vastu (access token), mida hiljem saab kasutada Billberry kliendi API päringute tegemiseks (nagu nt e-arve saatmine).

Autoriseerimisotspunkt

Autoriseerimisotspunkt on aadress, kuhu kasutaja brauser suunata, et autoriseerimisprotsessi alustada.

Autoriseerimisotspunkt (authorization endpoint)
https://app.billberry.ee/authorizations/oauth2/new
Testkeskkonna autoriseerimisotspunkt (authorization endpoint)
https://dev.billberry.ee/authorizations/oauth2/new

Et Billberry teaks, millise rakendusega autoriseerimist seostada, kuhu suunata ja millise ettevõtte ligipääsu küsida, tuleb autoriseerimisotspunktile kaasa anda mõned parameetrid (URLi query parameetritena).

Autoriseerimisotspunkti (authorization endpoint) parameetrid

ParameeterKirjeldus
client_idSinu rakenduse identifikaator, mille saad partneri OAuth 2.0 seadistuste lehelt.
response_typeAlati code. Tuleneb OAuth 2.0 Authorization Code Grant protsessist.
scopeSoovitud õigused-ligipääsud, mida küsid.
Näiteks send-invoices. Alt leiad loetelu õigustest.
stateVäärtus, mida saad kasutada autoriseerimisvoo konteksti säilitamiseks. Kasutajat tagasi suunates lisab Billberry sama state väärtuse kaasa.
Tavaliselt kasutatakse cross-site request forgery rünnakute takistamiseks genereerides juhuslik väärtus ja peale suunamist kontrollides, kas väärtus on sama.
redirect_uriURL, kuhu pärast eduka või vea korral kasutaja suunatakse.
Kui URLi kaasa ei pane, valitakse vaikimisi esimene partneri seadistatud lubatud aadress.
countryEttevõtte riigi ISO 3166 tunnus, millele ligipääsu küsid.
Näiteks EE.
registry_codeEttevõtte registrikood, millele ligipääsu küsid.

Autoriseerimisotspunktile, ehk sinna, kuhu kasuta brauseriga esialgu suunad, oma kliendirakenduse parooli (client secret) ära kaasa pane. Seda on vaja alles siis, kui on aeg oma serveris tagasi saadud autoriseerimiskood API võtme vastu vahetada.

Kui ettevõtte esindaja on ligipääsu jaganud (või tekkis mõni viga), suunatakse ta tagasi kas varem seadistatud OAuth 2.0 suunamise aadressile või päringuga kaasa lisatud redirect_uri parameetrile.

Autoriseerimise edukas tulemus

Autoriseerimise tulemus (authorization response) edastatakse läbi kasutaja suunamise tagasi rakenduseni (nt redirect_uri-ga antud aadressile) koos järgnevate query parameetritega.

ParameeterKirjeldus
codeAutoriseerimiskood, mille saad välja vahetada API võtme vastu.
stateSama state parameetri väärtus, mis autoriseerimisotspunktile kaasa anti.
Kontrollides, kas väärtus on sama, mis kasutaja suunamise hetkel, saab takistada CSRF rünnakut. Alt leiad pikema kirjelduse OAuth 2.0 CSRF turvanõrkusest

Autoriseerimiskoodi võid välja lugeda serveri poolel query parameetrist, kui kasutaja sinu rakendusse naaseb. Seda ei ole mõtet teha JavaScriptiga brauseris, sest autoriseerimiskoodi saab API võtme vastu vahetada vaid server. Ainult tema teab OAuthi parooli (client secret-it).

Autoriseerimise vea tulemus

Autoriseerimise tulemus (error response) edastatakse läbi kasutaja suunamise tagasi rakenduseni (nt redirect_uri-ga antud aadressile) koos järgnevate query parameetritega.

ParameeterKirjeldus
errorVeakood. Lubatud väärtused leiad OAuth 2.0 standardist
error_descriptionVea kirjeldus. Hetkel võib olla puudu või hoopis ingliskeelne.

Enamik veaolukordi suunavad tagasi sinu rakendusse. Ainsana ei tehta seda siis, kui tekkib sisemine viga Billberrys, mis seda takistab, või kui Billberry ei tea, kuhu kasutaja suunata. See juhtub, kui näiteks ei leitud client_id alusel ühtki OAuthi seadistust või ei ole redirect_uri-s antud suunamise aadress (redirection URI) lubatud.

Erinevad õigused (scope)

OAuth 2.0 standard lubab scope parameetriga kaasa anda loetelu õigustest/ligipääsudest, mida tagastatud autoriseerimiskood ja hiljem saadud API võti annavad. Hetkel toetab Billberry OAuthi kaudu vaid e-arvete saatmise küsimist, kuid plaanis on lisada ka saabunud e-arvete ligipääs. Kui seda soovid, anna teada.

ÕigusKirjeldus
send-invoicesE-arvete saatmine. Sissetulnud e-arveid näha ei saa.

Mitu õigust korraga saab küsida eraldades nad scope parameetris tühikutega.

API võtme pärimine

Kui eduka autoriseerimisvoo tulemusel on autoriseerimiskood (authorization code) käes, saab selle vahetada Billberry API võtme vastu läbi võtme otspunkti (token endpoint).

Kaheastmeline protsess on OAuthis seepärast, et lõppkasutaja ei saaks ise ligi API võtmele. Kuna lõppkasutaja ei tea sinu rakenduse OAuth 2.0 parooli (client secret), ei saa ta ka ise autoriseerimiskoodi API võtme vastu vahetada.

API võtme otspunkt (token endpoint)
https://api.billberry.ee/sessions/oauth2
Testkeskkonna API võtme otspunkt (token endpoint)
https://dev-api.billberry.ee/sessions/oauth2

Vastavalt OAuth 2.0 standardile tuleb võtme otspunktile teha päring HTTP POSTiga ja application/x-www-form-urlencoded sisuga (ehk tavaline vorm).

ParameeterKirjeldus
grant_typeAlati authorization_code. Tuleneb OAuth 2.0 Authorization Code Grant protsessist.
codeAutoriseerimiskood
redirect_uriSama väärtus, mille autoriseerimisotspunktile kaasa panid. Pole vaja lisada, kui toetusid vaikeaadressile (ehk ei edastanud redirect_uri parameetrit).

Võtme pärimine vajab kliendirakenduse autentimist. Kasuta selleks Basic autentimist, kus kasutajanimi on Billberrys seadistatud OAuth rakenduse client_id ja parool client_secret. Näiteks, kui client_id on erpsy ja client_secret on 2ab96390c7dbe3439de74d0c9b0b1767, näeb päring välja selline:

POST /sessions/oauth2 HTTP/1.1
Host: api.billberry.ee
Authorization: Basic ZXJwc3k6MmFiOTYzOTBjN2RiZTM0MzlkZTc0ZDBjOWIwYjE3Njc=
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Accept: application/json

grant_type=authorization_code&code=0ec1ee0ba914ffb9f9f5cfe19b28b7b9

Miks on vaja võtit pärida klassikalise vormiga (application/x-www-form-urlencoded), kui vastused on ette nähtud JSONis, tuleb küsida OAuth 2.0 standardi autoritelt…

API võtme edukas tulemus

Vastavalt OAuth 2.0 standardile on API võtme vastus (access token response) JSON formaadis.

HTTP/1.1 201 Session Created
Content-Type: application/json

{
    "token_type": "basic",
    "access_token": "NDI6MmFiOTYzOTBjN2RiZTM0MzlkZTc0ZDBjOWIwYjE3Njc=",
    "organization_country": "EE",
    "organization_registry_code": "10000018",
    "scope": "send-invoices"
}
VäliKirjeldus
token_typeAlati basic.
access_tokenBillberry API võti Authorization päises kasutamiseks.
organization_countryAutoriseeritud ettevõtte riigi ISO 3166 tunnus.
organization_registry_codeAutoriseeritud ettevõtte registrikood.
scopeAntud õigused/ligipääsud.

Võtme tüüp (token_type) basic tähendab, et access_token on sobilik otse Basic autentimiseks ja kopeerimiseks Authorization päisesse koos "Basic" prefiksiga (ehk Authorization: Basic NDI6MmFiO…). See tähendab, et access_token on tegelikult base64-s kodeeritud Billberry API võtme id ja parool — sama, mille saab käsitsi Billberry lehel genereerida.

Billberry kliendi API juhendist leiad rohkem infot, aga näiteks nõnda saad saata e-arveid kasutades access_token-it Authorization päises:

POST /invoices HTTP/1.1
Host: api.billberry.ee
Authorization: Basic NDI6MmFiOTYzOTBjN2RiZTM0MzlkZTc0ZDBjOWIwYjE3Njc=
Content-Type: application/xml
Accept: application/vnd.billberry.invoice+json; v=1

<E_Invoice></E_Invoice>

API võtme vea tulemus

Vea tekkimisel näeb OAuth 2.0 standard ette HTTP veakoodiga JSON vastust järgnevate väljadega.

VäliKirjeldus
errorVeakood. Lubatud väärtused leiad OAuth 2.0 standardist
error_descriptionVea kirjeldus. Võib olla vastusest puudu.

Näiteks juba kasutatud (ehk võtme vastu vahetatud) autoriseerimisvõtme puhul vastab Billberry:

HTTP/1.1 400 Authorization Already Used
Content-Type: application/json

{"error": "invalid_grant"}

API võtmete kustutamine

Kui soovid saadud API võtmeid (access token-eid) kustutada, saad seda teha OAuth 2.0 Token Revocation (RFC 7009) standardi järgi.

API võtme kustutamise otspunkt (token revocation endpoint)
https://api.billberry.ee/sessions/oauth2?_method=DELETE
Testkeskkonna API võtme kustutamise otspunkt (token revocation endpoint)
https://dev-api.billberry.ee/sessions/oauth2?_method=DELETE

Vastavalt standardile tuleb võtme kustutamise otspunktile teha päring HTTP POSTiga ja application/x-www-form-urlencoded sisuga (ehk tavaline vorm).

ParameeterKirjeldus
tokenAPI võti ehk varasemalt saadud access_token.

Sarnaselt võtme pärimisele, peab ka kustutamiseks kliendirakendust autentima. Kasuta selleks Basic autentimist, kus kasutajanimi on Billberrys seadistatud OAuth rakenduse client_id ja parool client_secret. Näiteks, kui client_id on erpsy ja client_secret on 2ab96390c7dbe3439de74d0c9b0b1767, ning kustutatav võti sama, mis varasemates näidetes, näeb päring välja selline:

POST /sessions/oauth2?_method=DELETE HTTP/1.1
Host: api.billberry.ee
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZXJwc3k6MmFiOTYzOTBjN2RiZTM0MzlkZTc0ZDBjOWIwYjE3Njc=

token=NDI6MmFiOTYzOTBjN2RiZTM0MzlkZTc0ZDBjOWIwYjE3Njc%3D

Kui päringu sisu ehk vormi programmis ise tekstist koostad, ära unusta token parameetri väärtust URL-encodemast. Näiteks = muutub %3D-ks vormis.

Kui su rakendus toetab, võid ka _method=DELETE parameetri ära jätta, ning otse HTTP DELETE meetodit kasutada:

DELETE /sessions/oauth2 HTTP/1.1
Host: api.billberry.ee
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ZXJwc3k6MmFiOTYzOTBjN2RiZTM0MzlkZTc0ZDBjOWIwYjE3Njc=

token=NDI6MmFiOTYzOTBjN2RiZTM0MzlkZTc0ZDBjOWIwYjE3Njc%3D

Võtme kustutamise edukas tulemus

Vastus kustutamisele on RFC 7009 järgi alati HTTP staatuskoodiga 204 ja tühja sisuga. Vaatamata sellele leiab infot, kas token kustutati, oli juba kustutatud või pole kunagi eksisteerinudki, HTTP staatusssõnumist.

HTTP/1.1 204 Session Deleted

Võtme kustutamise vea tulemus

Vea tekkimisel näeb RFC 7009 ette HTTP veakoodiga JSON vastust järgnevate väljadega.

VäliKirjeldus
errorVeakood. Lubatud väärtused leiad OAuth 2.0 standardist ja RFC 7009 standardist.
error_descriptionVea kirjeldus. Võib olla vastusest puudu.

Näiteks vigase võtme formaadi puhul vastab Billberry:

HTTP/1.1 400 Token Invalid
Content-Type: application/json

{"error": "invalid_request"}

Turvalisus

OAuth 2.0 standard on kirjeldanud erinevaid turvaprobleeme, mida tasub sirvida.

Cross-Site Request Forgery

Cross-site request forgery turvanõrkus OAuth 2.0 voos tekkib sellest, kui rakendus ei võrdle peale autoriseerimisvoogu tagasi suunatud kasutaja state parameetrit sellega, mis talle autoriseerimisvoo alguses määrati. Alternatiivselt on ohtlik, kui ründaja saab mõne kasutaja state parameetri teada.

Turvanõrkust saab ära kasutada nõnda:

  1. Ründaja teeb sinu rakenduses konto ja alustab autoriseerimisvoogu.
  2. Ründaja annab Billberrys ligipääsu mõnele ettevõttele.
  3. Billberry suunab ründaja tagasi su rakendusse, kuid rakendusse jõudmise asemel paneb ründaja aadressi (koos autoriseerimiskoodiga) kõrvale.
  4. Ründaja suunab ise sinu rakendusse sisseloginud ohvri autoriseerimiskoodiga aadressile.
    Veebis on lihtne inimesi nende teadmata suunata. Lehe külastus võib telgitaga olla kasvõi mõni peidetud pilt veebilehel (<img src="…">).
  5. Sinu rakenduse vaatenurgast oli ohver see, kes autoriseerimist alustas ja kelle kontoga tuleb nüüd uus ettevõte siduda.

Kas eelnev on praktikas turvanõrkus või lihtsalt bugi, sõltub rakendusest. Kui näiteks kõik ühe ettevõttega seotud inimesed saavad ligi teineteise andmetele, võib tekkida andmeleke. Kui toetad Google'i kontoga sisselogimist ja ründaja saab nõnda oma Google'i konto ohvri konto külge, saaks ründaja pärast enda Google kontoga sisse logida.

Turvanõrkuse ärahoidmiseks on üks lahendus enne autoriseerimislehele suunamist määrata kasutajale juhusliku sisuga "CSRF token" cookie. Näiteks nimega oauth_csrf_token. Selle juhusliku väärtuse saab anda Billberryle state parameetris. Kui autoriseerimine läbi, suunab Billberry kasutaja tagasi koos sama state parameetri sisuga. Rakenduse server selle peale kontrollib, kas oauth_csrf_token cookie on alles, ja kas selle sisu klapib state parameetri väärtusega. Kui mitte, võib tegu olla CSRF rünnakuga.

Oluline on enne väärtuste võrdlemist kontrollida oauth_csrf_token cookie eksistentsi. Vastasel juhul võib ründaja lihtsalt state parameetri ära jätta. Kui kasutaja pole kunagi ise OAuthi voogu alustanud, pole tal ka CSRF tokeni cookie-t.