Аутентификация OAuth2 и токены JWT

После формы регистрации осталось добавить вход в кабинет и восстановление пароля. Для этого перед программированием нам нужно определиться, как мы будем осуществлять аутентификацию в приложении из JS-фронтенда и API.

Как раз сегодня рассмотрим практики аутентификации по токенам при работе с API и сравним классические подходы с использованием токенов в формате JWT.

И на слайдах смоделируем по шагам процесс получения и обновления токенов по универсальной спецификации OAuth2, чтобы с нашим API могли работать сторонние клиенты:

  • 00:02:39 - Basic Authentication
  • 00:04:40 - Использование токенов
  • 00:06:59 - Токены в распределённых системах
  • 00:08:28 - Хранение данных в токене
  • 00:11:06 - Инвалидация токена
  • 00:12:34 - Механизм обновления
  • 00:15:07 - JSON Web Token
  • 00:18:22 - Пакет lcobucci/jwt
  • 00:19:30 - Процесс аутентификации
  • 00:20:03 - Вход через сторонние сервисы
  • 00:24:07 - Использование одноразового кода
  • 00:25:59 - Спецификация OAuth 2
  • 00:28:04 - Доступ к разделам
  • 00:30:36 - Модерация клиентов
  • 00:35:33 - Refresh Token Grant
  • 00:36:25 - Дополнение PKCE

И в следующих эпизодах реализуем весь процесс аутентификации на бэкенде и фронтенде.

Скрытый контент
Комментарии (9)
Максим

Спасибо))) Совсем скоро пойдёт домен! Ура)

Ответить
Руслан

Спасибо!

Ответить
Руслан

Дмитрий, извините за оффтоп, можете, пожалуйста, порекомендовать какой пакет лучше использовать для имплементации OAuth с PKCE в Laravel, для SPA с раздельным API приложением? Спасибо за Ваш труд!

Ответить
Дмитрий Елисеев

Для этого как раз есть Laravel Passport

Ответить
Руслан

Спасибо!

Ответить
Arunas

Спасибо. :)

Ответить
Максим

Дмитрий, подскажите, пожалуйста, почему в Value Object Id для генерации ID мы используем фабричный метод generate() вместо того, чтобы вынести это в сервис IdentifierGenerator и в нем метод `generate()’.

Тогда бы мы подключали этот генератор в командах и использовали бы примерно так:

$id = new Id($this->identifier->generate());

Это бы позволило вынести генерацию Id в отдельный сервис. Отдельно тестировать его и не давать VO больше отвественности, чем ему нужно...

Ответить
Дмитрий Елисеев

Да, можно при желании.

Имеет смысл переносить генерацию в репозиторий при использовании инкрементных идентификаторов, когда мы можем поместить туда доставание следующего номера из секвенции:

class UserRepository
{
    ...

    public function nextId(): Id
    {
        return new Id(
            (int)$this->connection->query('SELECT nextval(\'users_seq\')')->fetchColumn()
        );
    }
}

чтобы потом вызывать этот метод:

$id = $this->users->nextId();

Выносить в IdentifierGenerator имеет смысл если мы пишем юнит-тесты к хэндлерам команд и там хотим подменять этот генератор, чтобы он возвращал фиксированное значение.

Но как альтернативу этому можно генерировать значение прямо в контроллере и его передавать в команду в поле $id:

class Command {
    public string $id;
    public string $email;
    public string $password;
}

и потом брать его в хэндлере из команды:

$id = new Id($command->id);

Тогда $this->identifier->generate() или Uuid::uuid4()->toString() потребуется вызывать только в контроллере. Такой подход актуален если нам прямо из контроллера нужно будет сразу вернуть идентификатор. И в том случае, если команды у нас выполняются асинхронно.

Ответить
Максим

Да, я именно пришёл к тому, чтобы генерацию ID использовать даже не в командах, а контроллере. Иногда даже требуется генерировать ID на JS и передавать его в API. В любом случае спасибо за развёрнутый ответ)

А по поводу выноса в репозиторий - да. Видел у вас это. Однако, когда у нас есть отдельный сервис генерации ID мы можем реализацию метода generate() заменять как угодно. Если нужно - подключили в этот сервис репозиторий и запросили nextId(). Если не нужно сгенерируем Id Uuid::uuid4()->toString()

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий

Или войти через:

Google
GitHub
Yandex
MailRu