.

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

Wykonywanie komendy w shell w Composerze

 

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 

Włączanie modułów takich jak Two-factor Authentication (TFA) w Drupalu

 

Proces logowania po instalacji modułu Two-factor Authentication (TFA)

  1. Użytkownik wpisuje swoje dane logowania (login i hasło) w formularzu i zatwierdza.
  2. Jeżeli dane są poprawne, Drupal tworzy sesję użytkownika, którego identyfikuje jako uwierzytelniony.
  3. Moduł TFA implementuje hook_user_login.
  4. TFA sprawdza, czy zalogowany użytkownik powinien użyć drugiej metody weryfikacji. Jeżeli tak - następuje wylogowanie i przekierowanie na drugą metodę weryfikacji.
  5. Następuje proces weryfikacji np. poprzez wpisanie kodu z wiadomości SMS.
  6. 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

Dodawanie nowego klucza w ustawieniach modułu Key

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.
Przykładowa struktura katalogów z miejscem, w którym trzymane są klucze

 

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ą.

Dodawanie metody szyfrowania dla modułu Drupala Encrypt

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.

Wybieranie ról, dla których będzie wymagane uwierzytelnianie dwuskładnikowe

 

Pluginy do uwierzytelniania dwuetapowego

Po zainstalowaniu wyżej wymienionych modułów mamy trzy pluginy do wyboru. Dwa z nich bazują na aplikacji Google Authenticator.

Pluginy do uwierztelniania dostępne w TFA Settings
  • 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.

Komunikat, który pojawia się po pominięciu włączenia dwuetapowego uwierzytelniania po raz trzeci

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.

Konfigurowanie metody  uwierzytelniania dwuetapowego w Drupalu

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.

Kod QR wygenerowany w Drupalu, który musimy zeskanować w wybranej aplikacji mobilnej

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.

Kod uwierzytelniający do logowania do strony w Drupalu, wygenerowany w aplikacji Google Authenticator

W przypadku Recovery Codes wystarczy wygenerować i zapisać kody w bezpiecznym miejscu.

Generowanie kodów odzyskiwania do uwierzytelniania dwuskładnikowego

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.