Co to jest weryfikacja dwuetapowa i jak ją stosować w Drupalu?
Weryfikacja dwuetapowa, w skrócie 2FA (ang. two factor authentication) jest coraz częściej spotykaną funkcjonalnością na stronach internetowych. Z tego tekstu dowiesz się, jak ją kompletnie wdrożyć na stronie opartej o Drupala 9 lub 8.
Co to jest weryfikacja dwuetapowa?
Weryfikacja dwuetapowa to proces uwierzytelniania użytkownika podczas logowania, który składa się z dwóch metod kontroli. Pierwszą jest znane wszystkim logowanie poprzez podanie loginu oraz hasła. Wraz z rozwojem sieci web, gdzie powstało wiele serwisów, które trzymają wrażliwe dla nas dane np. Facebook czy Github, zwiększyło się ryzyko ataków i tego, że ktoś nieuprawniony uzyska dostęp do naszego konta. Aby temu przeciwdziałać, wprowadza się drugą metodę weryfikacji. Nie daje ona stuprocentowej pewności, że nasze dane są niezagrożone, ale znacznie poprawia bezpieczeństwo, np. Drupala.
Najpopularniejszymi metodami drugiej weryfikacji podczas logowania są:
- kod wysyłany w wiadomości SMS,
- lista wygenerowanych kodów do wykorzystania,
- generowanie kodów dostępu w zewnętrznych aplikacjach np. Google Authenticator.
Implementacja weryfikacji dwuetapowej w Drupalu
Wdrożenie podstawowej wersji omawianej funkcjonalności sprowadza się do instalacji kilku modułów i ich konfiguracji.
Podstawowa wersja obejmuje:
- zmianę procesu logowania w Drupalu,
- nowy blok z formularzem logowania,
- generowanie tekstowych kodów dostępu.
Rozszerzone zagadnienia, które opiszemy w tym tekście będą dotyczyć generowania kodów w aplikacji Google Authenticator oraz kodów wysyłanych na adres e-mail.
Moduły
Do zbudowania dwuetapowej weryfikacji, przedstawionej w tym wpisie, potrzebne są moduły:
- Two-factor Authentication (TFA) - główna funkcjonalność,
- Key - moduł do zarządzania kluczami w Drupalu,
- Encrypt - pozwala innym modułom na szyfrowanie i odszyfrowywanie danych,
- Real AES lub inny moduł dodający metodę szyfrowania (lista tych modułów wymieniona jest na stronie modułu Encrypt),
- GA_login - integracja z Google Authenticator, aplikacją na telefon generująca kody.
Instalacja
Najszybszą metodą instalacji wszystkich potrzebnych modułów jest wykorzystanie Composera i wykonanie komendy w shell:
composer require drupal/tfa
oraz
composer require drupal/real_aes
Jeżeli nie używasz Composera to pobierz każdy z tych modułów i rozpakuj w katalogu, gdzie znajduje się strona - /modules/contrib. Jeżeli nie masz katalogu contrib, potrzebujesz go utworzyć.
Teraz włącz wszystkie moduły.
Drush: drush en key real_aes encrypt tfa ga_login
Lub klasycznie na stronie /admin/modules
Proces logowania po instalacji modułu Two-factor Authentication (TFA)
- Użytkownik wpisuje swoje dane logowania (login i hasło) w formularzu i zatwierdza.
- Jeżeli dane są poprawne, Drupal tworzy sesję użytkownika, którego identyfikuje jako uwierzytelniony.
- Moduł TFA implementuje hook_user_login.
- TFA sprawdza, czy zalogowany użytkownik powinien użyć drugiej metody weryfikacji. Jeżeli tak - następuje wylogowanie i przekierowanie na drugą metodę weryfikacji.
- Następuje proces weryfikacji np. poprzez wpisanie kodu z wiadomości SMS.
- Jeżeli kod jest poprawny, następuje ponowne zalogowanie użytkownika.
Konfiguracja modułów
Pierwszą rzeczą jest stworzenie klucza do szyfrowania. W tym celu przejdź do konfiguracji modułu Key i dodaj nowy klucz.
/admin/config/system/keys/add
Nadaj nazwę kluczowi. Jako typ klucza wybierz Encryption, a Key size ustaw na 256 bitów.
W ustawieniach, skąd jest pobierany klucz, są trzy opcje do wyboru. Jednak zalecam, biorąc pod uwagę bezpieczeństwo, wybrać, aby klucz był trzymany w pliku poza głównym katalogiem strony lub jako zmienna środowiskowa (env).
W przypadku pliku w File location trzeba podać ścieżkę, gdzie znajduje się plik. Musi on już wcześniej istnieć, bo bez tego nie będzie można zapisać zmian. Poniżej możesz zobaczyć, jak wygenerować taki plik.
Ścieżka do pliku
../keys/tfa.key
Gdzie .. (dwie kropki) oznaczają, że wychodzimy wyżej z bieżącego katalogu.
Trzecią opcją, niepolecaną, jest trzymanie klucza w plikach konfiguracyjnych, przy których trzeba uważać, ponieważ znajdują się w katalogu, gdzie leży strona. Mogą też omyłkowo zostać wysłane do repozytorium.
Na screenie poniżej można zobaczyć przykładową strukturę katalogów uwzględniającą pozycję, gdzie trzymane są klucze.
- Web - katalog z Drupalem,
- keys - katalog z kluczami,
- tfa.key - plik z kluczem.
Jak wygenerować klucz 256 bitowy?
Najłatwiej zrobić to przy pomocy komendy linuksowej:
openssl rand -base64 32 > tfa.key
lub
dd if=/dev/urandom of=keyfile bs=32 count=1 > tfa.key
W obu przypadkach wynikiem będzie stworzenie pliku tfa.key z wygenerowanym kluczem.
Po zapisaniu zmian przechodzimy do konfiguracji modułu Encrypt, gdzie musimy dodać profil szyfrowania.
/admin/config/system/encryption/profiles
Konfiguracja jest prosta, ogranicza się do wybrania metody szyfrowania, w tym przypadku dostarczonej przez moduł Real AES, oraz wybraniu klucza stworzonego przed chwilą.
Po tych operacjach można przejść do konfiguracji modułu TFA, która znajduje się na stronie
/admin/config/people/tfa
Z tego miejsca zarządzamy całą funkcjonalnością. Włączamy i wyłączamy 2FA (two-factor authentication - weryfikacja dwuetapowa) dla naszej strony, standardowo 2FA jest wyłączona. Wybieramy także role, dla których wymagane będzie 2FA. Ważne, aby na stronie z uprawnieniami wybrana rola miała dostęp do skonfigurowania 2FA.
Pluginy do uwierzytelniania dwuetapowego
Po zainstalowaniu wyżej wymienionych modułów mamy trzy pluginy do wyboru. Dwa z nich bazują na aplikacji Google Authenticator.
- Time-based OTP - aplikacja serwuje czasowe kody, które umożliwiają zalogowanie się do strony.
- Hmac-based OTP - generowany jest klucz hash i w przypadku zgodności użytkownik może się zalogować.
Trzeci plugin dostępny jest bezpośrednio z modułu Two-factor Authentication.
- TFA Recovery codes - generuje użytkownikowi zadaną liczbę kodów do wykorzystania podczas logowania.
Możemy tworzyć własne pluginy (wspomnimy o tym w dalszej części wpisu) i wprowadzać nowe sposoby na uwierzytelnianie np. poprzez kody SMS.
W ustawieniach można też podać, ile razy użytkownik może pominąć włączenie 2FA. Standardowo są to 3 logowania. Po zalogowaniu pojawi się komunikat.
Jeżeli uprawnienia dla roli są poprawnie ustawione, na stronie profilu pojawi się zakładka Security z możliwością konfiguracji każdej z włączonych metod uwierzytelniania.
Adres: /user/UID/security/tfa
Aby dwuetapowa weryfikacja była włączona, wystarczy skonfigurować jedną metodę. Jeżeli będzie skonfigurowanych więcej, podczas logowania użytkownik będzie mógł wybrać ten sposób, z którego skorzysta, nie będzie musiał weryfikować się przy pomocy każdego z nich.
Włączenie pluginu TOTP i HOTP odbywa się z użyciem wybranej aplikacji na telefon, czyli:
- Google Authenticator (Android/iPhone/BlackBerry),
- Authy (tylko TOTP),
- FreeOTP (Android),
- GAuth Authenticator (desktop).
Potrzebne jest także zeskanowanie w aplikacji wygenerowanego kodu QR.
Po tej operacji kody będą generowane w aplikacji telefonu. Teraz wystarczy wygenerować pierwszy kod i zatwierdzić. Jeżeli jest poprawny to wybrana metoda będzie włączona.
W przypadku Recovery Codes wystarczy wygenerować i zapisać kody w bezpiecznym miejscu.
Samo wygenerowanie kodów i przypisanie ich do konta użytkownika - button Save codes to account - włączy tę metodę.
Własny plugin do uwierzytelniania
Moduł TFA daje możliwość dodawania własnych pluginów weryfikacji dwuetapowej. Sprowadza się to do stworzenia odpowiednich klas z metodami.
W jaki sposób jeszcze można weryfikować logującego się użytkownika? Można wysłać kodu SMS-em, mailem (służy do tego gotowy moduł Email TFA) lub na Slacku.
Cały zaprezentowany poniżej kod nie jest gotowym pluginem a jedynie opisem tego, z czego jest zbudowany.
Własny moduł łatwo jest odwzorować, bazując na kodzie z modułu ga_login. Polecam go przejrzeć i przeanalizować dla lepszego zrozumienia.
Przyjmijmy, że nasz moduł nazywa się tfa_code. Dwie główne klasy powinny znajdować się w katalogach.
Klasa TfaCodeValidation (nazwa dowolna)
tfa_code/src/Plugin/TfaValidation/TfaCodeValidation.php
Klasa TfaCodeSetup (nazwa dowolna)
tfa_code/src/Plugin/TfaValidation/TfaCodeSetup.php
Klasa TfaCodeSetup służy do obsługi procesu włączenia danej metody uwierzytelniania, a klasa TfaCodeValidation odpowiada za proces weryfikacji użytkownika podczas logowania poprzez wybraną metodę.
Klasa TfaCodeSetup i jej najważniejsze elementy
Adnotacja w komentarzu klasy zawiera informacje o tym, że jest to plugin TfaSetup oraz ma unikatowe id, które będzie wykorzystane w drugiej klasie.
/**
* Setup for 2FA by SENDING code.
*
* @TfaSetup(
* id = "tfa_code_setup",
* label = @Translation("TFA Code Setup"),
* description = @Translation("TFA Code Setup Plugin"),
* setupMessages = {
* "saved" = @Translation("code saved."),
* "skipped" = @Translation("code not saved.")
* }
* )
*/
class TfaCodeSetup extends TfaCodeValidation implements TfaSetupInterface {
Klasa dziedziczy po klasie walidacji oraz implementuje interfejs zawarty w module TFA.
Metoda
public function ready() {
Powinna zwracać TRUE jeżeli metoda weryfikacji może zostać włączona w danym kontekście. Kiedy natomiast może zwrócić FALSE? Przykładowo, gdy implementujesz wysyłanie kodów przy pomocy SMS, ale wcześniej wymagasz od użytkowników, aby w profilu potwierdzili swój numer telefonu. Gdy użytkownik nie potwierdzi wcześniej swojego numer telefonu, nie może włączyć tego sposobu uwierzytelniania. Metoda ready() powinna być wtedy napisana tak, aby w takim przypadku zwróciła FALSE.
Metoda
public function getOverview(array $params) {
Wyświetla informacje oraz linki związane z włączeniem metody uwierzytelniania.
Metoda
public function getSetupForm(array $form, FormStateInterface $form_state, $reset = 0) {
Znajduje się w niej definicja formularza włączenia danej metody. To tutaj muszą znaleźć się wymagania do włączenia pluginu, takie jak pole formularza do wpisania kodu, który przyjdzie do osoby, która chce włączyć tę metodę weryfikacji.
Przykład:
$form['get_code'] = [
'#type' => 'button',
'#value' => t('Get validation code),
'#ajax' => [
'callback' => [$this, 'get'],
'event' => 'click',
],
'#limit_validation_errors' => [],
'#prefix' => '<div id="tfa-validate-set-code">',
'#suffix' => '</div>',
];
Przycisk, który uruchamia funkcję get, zdefiniowaną w callbacku.
W funkcji get trzeba zaprogramować wysyłkę kodu do użytkownika np. poprzez email lub sms. Nazwa funkcji jest tutaj dowolna.
Pole do wpisania wysyłanego kodu
$form['tfa_container']['set_tfa_code'] = [
'#type' => 'textfield',
'#size' => 30,
'#placeholder' => t('Type validation code here'),
'#prefix' => '<div id="tfa-validate-set-code">',
'#suffix' => '</div>',
];
To czy kody są zgodne - ten wysłany z wpisanym - sprawdzane jest w metodzie
public function validateSetupForm(array $form, FormStateInterface $form_state) {
Jak wszystko poszło dobrze to metoda
public function submitSetupForm(array $form, FormStateInterface $form_state) {
powinna zwracać TRUE.
Klasa TfaCodeValidation i jej najważniejsze elementy
Adnotacja klasy jest analogiczna do tej z TfaCodeSetup.
/**
* Code validation class.
*
* @TfaValidation(
* id = "tfa_code_validation",
* label = @Translation("TFA Code validation"),
* description = @Translation("TFA Code Validation Plugin"),
* setupPluginId = "tfa_code_setup",
* )
*/
Metoda
public function ready() {
Wygląda analogicznie jak w poprzedniej klasie.
Metoda
public function getForm(array $form, FormStateInterface $form_state) {
To tutaj tworzony jest formularz dla danej metody, który widzi użytkownik podczas logowania i uwierzytelniania. Podobnie jak w poprzedniej klasie powinny się tu znaleźć pola do wysyłania i wpisania kodu. Kod weryfikowany jest w metodzie
public function validateForm(array $form, FormStateInterface $form_state) {
Na tym kończy się implementacja własnego pluginu do weryfikacji dwuetapowej. Jeszcze raz polecam przeanalizować kod z modułu ga_login, ponieważ na jego podstawie szybko stworzysz własny działający moduł.
Weryfikacja dwuetapowa w Drupalu - podsumowanie
Tym rozbudowanym wpisem chcieliśmy jak najlepiej wyjaśnić temat wdrożenia weryfikacji dwuetapowej dla strony opartej o Drupala. W obecnych czasach coraz więcej użytkowników internetu jest świadomych zagrożenia i utraty danych. Włączenie 2FA powoduje, że ich konta na stronach internetowych są bezpieczniejsze i trudniejsze do przechwycenia. Uwierzytelnianie dwuetapowe nie daje 100% pewności, ale na pewno znacznie podnosi bezpieczeństwo oraz poziom zaufania dla strony, na której wdrożona jest ta funkcjonalność. Nasz zespół wsparcia Drupala może Ci pomóc ją zaimplementować i przygotować więcej rad odnośnie bezpieczeństwa Twojej witryny.