Laravel – React Native: Sanctum получает 302 редиректы на главную страницу

Вопрос или проблема

У меня есть бэкенд на Laravel и фронтенд на React Native. Я хочу защитить API маршруты, к которым обращается мое приложение React Native с помощью Axios, для этого я установил Laravel Sanctum.

Мой текущий рабочий процесс: я логинюсь или регистрирую пользователя с помощью электронной почты и пароля, получаю токен Sanctum, который храню с помощью AsyncStorage в своем приложении, затем отправляю этот токен в заголовках всех своих вызовов Axios, используя перехватчики.

ПРОБЛЕМА:

Маршруты, защищенные middleware auth:sanctum, получают 302 Found, а затем перенаправляются на главную страницу / 200 OK.

Как я создаю токен на бэкенде:

$token = $user->createToken($request['device_name'])->plainTextToken;

Как я добавляю свой Bearer токен в заголовки (я проверяю, что они прикреплены через консольный лог):

if (token) 
{
    console.log('SANCTUM: Добавление bearer токена в axios: ' + token);
    axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
}

Как я защищаю свои маршруты:

Route::get('/auth/sanctum/user', 'App\Http\Controllers\Api\AuthController@sanctumUser')->middleware('auth:sanctum');

В моем middleware RedirectIfAuthenticated я пытался изменить его после чтения некоторых других постов, но любые изменения, которые я сделал, не дали никакого результата…

<?php

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Обработка входящего запроса.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  ...$guards
     * @return mixed
     */

    //Добавил часть && !$request->wantsJson()

    public function handle($request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;

        foreach ($guards as $guard) 
        {
//Добавил !$request->wantsJson()            
if (Auth::guard($guard)->check()  && !$request->wantsJson() ) 
            {
//Пытался изменить это тоже                
return redirect(RouteServiceProvider::HOME);
            }
        }

        return $next($request);
    }
}

В моем Kernel http:

protected $middlewareGroups = [
        'web' => [
            //\App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            //\Illuminate\Session\Middleware\StartSession::class,
            //\Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            //EnsureFrontendRequestsAreStateful::class,
            \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

    ];

Файл sanctum.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Состояние доменов
    |--------------------------------------------------------------------------
    |
    | Запросы из следующих доменов / хостов будут получать куки
    | аутентификации API с состоянием. Как правило, это должны быть ваши локальные
    | и рабочие домены, которые получают доступ к вашему API через фронтенд SPA.
    |
    */

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1,127.0.0.1:8000,::1')),

    /*
    |--------------------------------------------------------------------------
    | Время истечения
    |--------------------------------------------------------------------------
    |
    | Это значение контролирует количество минут, в течение которых выданный токен будет
    | считаться просроченным. Если это значение равно null, токены доступа
    | не истекают. Это не изменит срок действия сеансов для первых сторон.
    |
    */

    'expiration' => null,

    /*
    |--------------------------------------------------------------------------
    | Middleware Sanctum
    |--------------------------------------------------------------------------
    |
    | При аутентификации вашего SPA от первой стороны с помощью Sanctum вам может понадобиться
    | настроить некоторые из middleware, которые использует Sanctum при обработке запроса.
    | Вы можете изменить перечисленный ниже middleware по мере необходимости.
    |
    */

    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],

];

