Аутентификация через Laravel Sanctum

Sanctum — это пакет для Laravel, легковесная альтернатива существующим методам аутентификации (например, Laravel Passport) для использования в SPA и простых API. Ранее пакет назывался Airlock.

Я часто использую Laravel для создания API моих приложений, так это с ней это получается быстро и без большого количества кода. Но создание аутентификацией в ней (на мой взгляд) всегда была утомительной задачей.

Поэтому неудивительно, что увидев твит Тейлора Отвелла о Laravel Sanctum я захотел попробовать его для аутентификации в простом мобильном приложении.

Я кратко расскажу вам, как установить Sanctum, но если у вас возникнут какие-либо проблемы, обратитесь к документации. После установки Sanctum и создания с его помощью простой системы аутентификации я покажу вам, как использовать ее в приложении для iOS. Предполагается, что у вас есть базовые знания Swift и я не буду углубляться в создание интерфейса, который я покажу на своих скриншотах.

Установка

Для тестирования я создам новый проект Laravel. Надеюсь, что вы знаете, как это сделать, а если нет, то для получения дополнительной информации обратитесь к документации Laravel. Зайдите в каталог проекта и выполните следующие команды в своем терминале:

composer require laravel/sanctum
php artisan vendor:publish
php artisan migrate

Теперь мы готовы погрузиться в проект и завершить настройку Sanctum.

В модели User используйте трейт HasApiTokens следующим образом:

use Laravel\Sanctum\HasApiTokens;
// Другие импорты опущены.
class User extends Authenticatable
{
    use HasApiTokens, Notifiable;    

    // Тело класса опущено.
}

Маршруты

Мы закончили настройку, теперь давайте создадим несколько маршрутов. Добавьте в ваш файл routes/api.php:

Route::prefix(‘sanctum’)->namespace(‘API’)->group(function() {
    Route::post(‘register’, ‘AuthController@register’);
    Route::post(‘token’, ‘AuthController@token’);
});

Пользователь будет использовать два этих маршрута для регистрации аккаунта и запроса токена (в основном, для входа в систему). Давайте создадим AuthController и напишем реализацию этих маршрутов. Запустите следующую строку в вашем терминале:

php artisan make:controller API\AuthController

Откройте только что созданный файл app/Http/Controllers/API/AuthController.php и добавьте функцию register:

public function register(Request $request)
{ 
    $validator = Validator::make($request->all(), [
        ‘name’ => [‘required’, ‘string’, ‘max:255’],
        ‘email’ => [‘required’, ‘string’, ‘email’, ‘max:255’, ‘unique:users’],
        ‘password’ => [‘required’, ‘string’, ‘min:8’],
        ‘device_name’ => [‘required’, ‘string’]
    ]); 
    // 1

    if ($validator->fails()) {
        return response()->json([‘error’ => $validator->errors()], 401);
    }
    // 2    
    
    $input = $request->all();
    $input[‘password’] = bcrypt($input[‘password’]);
    $user = User::create($input);
    // 3    
    
    $token = $user->createToken($request->device_name)->plainTextToken;
    // 4    
    
    return response()->json([‘token’ => $token], 200);
}

Вот пошаговое описание того, что делает этот код:

  1. Мы проверяем входящий запрос.
  2. Смотрим результат валидации. Если ошибка, то возвращаем ошибки в ответе.
  3. Хэшируем пароль и создаем нового пользователя.
  4. Создаем токен и сохраняем его, чтобы его можно было вернуть в ответе.

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

public function token(Request $request)
{
    $validator = Validator::make($request->all(), [
        ‘email’ => [‘required’, ‘string’, ‘email’, ‘max:255’],
        ‘password’ => [‘required’, ‘string’, ‘min:8’],
        ‘device_name’ => [‘required’, ‘string’]
    ]);    
    
    if ($validator->fails()) {
        return response()->json([‘error’ => $validator->errors()], 401);
    }
    // 1
 
    $user = User::where(‘email’, $request->email)->first();
    // 2
 
    if (!$user || !Hash::check($request->password, $user->password)) {
        return response()->json([‘error’ => ‘The provided credentials are incorrect.’], 401);
    }
    // 3
 
    return response()->json([‘token’ => $user->createToken($request->device_name)->plainTextToken]);
    // 4
}

