Uwierzytelnianie za pomocą tokenów JWT w WordPress REST API

This article explains a simple method for authenticating users using JWT tokens in a WordPress REST API. It provides an example code for verifying tokens and returning data, along with guidance on securing and handling user access.

Uwierzytelnianie za pomocą tokenów JWT w WordPress REST API

W tym artykule pokażemy, jak utworzyć dedykowany endpoint w WordPress REST API. W tym celu będziemy potrzebować biblioteki PHP, która pomoże nam generować i dekodować tokeny JWT. Bibliotekę znajdziesz tutaj: Firebase PHP-JWT.

Krok 1: Instalacja biblioteki

Pierwszym krokiem jest zainstalowanie biblioteki za pomocą Composera. Uruchom w swoim projekcie następujące polecenie:

composer require firebase/php-jwt

Jeśli nie wiesz, jak korzystać z Composera w swoim projekcie, zapoznaj się z tym szczegółowym poradnikiem

Krok 2: Tworzenie klasy dla dedykowanej przestrzeni nazw API

Po zainstalowaniu biblioteki utworzymy dedykowaną klasę, która posłuży do skonfigurowania nowej przestrzeni nazw dla naszego niestandardowego API.

Krok 3: Rejestrowanie przestrzeni nazw

Aby utworzyć nową przestrzeń nazw, musimy użyć hooka akcji rest_api_init:

add_action( 'rest_api_init', [ $this, 'register_new_rest_routes' ] );

Krok 4: Tworzenie funkcji do rejestrowania tras

Następnie utworzymy funkcję obsługującą, która doda nową przestrzeń nazw. Oto kompletny kod tej funkcji:

/**
 * Register route.
 *
 * @return void
 */
public function register_new_rest_routes(): void {
    register_rest_route(
       self::CUSTOM_API_NAMESPACE,
       '/auth',
       [
          'methods'             => WP_REST_Server::CREATABLE,
          'callback'            => [ $this, 'auth_callback' ],
          'permission_callback' => '__return_true',
          'args'                => [
             'email'    => [
                'type'              => 'string',
                'required'          => true,
                'format'            => 'email',
                'validate_callback' => function ( $param ) {
                   return filter_var( $param, FILTER_VALIDATE_EMAIL );
                },
             ],
             'password' => [
                'type'              => 'string',
                'required'          => true,
                'validate_callback' => function ( $param ) {
                   return filter_var( $param, FILTER_SANITIZE_FULL_SPECIAL_CHARS );
                },
             ],
          ],
       ]
    );

    register_rest_route(
       self::CUSTOM_API_NAMESPACE,
       '/get-posts',
       [
          'methods'             => WP_REST_Server::CREATABLE,
          'callback'            => [ $this, 'get_post_callback' ],
          'permission_callback' => '__return_true',

       ]
    );
}

Wyjaśnienie kodu

Funkcja register_rest_route() rejestruje nowe endpointy.

  • Trzeci parametr: Tablica argumentów:
  • self::CUSTOM_API_NAMESPACE: Dla uproszczenia nazwę przestrzeni nazw przechowuję w stałej.
  • Drugi parametr: Określa endpoint, w tym przypadku „auth”, który obsługuje uwierzytelnianie użytkownika i zwraca wygenerowany token.
