Sobes.tech
Junior

Jak przebiega proces uwierzytelniania?

sobes.tech AI

Odpowiedź od AI

Proces uwierzytelniania użytkownika w aplikacji frontend składa się ogólnie z następujących kroków:

  1. Żądanie danych uwierzytelniających: Użytkownik wpisuje login i hasło w formularzu na stronie lub w aplikacji.
  2. Wysyłanie danych na serwer: Frontend wysyła te dane na serwer (backend) za pomocą żądania HTTP (zwykle POST) na specjalny punkt końcowy uwierzytelniania. Dane mogą być wysłane w ciele żądania w formacie JSON lub FormData.
  3. Weryfikacja danych na serwerze: Backend otrzymuje dane, sprawdza ich obecność w swojej bazie danych (np. czy login odpowiada istniejącemu użytkownikowi i czy hash wprowadzonego hasła zgadza się z hashem w bazie).
  4. Generowanie tokenu/sesji: Jeśli dane uwierzytelniające są poprawne, serwer generuje unikalny token uwierzytelniania. Może to być:
    • ID sesji: Serwer tworzy sesję i wiąże ją z użytkownikiem, wysyłając klientowi identyfikator sesji (np. w cookie z flagą HttpOnly).
    • Token (np. JWT): Serwer generuje token zawierający informacje o użytkowniku i jego uprawnieniach, podpisując go swoim kluczem tajnym. Token ten jest wysyłany do klienta.
  5. Wysyłanie tokenu/sesji do klienta: Serwer odpowiada frontendowi, wysyłając wygenerowany token uwierzytelniania.
    • Jeśli używany jest ID sesji, zwykle jest on przesyłany w nagłówku HTTP Set-Cookie.
    • Jeśli używany jest token, może być on przesłany w ciele odpowiedzi (JSON) lub w nagłówku Authorization (np. Bearer <token>).
  6. Przechowywanie tokenu na kliencie: Frontend otrzymuje token i przechowuje go do kolejnych żądań.
    • ID sesji jest przechowywany w przeglądarce w cookies (automatycznie).
    • Token może być przechowywany w localStorage, sessionStorage lub cookies (z flagą HttpOnly dla ochrony przed XSS). Zaleca się używanie HttpOnly cookies dla tokenów dostępu, co zmniejsza ryzyko kradzieży tokenu przez ataki XSS. Dla JWT można również przechowywać token odświeżania w HttpOnly cookies.
  7. Użycie tokenu do chronionych żądań: Przy wykonywaniu kolejnych żądań do chronionych zasobów (wymagających uwierzytelnienia), frontend wysyła zapisany token w każdym żądaniu.
    • Dla sesji przeglądarka automatycznie wysyła odpowiednie cookies z ID sesji.
    • Dla tokenów frontend musi jawnie dodawać token do nagłówka Authorization (np. Authorization: Bearer <token>).
  8. Weryfikacja tokenu na serwerze: Przy otrzymaniu każdego żądania do chronionego zasobu, serwer wyciąga token z żądania i sprawdza jego autentyczność (np. ważność tokenu, podpis tokenu, obecność sesji z takim ID).
  9. Autoryzacja: Jeśli token jest ważny, serwer identyfikuje użytkownika powiązanego z tym tokenem i sprawdza jego uprawnienia do żądanego zasobu (to już proces autoryzacji, po uwierzytelnieniu).
  10. Wykonanie żądania: Jeśli użytkownik jest uwierzytelniony i autoryzowany, serwer wykonuje żądanie i wysyła odpowiedź. W przeciwnym razie, serwer wysyła błąd (np. 401 Unauthorized lub 403 Forbidden).

Schematy uwierzytelniania są różne (na podstawie sesji, tokenów JWT, OAuth2, OpenID Connect itp.), ale podstawowe kroki uzyskania i użycia tokenu do identyfikacji użytkownika pozostają podobne.

Przykład wysyłania danych na serwer (z użyciem fetch API i tokenu):

// Przykład danych użytkownika
const userData = {
  username: 'user123',
  password: 'securepassword'
};

// Wysyłanie danych na serwer
fetch('/api/login', { // Punkt końcowy uwierzytelniania na serwerze
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(userData)
})
.then(response => {
  if (!response.ok) {
    throw new Error('Login failed');
  }
  return response.json(); // Oczekujemy, że serwer zwróci JSON z tokenem
})
.then(data => {
  const authToken = data.token; // Otrzymujemy token z odpowiedzi serwera
  localStorage.setItem('authToken', authToken); // Przechowujemy token (np. w localStorage)
  console.log('Login successful, token saved.');
  // Przekieruj użytkownika na chronioną stronę
})
.catch(error => {
  console.error('Authentication error:', error);
  // Wyświetl komunikat o błędzie użytkownikowi
});

// Przykład chronionego żądania z użyciem zapisanego tokenu
const token = localStorage.getItem('authToken');
if (token) {
  fetch('/api/protected-resource', {
    method: 'GET',
    headers: {
      'Authorization': `Bearer ${token}` // Dodaj token do nagłówka Authorization
    }
  })
  .then(response => {
    if (!response.ok) {
      if (response.status === 401) {
        console.log('Token wygasł lub jest nieprawidłowy. Przekierowanie do logowania.');
        // Token jest nieprawidłowy, usuń token i przekieruj do logowania
        localStorage.removeItem('authToken');
        // window.location.href = '/login'; // Przykład przekierowania
      }
      throw new Error('Nie udało się pobrać chronionego zasobu');
    }
    return response.json();
  })
  .then(data => {
    console.log('Dane chronione:', data);
  })
  .catch(error => {
    console.error('Błąd podczas pobierania chronionego zasobu:', error);
  });
} else {
  console.log('Nie znaleziono tokenu uwierzytelniającego. Przekierowanie do logowania.');
  // window.location.href = '/login'; // Przykład przekierowania
}

Ważne aspekty bezpieczeństwa:

  • Zawsze używaj HTTPS do wysyłania danych uwierzytelniających i tokenów, aby zapobiec przechwyceniu.
  • Przechowuj tokeny bezpiecznie (unikaj przechowywania poufnych informacji, takich jak hasła lub tokeny dostępu, bezpośrednio w kodzie lub publicznych polach).
  • Dla JWT: używaj krótkiego czasu ważności dla tokenów dostępu i odświeżaj je za pomocą tokenów odświeżania, które przechowujesz w HttpOnly cookies. Tokeny dostępu można przechowywać w pamięci aplikacji lub localStorage, ale trzeba uwzględnić ryzyko XSS.
  • Waliduj wszystkie dane na serwerze.