Як використовувати аутентифікацію токена доступу

Дата оновлення перекладу 2022-12-22

Як використовувати аутентифікацію токена доступу

Токени доступу або токени API часто використовуються як механізм аутентифікації у контекстах API. Токен доступу - це рядок, отриманий під час аутентифікації (використовуючи додаток або сервер авторизації). Роль токена доступу полягає у верифікації особистості користувача, щоб отримати згоду перед випуском токена.

Токени доступу можуть бути будь-якого типу, наприклад, непрозорими рядками, веб-токенами JSON (JWT) або SAML2 (XML-структурами). Будь ласка, перегляньте RFC6750: Фреймворк авторизації OAuth 2.0: використання токенів предʼявника, щоб побачити детальну специфікацію.

Використання аутентифікатора токена доступу

Це керівництво припускає, що ви налаштували безпеку та створили обʼєкт користувача у вашому додатку. Дотримуйтесь основного керівництва безпеки, якщо це ще не так.

1) Сконфігуруйте аутентифікатор токена доступу

Щоб використати аутентифікатор токена доступу, ви маєте сконфігурувати token_handler. Обробник токена отримує токен із запиту та повертає правильний ідентифікатор користувача. Щоб отримати ідентифікатор користувача, реалізаціям може бути потрібно завантажити та валідувати токен (наприклад, відкликання, термін дії, цифровий підпис тощо).

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler

Цей обробник має реалізувати AccessTokenHandlerInterface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// src/Security/AccessTokenHandler.php
namespace App\Security;

use App\Repository\AccessTokenRepository;
use Symfony\Component\Security\Http\AccessToken\AccessTokenHandlerInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;

class AccessTokenHandler implements AccessTokenHandlerInterface
{
    public function __construct(
        private AccessTokenRepository $repository
    ) {
    }

    public function getUserBadgeFrom(string $accessToken): UserBadge
    {
        // наприклад, запит до бази даних "access token", щоб шукати цей токен
        $accessToken = $this->repository->findOneByValue($token);
        if (null === $accessToken || !$accessToken->isValid()) {
            throw new BadCredentialsException('Invalid credentials.');
        }

        // та повернути обʼєкт UserBadge, що містить ідентифікатор користувача із знайденого токена
        return new UserBadge($accessToken->getUserId());
    }
}

Аутентифікатор токена дотупу використає повернутий ідентифікатор користувача, щоб завантажити користувача, використовуючи постачальника користувачів .

Caution

Важливо перевірити, чи є токен валідним. Наприклад, приклад вище, верифікує, чи у токена не завершився строк дії. З автономними токенами доступу, такими як JWT, обробник зобовʼязаний верифікувати цифровий підпис та зрозуміти усі заяви, ообливо sub, iat, nbf та exp.

2) Сконфігуруйте екстрактор токена (опціонально)

Тепер додаток готвий до обробки вхідних токенів. Екстрактор токена вилучає токен із запиту (наприклад, заголовку або тіла запиту).

За замовчуванням, токен доступу читається з параметра заголовку запиту Authorization зі схемою Bearer (наприклад, Authorization: Bearer the-token-value).

Symfony надає інші екстрактори, як описано в RFC6750:

header (за замовчуванням)
Токен відправляється через загловок запиту. Зазвичай Authorization зі схемою Bearer.
query_string
Токен є частиною рядку запиту. Зазвичай access_token.
request_body
Токен є частиною тіла запиту під час запиту POST. Зазвичай access_token.

Caution

Через слабкість безпеки, повʼязану з методом URI, включно з високою ймовірністю, що URL тіла запиту, яке містить токен доступу, буде логовано, методи query_string і request_body НЕ ПОВИННІ бути використані, окрім випадків, коли неможливо перенести токен доступу у поле заголовку запиту.

Ви також можете створити користувацький екстрактор. Клас має реалізовувати AccessTokenExtractorInterface.

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
10
11
12
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler

                # використати інший вбудований екстрактор
                token_extractors: request_body

                # або надати ID сервісу користувацького екстрактора
                token_extractors: 'App\Security\CustomTokenExtractor'

Можливо встановити декілька екстракторів. У такому випадку, порядок має значення: перший у списку буде викликано першим.

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
8
9
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler
                token_extractors:
                    - 'header'
                    - 'App\Security\CustomTokenExtractor'

3) Надішліть запит

Це все! Ваш додаток тепер може аутентифікувати вхідні запити, використовуючи токен API.

Використовуючи екстрактор заголовку за замовчуванням, ви можете протестувати функцію, надіславши запит таким чином:

1
2
$ curl -H 'Authorization: Bearer an-accepted-token-value' \
    https://localhost:8000/api/some-route

Налаштування обробника успіху

За замовчуванням, запит продовжується (наприклад, запускається контролер для маршруту). Якщо ви хочете налаштувати обробку успіху, створіть ваш власний обробник успіху, шляхом створення клау, який реалізує AuthenticationSuccessHandlerInterface, та сконфігуруйте сервіс ID як success_handler:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
7
# config/packages/security.yaml
security:
    firewalls:
        main:
            access_token:
                token_handler: App\Security\AccessTokenHandler
                success_handler: App\Security\Authentication\AuthenticationSuccessHandler

Tip

Якщо ви хочете налаштувати обробку невдачі за замовчуванням, використайте опцію failure_handler та створіть клас, який реалізує AuthenticationFailureHandlerInterface.