Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Generowanie kodu autoryzacyjnego
Forum PHP.pl > Forum > PHP
kowi87
Witam!
Stanąłem przed nie lada wyzwaniem, ponieważ podczas prac nad aplikacją doszedłem modułu autoryzacji.
A ten potrzebuję by działał w następujący sposób:
- zewnętrzna aplikacja do procesu automatycznej autoryzacji będzie używać dwóch danych: ID (np: uuid) i wygenerowany kod
- aplikacja napisana w PHP ma za zadanie również wygenerować ten kod (identyczny) i porównać z tym przesłanym przez zewnętrzny program

Próbowałem generować kody w oparciu o timestamp w fomacie UNIX, lecz problemem jest ewentualna różnica pomiędzy czasem aplikacji klienta, a czasem serwera.

Chodzi o to, by na podstawie jakiejś danej w danym momencie wygenerować kod, który byłby ważny tylko w obecnej chwili + jakiś krótki odcinek czasu na wypadek wolnego łącza.

Czy istnieje coś takiego, na czym można oprzeć powyższe rozwiązanie autoryzacji?
Ewentualnie, może ktoś ma lepszy pomysł.
kartin
TOTP - Time-Based One-Time Password Algorithm. Ewentualna różnica w czasie nie jest problemem, o ile nie będzie się mocno zmieniać pomiędzy kolejnymi autoryzacjami.
Pyton_000
@up. Weź Ty czytaj tematy zanim coś napiszesz. Bo to już kolejny temat w którym piszesz głupoty nie na temat zadany w temacie.
Pyton_000
Chodzi o autoryzację 2 etapową.
Powiedzmy coś na wzór Tokenów z Battle.net czyli logujesz się i aplikacja prosi Cię o kod z Tokeny. Token jest waży przez kilka sekund.

Chodzi właśnie o problem tych tokenów, ich generowanie i żywotność.
kowi87
Cytat(darek334 @ 5.06.2015, 20:08:50 ) *
Coś na wzór czasowego captchta ? Bo zrozumiałem raczej jako token autoryzacyjny do jednego użycia coś na wzór zabezpieczenia formularza przed ponownym jego wysłaniem
dobra nie ważne napisałem to co napisałem , trzeba poczekać na autora co odpowie i nie pisz mi że ja pisze na forum głupoty bo na prawdę staram się tego unikać, bo krytykować bez podstawnie to każdy może a tu nie jest od tego miejsce

Aplikacja kliencka w konkretnym systemie operacyjnym ma wygenerować UUID i użyć go jako loginu, a jako czegoś w stylu hasła ma użyć jednorazowego kodu który wygeneruje w momencie łączenia się - kodu identycznego z tym, który po swojej stronie również podczas próby połączenia wygeneruje skrypt napisany w PHP, z którym wspomniana aplikacja się połączy. Cały ten zabieg po to, by aplikacja kliencka nie mogła uruchamiać funkcji ze skryptu PHP bez odpowiedniej weryfikacji.

Kartin w pierwszej odpowiedzi zaproponował rozwiązanie z użyciem TOTP, które już próbuję zaadoptować do mojego środowiska. Zobaczymy co z tego wyjdzie, bowiem całość opiera się na timestampie, a nie wiem jak zachowa się system w przypadku znacznej różnicy czasu pomiędzy klientem, a serwerem. Jeśli ktoś posiada wiedzę na ten temat proszę o podzielenie się nią.
Comandeer
@darek334 ale weź przeczytaj dokładnie problem…

Chodzi o wygenerowanie tego samego hasła dwa razy - tak, żeby było identyczne. I stąd pomysł z TOTP: token jest generowany na podstawie czasu i uuid, więc w danym przedziale czasu zawsze będzie takie samo.

@kowi87 różnica w czasie - rozumiem, że chodzi Ci o strefy czasowe? Jeśli tak to przecież można generować wg czasu UTC - wówczas powinien być identyczny.
kartin
Cytat(kowi87 @ 6.06.2015, 12:51:25 ) *
Zobaczymy co z tego wyjdzie, bowiem całość opiera się na timestampie, a nie wiem jak zachowa się system w przypadku znacznej różnicy czasu pomiędzy klientem, a serwerem. Jeśli ktoś posiada wiedzę na ten temat proszę o podzielenie się nią.

