Zadejte hledaný výraz...

Ověření tokenu na straně API

David Musil
verified
rating uzivatele
(69 hodnocení)
12. 5. 2016 23:10:23
Ahoj,
uz jsem tu mel dneska jeden dotaz, ale mam dalsi ohledne API a ohledne tokenu, ktery predavam v hlavicce pomoci CURL.
Kdyz pomoci CURL volam overeni pres user a pass (to funguje) a jeste k tomu token, netluce se to spolu? Mohu to vubec takto kombinovat?
Pri overeni pres user a pass API pracuje take jak ma. Bohuzel pose, co pride hlavicku s tokenem, tak vubec nepracuje a nemam ani moznost udelat nejaky kontrolni vypis, protoze nedostanu od API zadnou informaci.
Otazka tedy zni, co udelat na strane API, abych v nem ten token overil a API pracovalo. Pokud tedy vubec jde token kombinovat s tim overenim pres user a pass.
$url = 'http://localhost/server00/MY_API/?table=objects&id=2';
$token = '$1$iXO7kwj0$27QR0QVQHWfPu5OoHDuYE0';
$user = 'admin';
$pass = 'pass';
$header = array('Accept: application/json', 'Authorization: ' . $token);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//curl_setopt($ch, CURLOPT_USERPWD, $json);
$response = curl_exec($ch);
12. 5. 2016 23:10:23
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195568
tomve
verified
rating uzivatele
(22 hodnocení)
13. 5. 2016 00:31:32
Většina APIček má jen token (dlouhý + komplikovaný).
Za mě - login kompletně vyhodit a soustředit se na tvorbu tokenu + api skrz https.
Víceméně login plní funkci tokenu a naopak, takže řešíš 1 věc 2x.
13. 5. 2016 00:31:32
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195567
TomasX
verified
rating uzivatele
(4 hodnocení)
13. 5. 2016 01:28:18
pokud nechceš/nemůžeš použít oauth, jediná správná cesta digest namísto basic. Důležité je minimalizovat riziko v případě vyzrazení hlaviček (ať už cestou či z logů) a hlavně neposílání hesla při každém požadavku (s heslem se musí manipulovat co nejméně a hlavně ho nikam neposílat).
Mrkni na http://php.net/manual/en/features.http-auth.php, pokud bys chtěl, vysvětlím jednotlivé části či ti hodím funkční kód.
13. 5. 2016 01:28:18
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195566
Jan Kuthan
verified
rating uzivatele
(48 hodnocení)
13. 5. 2016 08:08:05
osobně se mi líbí varianta s heslem a jménem si říci na jednu funkci o token a pak k další komunikaci používat tento token, token má nastavenou expiraci např. na pár hodin
13. 5. 2016 08:08:05
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195565
ViPErCZ
verified
rating uzivatele
(21 hodnocení)
13. 5. 2016 08:17:23
Jinak s tím původním dotazem jak si poslat token jsem ti napsal do původního vlákna ještě.
Osobně bych se taky podíval přes google jak to už někdo vyřešil přede mnou... tedy na nejlepší způsob. Určitě bude lepší posílat jen nějaký auth token a ne uživatelské jméno a heslo a navíc porád dokola při každém requestu.
13. 5. 2016 08:17:23
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195564
TomasX
verified
rating uzivatele
(4 hodnocení)
13. 5. 2016 10:35:39
ne, nejlepší způsob je hashovat url, čas a neposílat žádný statický auth token, což není nic jiného než heslo, rozdíl v tom není. K tomu přidat nonce, aby i opakované požadavky měly jiný auth. Stejně tak je nutné na serveru kontrolovat čas a nechat max. odchylku třeba deset minut, tím zajistíš, že starý někde uniklý auth nelze jíž v budoucnu použít a jen pouze držitel původního secret dokáže vygenerovat nový požadavek. Myslete na to, že SSL nic neochrání, často dochází k terminaci někde na bráně, na proxy a zbytek cesty v mezi servery jedou data v čitelné podobě. Stejně tak http hlavičky se různě logují, analyzují a přístup do nich má kde kdo, tam nesmí být tajné věci, natož hesla.
Nemá smysl vymýšlet nic nového, již je to více než dvacet let co tady http digest. Hezky je celý proces popsaný na wiki https://en.wikipedia.org/wiki/Digest_access_authentication#Example_with_explanation, jen místo md5 dej sha256, pro serverou část může vynechat ten challenge (klient se zeptá na stránku a server mu odpoví s jeho nonce) a jsi za vodou.
Naivní implementace by mohla vypadat nějak takhle, psáno přímo v prohlížeči, omluvte případné syntax errory, v php nedělám denně:
function generate_auth_header($uri, $method, $token) {
$time = time();
$nonce = uniqid();
$realm = base64_encode("$method $uri $time $nonce");
$digest = base64_encode(hash_hmac("sha256", $realm, $token, $binary = true));
return "$realm:$digest";
}
function is_valid_auth_header($current_uri, $current_method, $token, $auth) {
$date_margin = 60 * 10; // 10 minutes
list($realm, $digest) = explode(":", $auth);
list($method, $uri, $time, $nonce) = explode(" ", base64_decode($realm));
if($current_uri !== $uri) return "missmatch uri";
if($current_method !== $method) return "missmatch method";
if($time > time() + $date_margin) return "date is in future";
if($time < time() - $date_margin) return "expired date";
$my_digest = base64_encode(hash_hmac("sha256", $realm, $token, $binary = true));
return hash_equals($my_digest, $digest);
}
// kód u klienta pro generování správné hlavičky
$method = "PUT";
$uri = '/server00/MY_API/?table=objects&id=2';
$url = "http://localhost" . $uri;
$token = '$1$iXO7kwj0$27QR0QVQHWfPu5OoHDuYE0';
$auth = generate_auth_header($uri, $method, $token);
$header = array('Accept: application/json', 'X-Hmac-Authorization: ' . $auth);
// případně to lze skombinovat i s jménem a heslem pro lepší možnost hlídání práv
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$response = curl_exec($ch);
//kód na serveru pro ověření hlavičky
$method = $_SERVER;
$uri = $_SERVER;
$token = '$1$iXO7kwj0$27QR0QVQHWfPu5OoHDuYE0';
$auth = $_SERVER; //je možné použít i původní authorization hlavičku, ale mod_cgi dříve neuměl jí předávat
$valid = is_valid_auth_header($uri, $method, $token, $auth);
if($valid === true) {
die("request is valid");
} else {
die("auth error: $valid");
}
13. 5. 2016 10:35:39
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195563
ViPErCZ
verified
rating uzivatele
(21 hodnocení)
13. 5. 2016 11:15:07
Jo něco takového jsem měl na mysli. Jen mi úplně z hlavy nebylo jasné, když ten statickej token co tam máš budu hledat v databázi. To budu validovat přes všechny záznamy?
Proto jsem úplně nenapsal odpověď konkrétně, ale rovnou s tím najít si to na google.
PS: jen doplním, že pokud budete posílat stále stejný token, tak to je skoro jak heslo... jendou se někomu může podařit ho ukrást a vyjde to nastejno jak kdyby měl heslo. Zahashovat ho s nějakým "saltem" a posílat tenhle paskvil bude daleko složitější vydolovat.
13. 5. 2016 11:15:07
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195562
TomasX
verified
rating uzivatele
(4 hodnocení)
13. 5. 2016 11:26:01
kód, který jsem tady napsal je pouze autorizace, tj. ověření práv. Autentizace (ověření identity a získání tokenu z databáze) se může zajistit jakkoliv, klidně použítí http basic auth s jménem a heslem, viz komentář a původní kód, takové řešení bych doporučoval, správně totiž autorizace a autentizace má být oddělená. Či je možné jméno přidat do realmu pro jednoduchost. Nic ani nebrání použití PKI v podobě třeba PGP.
Tenhle algoritmus a takovéhle ověření je odolné proti MitM a nemusím se bát úniku hlaviček. Pro lepší bezpečnost je ještě možné ukládat celý auth po dobu časové tolerance (10 minut) a nedovolit stejný použít znovu. Lze také skombinovat s oauth a samotný token ověřovat vůči třetí službě a nechat ho pravidelně přegenerovávat, tím mohu právě autentizaci předat na třetí osobu (google, google apps, facebook, ldap) a daleko lépe řešit práva a přístupy.
13. 5. 2016 11:26:01
https://webtrh.cz/diskuse/overeni-tokenu-na-strane-api#reply1195561
Pro odpověď se přihlašte.
Přihlásit