Вот что делает этот код:

  1. Мы еще раз проверяем запрос и возвращаем ошибки, если валидация не удалась.
  2. Получаем первого User из нашей базы данных по указанному адресу электронной почты. Электронная почта уникальна, поэтому в лучшем случае нам вернёт одного пользователя.
  3. Если пользователь не существует (то есть адрес электронной почты был неправильным), или пароль не верен, то мы возвращаем ошибку, которую может подцепить наше приложение.
  4. Мы возвращаем сгенерированный токен.

Каркас нашей аутентификации готов! Давайте быстренько создадим маршрут, который позволит нам получить имя вошедшего в систему пользователя.

В файле routes/api.php добавьте следующий код:

Route::middleware(‘auth:sanctum’)->get(‘/name’, function (Request $request) {
    return response()->json([‘name’ => $request->user()->name]);
});

Здесь мы используем мидлвар auth:sanctum. Это позволит удостовериться, что в заголовках запроса присутствует api-токен, и вернет ошибку, если его нет. Если запрос работает, то мы можем использовать $request->user() для получения доступа к пользовательской модели.

Я бы хотел много чего еще написать о том, что можно легко сделать с Sanctum, но воздержусь, чтобы иначе статья будет чрезмерно большой. Если вы хотите больше узнать о возможностях, например, добавление /возможностей/ и отзыв маркеров, обратитесь к документации.

Аутентификация

Laravel Sanctum Аутентификация

Пришло время протестировать наш API. Откроем Xcode и, на скорую руку, экран входа. После выполнения любой проверки на стороне клиента, которую вы захотите выполнить, передайте значения из полей форме регистрации в функцию, которую вы будете использовать для выполнения HTTP-запроса. Чтобы предоставить код, который можно использовать независимо от предпочитаемой вами архитектуры, я просто покажу вам, как простроить запрос для регистрацию пользователя. Убедитесь, что включили Content-Type заголовок application/json, иначе ваши запросы не будут выполнены.

var request = URLRequest(url: URL(string: “http://yourprojecturl.test/api/sanctum/register")!)
request.httpMethod = “POST”
request.addValue(“application/json”, forHTTPHeaderField: “Content-Type”)
guard let body = try? jsonEncoder.encode([
    “name”: name,
    “password”: password,
    “email”: email,
    “device_name”: deviceName
]) else {
    return
}

Laravel Sanctum Аутентификация

Запрос на вход в систему очень похож, мы просто заменяем конечную конечную точку URL на /token и удаляем name из тела. Успешный запрос к любой из этих конечных точек приведет к следующему телу ответа:

{
 “token”: “<api token>”
}

После того, как ваш пользователь зарегистрирует свою учетную запись или войдет в систему, обязательно сохраните где-нибудь этот токен. Мы будем использовать его в следующем запросе, чтобы получить имя c бэкэнда:

var request = URLRequest(url: URL(string: “http://yourprojecturl.test/api/name"))
request.httpMethod = “GET” 
request.addValue(“Bearer \(apiToken)”, forHTTPHeaderField: “Authorization”)

Краткий обзор

Давайте вкратце рассмотрим то, что я объяснил в этой статье:

  • Мы настроили каркас Laravel и Sanctum для обработки аутентификации пользователей.
  • Мы можем создавать маршруты, используя мидлвар auth:sanctum, которое будет проверять токен, отправленный в заголовках, и давать нам доступ к соответствующей пользовательской модели.
  • Мы можем создавать запросы на использование нашего API.

Следующие шаги

Как я упоминал ранее, это лишь поверхностно рассматривает то, что можно сделать с Sanctum. Вы можете создавать токены с различными способностями, чтобы одни пользователи могли выполнять действия, а другие — нет. Или вы можете устанавливать срок годности токена и пользователю придется запрашивать новый. Sanctum все еще находится в бета-версии, поэтому возможно, что всё изменится и будут добавлены новые функции.

Надеюсь, эта статья дала вам некоторое представление о том, как Sanctum может быть простой альтернативой другим методам авторизации. Если вы разработчик мобильных приложений и никогда раньше не работали с Laravel, то я настоятельно рекомендую вам потратить на него немного времени. Вы сможете создать бэкэнд для своих приложений в кратчайшие сроки.

Автор: Jille van der Weerd
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.