Algorytm TOTP zakłada generowanie tokena na podstawie tzw. czasu uniksowego zatem problem różnych stref czasowych jest rozwiązany na starcie.
Przy pierwszym połączeniu - dodawaniu nowego klienta, możesz różnicę między czasem klienta a czasem rzeczywistym ustalić i uwzględniać ją przy dalszej weryfikacji kodów.

Bardzo często czas na komputerach jest synchronizowany przez NTP z serwerami czasu, więc w takich przypadkach różnica między czasem klienta a rzeczywistym nie będzie zwykle miała znaczenia. W przypadku braku synchronizacji błąd raczej nie przekroczy kilku-kilkudziesięciu minut. Zatem czas klienta możesz ustalić na podstawie przesłanych przez niego kodów.
Możesz też przy pierwszym połączeniu danego klienta po prostu wysłać czas do serwera i na tej podstawie obliczyć różnicę czasu.

Podczas kolejnych autoryzacji dobrze jest na podstawie przesyłanych kodów utrzymywać synchronizację czasu. Czyli jeśli klient kilka razy prześle kod np. o jeden do przodu to znaczy, że jego zegar zaczyna śpieszyć i należy do zapamiętanej różnicy czasu dodać jedną jednostkę czasu.

Polecam poczytanie RFC 6238 w sekcji 6 jest opisany problem utrzymywania synchronizacji czasu.

Cytat(darek334 @ 6.06.2015, 16:53:09 ) *
Jeśli Twój problem polega tylko na wygenerowaniu jakiegoś kodu, to jeśli dobrze zrozumiałem, to ja ze swojej strony ponieważ pisałem już podobny kod do autoryzacji formularzy czyli po to aby nie można było użyć tego samego formularza dwa razy co moim zdaniem jest o wiele trudniejszym zadaniem niż to o czym piszesz

Masz inną skalę trudności i wygląda na to, że źle zrozumiałeś o co chodzi w tym temacie.

W przypadku chęci zabezpieczenia formularza przed wielokrotnym wysłaniem wystarczy wygenerowanie przez serwer dowolnego kodu, byle dla danego klienta był inny za każdym razem. Może to być bieżący czas, kolejna liczba, kolejne słowo z Pana Tadeusza. Cokolwiek wygenerujesz zapisujesz w zmiennej sesji i porównujesz z wartością przysłaną wraz z innymi danymi formularza. Jeśli zgadza się to akceptujesz formularz, jeśli nie to nie.

Wyobraź sobie, że do zalogowania do banku potrzebujesz dodatkowo kodu generowanego przez sprzętowy lub programowy (np. zainstalowany na telefonie) token. To jest przypadek z tego tematu i tutaj chodzi o wygenerowanie przez obie strony niezależnie od siebie identycznego kodu, którego dodatkowo nikt postronny nie odgadnie. W takich przypadkach stosowane są algorytmy TOTP, HOTP (HMAC-Based One-Time Password Algorithm) lub analogiczne.

Jak interesuje cię temat losowości to poczytaj sobie o tym czy generowane liczby losowe są rzeczywiście losowe. Inna ciekawostka to hasło "nsa intel random".
Comandeer
Cytat
jak dla mnie takie podejście jest błędne i wogóle niezgodne z zasadami bezpieczeństwa.

Polecam sprawdzić kto podpisał się pod tym RFC
Cytat
Token tworzony na podstawie czasu jest łatwy do podrobienia i nikt poważny go nie stosuje.

Nikt… oprócz Google, MS, Facebooka, Twittera, usług typu Authy itd. Generator kodów FB to nic innego jak TOTP w praktyce.
Cytat
Skoro takie rozwiązanie było by skuteczne to dlaczego PHP tego nie stosuje

Bo jest rozwiązaniem specyficznym, do wąskiej grupy przypadków.
Cytat
Zabezpieczenie sesji (bo można to tak nazwać) za pomocą tokenu tworzonego na podstawie timestamp to fatalny pomysł, nie do autoryzacji klienta.

Raczej tego typu token służy do jednorazowej autoryzacji operacji, nie klienta jako takiego.
Cytat
Piszesz o bankach ale przecież ich strony działają na skryptach PHP opartych na tych metodach, więc o czym mowa !

Dam se rękę uciąć, że połowa banków a) nie stoi na PHP cool.gif nie stosuje natywnych sesji
Cytat
Z tego co zrozumiałem chodzi tutaj o autoryzację klienta.