Файл auth.php:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Настройки аутентификации по умолчанию
    |--------------------------------------------------------------------------
    |
    | Эта опция контролирует "охрану" аутентификации по умолчанию и параметры сброса пароля
    | для вашего приложения. Вы можете изменить эти параметры
    | по мере необходимости, но это хорошее начало для большинства приложений.
    |
    */

    'defaults' => [
        'guard' => 'web',
        'passwords' => 'users',
    ],

    /*
    |--------------------------------------------------------------------------
    | Охраны аутентификации
    |--------------------------------------------------------------------------
    |
    | Далее вы можете определить каждую охрану аутентификации для вашего приложения.
    | Конечно, для вас здесь определена отличная базовая конфигурация,
    | которая использует хранилище сеансов и провайдер пользователей Eloquent.
    |
    | У всех драйверов аутентификации есть провайдер пользователей. Это определяет, как
    | пользователи фактически извлекаются из вашей базы данных или других методов хранения,
    | используемых этим приложением для сохранения данных ваших пользователей.
    |
    | Поддерживаемые: "session", "token"
    |
    */

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Провайдеры пользователей
    |--------------------------------------------------------------------------
    |
    | У всех драйверов аутентификации есть провайдер пользователей. Это определяет, как
    | пользователи фактически извлекаются из вашей базы данных или других методов хранения,
    | используемых этим приложением для сохранения данных ваших пользователей.
    |
    | Если у вас есть несколько таблиц или моделей пользователей, вы можете настроить несколько
    | источников, которые представляют каждую модель / таблицу. Эти источники затем могут
    | быть назначены к любым дополнительным охранам аутентификации, которые вы определили.
    |
    | Поддерживаемые: "database", "eloquent"
    |
    */

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Сброс паролей
    |--------------------------------------------------------------------------
    |
    | Вы можете указать несколько конфигураций сброса паролей, если у вас есть более одной
    | таблицы или модели пользователей в приложении, и вы хотите, чтобы у вас были
    | отдельные настройки сброса паролей в зависимости от конкретных типов пользователей.
    |
    | Время истечения — это количество минут, в течение которых токен сброса должен считаться
    | действительным. Эта функция безопасности поддерживает токены короткоживущими, чтобы
    | у них было меньше времени для угадывания. Вы можете изменить это по мере необходимости.
    |
    */

    'passwords' => [
        'users' => [
            'provider' => 'users',
            'table' => 'password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
    ],

    /*
    |--------------------------------------------------------------------------
    | Время ожидания подтверждения пароля
    |--------------------------------------------------------------------------
    |
    | Здесь вы можете определить количество секунд, прежде чем подтверждение пароля
    | истечет, и пользователю будет предложено ввести свой пароль повторно через
    | экран подтверждения. По умолчанию тайм-аут составляет три часа.
    |
    */

    'password_timeout' => 10800,

];

Ответ или решение

Чтобы решить проблему с получением 302 редиректов на главную страницу в вашем приложении Laravel и React Native при использовании Sanctum для защиты API маршрутов, давайте разберем возможные причины и решения:

1. Проблема с конфигурацией Sanctum

Убедитесь, что ваш файл конфигурации sanctum.php правильно настроен для работы с React Native. В частности, убедитесь, что SANCTUM_STATEFUL_DOMAINS в вашем .env файле настроен правильно. Этот параметр должен включать адрес вашего React Native приложения, особенно если вы используете эмулятор (например, localhost или IP-адрес вашего компьютера). Пример обновления:

SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1,192.168.0.100

Замените 192.168.0.100 на IP-адрес вашего компьютера, если ваше приложение подключается через локальную сеть.

2. Проблемы с CORS

Убедитесь, что у вас настроены правильные заголовки CORS. Проверьте файл cors.php, который находится в config. Например, добавьте ваш фронтенд домен:

'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:3000', 'http://192.168.0.100:3000'],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,

3. Проблемы с маршрутизацией

Проверьте, правильно ли вы защищаете маршруты. Например, убедитесь, что маршрут, который вы используете (/auth/sanctum/user), а также контроллер AuthController, работают как ожидалось и возвращают корректную информацию о пользователе, когда аутентификация прошла успешно.

4. Проверьте настройки Middleware

Убедитесь, что EnsureFrontendRequestsAreStateful добавлен в вашу группу middleware API. Это позволит Sanctum обрабатывать запросы от вашего React Native приложения корректно.

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

5. Использование token

Убедитесь, что вы правильно добавляете токен в заголовки вашего Axios. Вот пример кода для установки токена:

if (token) {
    console.log('SANCTUM: Adding bearer token to axios: ' + token);
    axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
}

Также проверьте, что ваш токен действительно сохраняется и используется на всех запросах.

6. Проверка ошибок на сервере

Используйте инструменты для отладки (например, dd() в Laravel) в контроллере, чтобы проверить, поступают ли запросы с правильными заголовками и токенами. Это поможет вам определить, правильно ли обрабатываются запросы на стороне сервера.

7. Проверка состояния сессий

Если вы продолжаете сталкиваться с проблемами, попробуйте отключить куки и сессии в вашем приложении React Native, так как это может вызвать дополнительные сложности при работе с Sanctum.

Заключение

Перепроверив все эти настройки один за другим, вы должны быть в состоянии выявить причину 302 редиректов на вашу домашнюю страницу. Убедитесь, что вы перезапустили сервер после изменения любых конфигураций, и тестируйте с обновленной версией вашего приложения.

Оцените материал
Добавить комментарий

Капча загружается...