Drukowana wersja tematu

Kliknij tu, aby zobaczyć temat w orginalnym formacie

Forum PHP.pl _ PHP _ Dwie aplikacjie, jedna domena, SSO

Napisany przez: aldtest 28.06.2022, 12:35:50

Posiadam dwie aplikacje w obrębie jednej domeny. Zrobiłem SSO tak aby z poziomu jednej aplikacji możliwe było logowanie do drugiej.

W pierwszej aplikacji zrobiłem token, który zawiera również nazwę użytkownika.

  1. $token = http://www.php.net/bin2hex(random_bytes(32)).'&'.$user;
  2. file_put_contents("token.txt",$token);


W drugiej aplikacji dekoduje token i jeżeli występuje dany użytkownik i występuje plik token.txt to pomijam hasło i wpuszczam do drugiego systemu. Po wylogowaniu z jednego z systemów token jest kasowany.
  1. $token_code = http://www.php.net/preg_replace('/&.*/s','', $token);
  2. $token_user = http://www.php.net/preg_replace('/.*&/s','', $token);


Niestety zauważyłem pierwszy błąd tzn. jeżeli zaloguje się na innej przeglądarce to wtedy utworzy się token.txt więc inna osoba z innej przeglądarki może wywołać bezpośrednio drugą aplikacje i bez logowania wejdzie bo spełniło wszystkie warunki. Czy ktoś ma jakiś pomysł aby zrobić np. token unikalny, może jakiś unikalny sessions_id bądź cookies.

Trochę utknąłem i nie wiem co dalej facepalmxd.gif

Chyba znalazłem rozwiązanie mojego problemu. Dołożyłem
  1. $_COOKIE['token'],
który następnie jest wysyłany za pomocą
  1. http://www.php.net/header("Set-Cookie: CookieToken=$sso_id; Domain=abc.pl; Path=/; Secure;");

Napisany przez: viking 28.06.2022, 12:58:57

Czyli zrobiłeś po prostu sesję (session_start właśnie to robi przy odpowiedniej konfiguracji). Każdy kto zgarnie to cookie będzie mógł się zalogować bez danych. Nie możesz wprowadzić oauth?

Napisany przez: aldtest 28.06.2022, 14:42:05

Zrobiłem tak aby nikt nie mógł wprowadzić id sesji. Dodatkowo zamknąłem to w obrębie adresu IP.

  1. if(!http://www.php.net/isset($_SESSION['initiate']))
  2. {
  3. http://www.php.net/session_regenerate_id();
  4. $new_session_id = http://www.php.net/session_id();
  5. http://www.php.net/session_write_close();
  6. http://www.php.net/session_id($new_session_id);
  7. http://www.php.net/session_start();
  8.  
  9. $_SESSION['initiate'] = 1;
  10. }

Napisany przez: gino 29.06.2022, 06:39:39

Nie do końca tak. Każde wywołanie aplikacji podrzędnej powinno trafić do aplikacji głównej (logującej) ze swoim adresem. Dopiero aplikacja logująca decyduje co dalej, sprawdza, czy dany użytkownik jest zalogowany, czy ma prawa do aplikacji, ustala klucz (pary kluczy, token), zakodowanego user-a i odsyła to wszystko do aplikacji podrzędnej. Jakakolwiek zmiana stanu user-a w aplikacji głównej (upłynięcie czasu sesji, wylogowanie, próba Session Fixation) ma skutkować odpowiednimi działaniami w aplikacji podrzędnej. Bez żadnych cookies. Tyle w bardzo krótkiej formie.
@viking podał bezpieczne rozwiązanie.

Napisany przez: aldtest 29.06.2022, 14:28:30

Taki warunek również jest zrobiony. W momencie wylogowania z aplikacji A token jest kasowany oraz zmienia się id sesji. W aplikacji B jest ustawiony warunek jeżeli brakuje pliku z tokenem oraz id sesji się zmieni następuje również wylogowanie z aplikacji B. Każdorazowe wywołanie aplikacji B sprawdza czy jest plik z tokenem oraz czy id sessji jest równy $_COOKIE['token'] w innym wypadku jest logout. Tak jak wspomniałem dodatkowo zamknąłem to wszystko w obrębie adresu IP.

Jasne wiem że mogę to zrobić za pomocą oauth natomiast chce się trochę pobawić sesją i cookies dlatego tak kombinuje. Może trochę jak koń pod górę ale chce mieć pewność że to co zrobiłem ma sens i jest bezpieczne albo ma to poważne luki i nie ma co się w dalej bawić.

Napisany przez: gino 30.06.2022, 06:56:03

Tego nie robi się na plikach tekstowych z tokenem, przynajmniej ja takich systemów nie znam (nie używam). Wygenerowane tokeny w części aplikacji służącej do autoryzacji użytkownika można zapisać do bazy łącznie z UUID usera i w sesji. Można porównywać wtedy klucze na bieżąco. W plikach tekstowych zawsze istnieje niebezpieczeństwo podejrzenia takiego pliku. W większych systemach używa się nawet dedykowanych maszyn (serwerów autoryzacji) tak jak na przykład u mnie w firmie.

Napisany przez: aldtest 30.06.2022, 14:26:54

Dzięki za wszystkie sugestie. Wycofałem się z generowania wartości do pliku oraz cookies. Poszedłem po najniższej lini oporu tzn. skoro dwie aplikacje są na tej samej domenie to w aplikacji A zrobiłem tak:

  1. if(!http://www.php.net/isset($_SESSION['data_sso']))
  2. {
  3. $_SESSION['data_sso'] = [];
  4. $_SESSION['data_sso']['user'] = $user;
  5. }


W aplikacji B sprawdzam czy istnieje $_SESSION['data_sso'] i do działa zdecydowanie lepiej niż to co zrobiłem wcześniej. Dodatko zamknąłem to wszystko w obrębie danej puli adresów IP więc wydaje mi się że to powinno wystarczyć.
  1. if(http://www.php.net/isset($_SESSION['data_sso'])){
  2. $user = http://www.php.net/isset($_SESSION['data_sso']['user']) ? $_SESSION['data_sso']['user'] : null;
  3. //coś tam
  4. }

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)