[
   'methods'             => WP_REST_Server::CREATABLE,
   'callback'            => [ $this, 'auth_callback' ],
   'permission_callback' => '__return_true',
   'args'                => [
      'email'    => [
         'type'              => 'string',
         'required'          => true,
         'format'            => 'email',
         'validate_callback' => function ($param) {
            return filter_var($param, FILTER_VALIDATE_EMAIL);
         },
      ],
      'password' => [
         'type'              => 'string',
         'required'          => true,
         'validate_callback' => function ($param) {
            return filter_var($param, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
         },
      ],
   ],
]
  • methods: Specifies the HTTP method (GET, POST, PUT, PATCH, DELETE). It’s best practice to use built-in constants from the WP_REST_Server class:
WP_REST_Server::READABLE    // GET
WP_REST_Server::CREATABLE   // POST
WP_REST_Server::EDITABLE    // POST, PUT, PATCH
WP_REST_Server::DELETABLE   // DELETE
WP_REST_Server::ALLMETHODS  // GET, POST, PUT, PATCH, DELETE
  • callback: Funkcja, która przetwarza żądanie i zwraca dane użytkownikowi.
  • permission_callback: Funkcja, która sprawdza poziom dostępu użytkownika. W tym przypadku zawsze zwraca wartość true.
  • args: Tablica parametrów przekazywanych do API:
    • type: Typ danych (int, string, bool itp.). Zaleca się określenie typu.
    • required: Określa, czy parametr jest wymagany.
    • format: Dodatkowy format ciągu znaków (date-time, uri, email, ip, uuid, hex-color).
    • validate_callback: Funkcja służąca do walidacji danych wejściowych, często używana jako funkcja anonimowa.

Funkcja callback obsługująca uwierzytelnianie

Następnie tworzymy funkcję obsługującą auth_callback, która przyjmuje jeden parametr — instancję klasy WP_REST_Request zawierającą wszystkie przesłane dane.

Aby uzyskać dostęp do danych wejściowych, używamy funkcji get_json_params(), która zwraca wszystkie parametry w postaci tablicy.

Weryfikujemy adres e-mail, aby upewnić się, że użytkownik istnieje w bazie danych. Jeśli nie, zwracamy odpowiedź z błędem. Takie podejście, znane jako wczesny return (early return), zwiększa wydajność serwera.

Następnie tworzymy klucz dla naszego tokenu JWT, wykorzystując AUTH_KEY, jeśli jest zdefiniowany, lub własną stałą jako rozwiązanie awaryjne.

Na koniec generujemy token JWT za pomocą funkcji statycznej JWT::encode() dostępnej w bibliotece:

$jwt = JWT::encode(
   [
      'email'    => $params['email'],
      'password' => $params['password'],
   ],
   $key,
   'HS256'
);

Możesz zastosować dodatkowe środki bezpieczeństwa, takie jak przechowywanie tokenu w bazie danych lub dodatkowe szyfrowanie. Więcej informacji na temat korzystania z biblioteki znajdziesz tutaj: firebase/php-jwt.

Uwaga: Ten kod służy wyłącznie do celów edukacyjnych i nie jest zalecany do stosowania w projektach produkcyjnych bez wdrożenia dodatkowych środków bezpieczeństwa.

Pełna funkcja callback obsługująca uwierzytelnianie

/**
 * Auth callback.
 *
 * @param WP_REST_Request $request Params.
 *
 * @return WP_REST_Response
 */
public function auth_callback(WP_REST_Request $request): WP_REST_Response {

    $params = $request->get_json_params();

    if (!email_exists($params['email'])) {
       return new WP_REST_Response(
          [
             'error' => __('User does not exist', 'domain'),
          ],
          403
       );
    }

    $key = defined('AUTH_KEY') ? AUTH_KEY : self::CUSTOM_API_AUTH_KEY_SALT;

    $jwt = JWT::encode(
       [
          'email'    => $params['email'],
          'password' => $params['password'],
       ],
       $key,
       'HS256'
    );

    // ...Additional processing or database storage.

    return new WP_REST_Response(
       [
          'token' => $jwt,
       ],
       200
    );
}

Jeśli wszystko zostało wykonane poprawnie, powinniśmy otrzymać następującą odpowiedź:

Sending a request via postman

Przyjrzyjmy się teraz, jak możemy zweryfikować ten token i zwrócić dane, jeśli token jest prawidłowy. W tym celu zarejestrowałem kolejny endpoint o nazwie get-posts. Endpoint ten nie będzie przyjmował żadnych parametrów, ale sprawdzi obecność naszego tokenu i, jeśli token będzie prawidłowy, zwróci dane.

Krok po kroku przeanalizujmy funkcję obsługującą to żądanie. W pierwszej kolejności należy pobrać nagłówek autoryzacji zawierający przekazany token. W tym celu użyjemy standardowej funkcji klasy get_header(‘authorization’) z kluczem ‘authorization‘. Oto przykład żądania w Postmanie:

Korzystam z uwierzytelniania za pomocą tokenu Bearer, co oznacza, że nagłówek zwróci nie tylko nasz token, ale również ciąg Bearer TOKEN, dlatego musimy usunąć część „Bearer” oraz wszystkie dodatkowe spacje. W tym celu możemy użyć funkcji str_replace, w której po prostu zastąpimy pierwszą część pustym ciągiem, uzyskując właściwy token.

Do prawidłowego odszyfrowania tokenu potrzebujemy również soli, której użyliśmy podczas jego generowania.

Do odszyfrowania tokenu użyjemy funkcji statycznej JWT::decode. Pierwszym parametrem jest nasz token, natomiast drugi wymaga utworzenia nowej instancji klasy Key z biblioteki JWT. Przekazujemy dwa parametry: naszą sól oraz metodę używaną do dekodowania, która w moim przypadku to HS256.

Jeśli wszystko się zgadza, otrzymamy zdekodowany token wraz z zawartymi w nim parametrami. Następnie używam funkcji wp_signon, która służy do uwierzytelniania użytkownika na podstawie nazwy użytkownika/adresu e-mail oraz hasła. W przypadku nieudanego uwierzytelnienia zwróci ona instancję klasy WP_Error.

Kolejnym krokiem jest sprawdzenie odpowiedzi funkcji wp_signon. Jeśli zwróci ona błąd, natychmiast odrzucamy żądanie użytkownika dotyczące dostępu do danych.

Następnie należy napisać kod odpowiedzialny za Twoją logikę biznesową, upewniając się, że użytkownik istnieje w systemie. Przed zwróceniem jakichkolwiek danych z serwera warto również sprawdzić jego poziom dostępu. Ponieważ korzystamy z funkcji wp_signon, powinna ona zwrócić pełny obiekt WP_User, dzięki czemu będziemy mieć dostęp do wszystkich danych tej klasy.

Oto pełny kod tej funkcji:

/**
 * Get some data.
 *
 * @param WP_REST_Request $request Request.
 *
 * @return WP_REST_Response
 */
public function get_post_callback( WP_REST_Request $request ): WP_REST_Response {
    $header_token = $request->get_header( 'authorization' );
    $token        = str_replace( 'Bearer ', '', $header_token );
    $key          = defined( 'AUTH_KEY' ) ? AUTH_KEY : self::CUSTOM_API_AUT_KEY_SALT;

    $decode_token = JWT::decode( $token, new Key( $key, 'HS256' ) );

    $user = wp_signon(
       [
          'user_login'    => $decode_token->email,
          'user_password' => $decode_token->password,
       ],
       false
    );

    if ( is_wp_error( $user ) ) {
       return new WP_REST_Response(
          [
             'error' => __( 'Incorrect access token', 'domain' ),
          ],
          403
       );
    }

    // ... The code that your API returns.

    return new WP_REST_Response(
       [
          'error'    => null,
          'response' => [ 'data' => 'Some data' ],
       ],
       200
    );
}

W tym artykule omówiliśmy prostą metodę uwierzytelniania oraz wykorzystanie tokenów JWT w projekcie. Ten kod został przygotowany wyłącznie jako przykład i nie powinien być używany w działającym projekcie produkcyjnym.

Pełny kod tej klasy znajdziesz na moim GitHubie pod tym adresem: https://github.com/alex-l-iwpdev/test-theme/tree/REST-JWT

Podsumowanie

Integracja uwierzytelniania za pomocą tokenów JWT z WordPress REST API zapewnia bezpieczny i wydajny sposób zarządzania dostępem użytkowników oraz ochrony poufnych danych. Dzięki zastosowaniu odpowiedniej walidacji tokenów możesz zapewnić sprawny proces uwierzytelniania i zwiększyć ogólny poziom bezpieczeństwa API, co sprawia, że rozwiązanie to dobrze sprawdza się w nowoczesnych aplikacjach internetowych. Ponieważ bezpieczeństwo pozostaje jednym z najważniejszych aspektów, wykorzystanie JWT wraz z metodami takimi jak uwierzytelnianie za pomocą tokenu Bearer pozwala ograniczyć dostęp do zasobów wyłącznie do autoryzowanych użytkowników. Ma to kluczowe znaczenie w przypadku aplikacji przetwarzających dane użytkowników lub wymagających bezpiecznej komunikacji z API.

Gotowy, aby wynieść swój projekt
na wyższy poziom?

Wprowadźmy Twoją wizję w życie dzięki profesjonalnemu tworzeniu stron i dedykowanym rozwiązaniom.
Skontaktuj się z nami już teraz i rozpocznijmy pracę nad przekształceniem Twoich pomysłów w rzeczywistość!

    Powiązane wpisy

    Wskazówki i spostrzeżenia z mojej drogi zawodowej

    Jak korzystać z autoloadingu Composera w WordPressie

    Jak korzystać z autoloadingu Composera w WordPressie

    • 02.10.2026
    • 14
    Przeniesienie strony ze środowiska lokalnego na serwer za pomocą dostępu SSH

    Przeniesienie strony ze środowiska lokalnego na serwer za pomocą dostępu SSH

    • 02.10.2026
    • 13
    Dlaczego WordPress 5.5.3 z PHP 8 zwraca błąd 404 na każdej stronie witryny?

    Dlaczego WordPress 5.5.3 z PHP 8 zwraca błąd 404 na każdej stronie witryny?

    • 02.10.2026
    • 13
    Wszystkie wpisy