FB przecież też tak poniekąd autoryzuje usera: kod przy logowaniu działa przecież na takiej zasadzie.
kowi87
Cytat(darek334 @ 9.06.2015, 16:04:11 ) *
widzę że autor porzucił wątek bo nie odpisuje

Niestety z powodu pracy nie jestem w stanie regularnie odwiedzać tego tematu.

Rozwiązanie poprzez weryfikację tokena tworzonego na podstawie czasu nie jest tak fatalnym rozwiązaniem, jak sądzisz. Bowiem do wygenerowania tego tokena nie jest brany pod uwagę jedynie czas, ale również inne dane.

Tu znajdziesz aplikację webową, która pomoże lepiej zrozumieć temat, tak jak mi pomogła smile.gif
http://dziobson.net/prjs/rfc6238/
kowi87
Cytat(darek334 @ 17.06.2015, 18:01:31 ) *
Jeśli chodzi o ten link to skrypt ma błąd, bo po wysłaniu zapytania zmienne nie są prawidłowo przechowywane przez sesję co powoduje ustawienie się zmiennych spowrotem na domyślne wartości, tak więc nie ma możliwości przetestowania innych wartości, natomiast wciskając refresh kod nie zmienia się a jego czas ważności z 30sek staje się stały.


Trochę męczyłem tą appkę i nie zauważyłem by był tam błąd.
Fakt, że jak wygeneruję kod, to potem ponownie są domyślne wartości we wszystkich polach prócz timestampu, ale zależnie od np: wybranego szyfrowania kod jest inny.

Chyba, że masz coś innego na myśli. Wyjaśnij proszę.
darek334
Hej,
właśnie o to mi chodziło, że po wygenerowaniu kodu sesja tego nie zapamiętuje i resetuje zmienne do domyślnych początkowych wartości na stronie przez co nie ma możliwości sprawdzenia innych wartości tylko 30sek itp, z kolei jak wciskasz refresh to ten niby kod którym chcesz autoryzować klienta przedłuża się w nieskończoność a przecież ma to być kod autoryzujący klienta.
Comandeer
Może dlatego, że znacznik czasu Unixa jest polem formularza, więc jak odświeżasz to generuje dla tego samego znacznika czasu? Więc działa to zgodnie z założeniem.
darek334
Hej,
inicjuje się zgodnie z założeniem, z tym się zgodzę, ale jako formularz tu przytoczony powinien działać też jako ten formularz...
Comandeer
Ale przecież to działa jak każdy normalny formularz. Odświeżasz, ponownie wysyłasz ten sam formularz, więc generuje kod dla znacznika przesłanego w formularzu… więc generuje kod "z przeszłości" - zgodnie z Twoim własnym życzeniem. Nie bardzo rozumiem gdzie tu jest jakiś błąd?
darek334
ok z tym się zgodzę, chodzi mi o sens tego używania skoro to ma być sposób na autoryzację to jakoś słaby skoro nieodporny na takie refreshe itp, ja to sobie przyrównuje do sposobu działania sesji w php, dobrze ustawiona sesja nie ma takich problemów a przeciez sesja jest po to aby właśnie autoryzować. Ktoś tu próbuje wytłumaczyć że autoryzowanie na zasadzie równoczesnego tworzenia kodu na podstawie timestamp jest dobre smile.gif. Soro ktoś daje taki przykład taką teorię to powinna ona być przekonująca. Jak na razie tego nie widzę. A dyskusja wokół tych kodzików przypomina mi troszkę takiego mistrza karate "uderz mnie tu i tu a ja zrobie to i to".
Comandeer
Ok, ale patrz: mamy do czynienia z aplikacją i serwerem. Problem polega na tym, że aplikacja musi coś przekazać serwerowi raz. Łączy się z nim po SSL i podaje swoje ID, po czym żeby potwierdzić to ID przekazuje wygenerowany kod czasowy na podstawie sekretnego hasła. Serwer sprawdza czy aplikacja o takim ID może takie hasło wygenerować w danym momencie czasu (więc musi to być oparte na jakimś standardzie) i tyle. Operacja jest wykonywana i serwer i aplikacja zapominają, że coś miało być zrobione. Tak ja to widzę.

Czy jest to wystarczająco bezpieczne? Zależy jaka to aplikacja, ale IMO do większości rzeczy takie coś by się nadało.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.