RFC 7591, 7592 и 8414

Аудитория

Эта статья предназначена для разработчиков, хорошо разбирающихся в OAuth2.0. Рекомендуется читать мои предыдущие статьи, собранные в список здесь. Вам также потребуется понимание HTTP.

В других статьях мы рассмотрели процессы, посредством которых клиент обращается к серверу авторизации и запрашивает токены. Однако как клиент узнает, где находится этот сервер, где находятся конечные точки и какие данные отправлять (помимо того, что определено в RFC)?

Кроме того, чтобы использовать сервер авторизации, нам необходимо предоставить некоторую исходную информацию о нашем клиенте (хорошим примером являются URI перенаправления). как нам это сделать?

В рамках статьи мы ответим на все вышеперечисленное. Обратите внимание, что это ускоренный курс, поэтому он не будет содержать исчерпывающих деталей. Для полной картины обратитесь к оригинальным RFC: 7591, 7592 и 8414.

Аргумент

Метаданные сервера авторизации

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

Подмножество метаданных, которые мы можем получить, приведено ниже, полный список можно найти здесь.

  • issuer: идентификатор эмитента сервера авторизации в виде https URL-адреса. Это один из способов определить, с какого сервера авторизации пришел токен.
  • authorization_endpoint и token_endpoint: полные URL-адреса конечных точек авторизации и токенов, как определено в базовой спецификации OAuth2.0.
  • jwks_uri: документ JWK Set, содержащий ключи, которые клиент может использовать для проверки информации, поступающей с сервера авторизации, и при необходимости использовать для шифрования сообщений, поступающих на сервер.
  • registration_endpoint: Конечная точка, которую клиент использует для регистрации на сервере OAuth2.0 — мы скоро рассмотрим это!
  • scopes_supported: Все различные области, которые может запросить наш клиент, запрашивая авторизацию у владельца ресурса.
  • grant_types_supported: список всех различных типов грантов, поддерживаемых сервером авторизации (код авторизации, неявный и т. д.).
  • revocation_endpoint: Конечная точка, где мы отзываем токены.
  • introspection_endpoint: Конечная точка, где мы анализируем токены.
  • code_challenge_methods_supported: Список вызовов кода PKCE.
  • signed_metadata: Подписанный JWT, содержащий все вышеперечисленное, на случай, если клиенты захотят его проверить.

Теперь мы знаем, какие данные могут нас заинтересовать, как их получить? Сервер авторизации должен предоставить документ JSON, содержащий его, обычно по пути .well-known/oauth-authorization-server. Для этого нам нужно знать базовый URL-адрес сервера авторизации, но, кроме этого, мы готовы к работе!

Для демонстрации воспользуемся Сервером авторизации Spotify. Базовый URL-адрес

https://accounts.spotify.com

Весь URL-адрес

https://accounts.spotify.com/.well-known/oauth-authorization-server

Ответ ниже!

{
    "authorization_endpoint": "https://accounts.spotify.com/authorize",
    "device_authorization_endpoint": "https://accounts.spotify.com/oauth2/device/authorize",
    "grant_types_supported": [
        "authorization_code",
        "client_credentials",
        "password",
        "urn:ietf:params:oauth:grant-type:jwt-bearer",
        "implicit",
        "refresh_token"
    ],
    "issuer": "https://accounts.spotify.com",
    "response_type_supported": [
        "token",
        "code"
    ],
    "revocation_endpoint": "https://accounts.spotify.com/oauth2/revoke/v1",
    "revocation_endpoint_auth_methods_supported": [
        "client_secret_basic",
        "client_secret_post"
    ],
    "token_endpoint": "https://accounts.spotify.com/api/token",
    "token_endpoint_auth_methods_supported": [
        "none",
        "client_secret_basic",
        "client_secret_post"
    ],
    "ui_locales_supported": [
        "af-ZA",
        "am-ET",
        "ar",
        "az-AZ",
        "bg-BG",
        "bn-IN",
        "bp",
        "cs",
        "da-DK",
        "de",
        "el",
        "en",
        "es",
        "es-ES",
        "et-EE",
        "fa-IR",
        "fi",
        "tl",
        "fr",
        "fr-CA",
        "gu-IN",
        "he-IL",
        "hi-IN",
        "hr-HR",
        "hu",
        "id",
        "is-IS",
        "it",
        "ja",
        "kn-IN",
        "ko",
        "lv-LV",
        "lt-LT",
        "ml-IN",
        "mr-IN",
        "ms",
        "nb-NO",
        "ne-NP",
        "nl",
        "or-IN",
        "pa-IN",
        "pa-PK",
        "pl",
        "pt-BR",
        "pt-PT",
        "ro-RO",
        "ru",
        "sk-SK",
        "sl-SI",
        "sr-RS",
        "sv",
        "sw",
        "ta-IN",
        "te-IN",
        "th-TH",
        "tr",
        "uk-UA",
        "ur",
        "vi-VN",
        "zh-CN",
        "zh-TW",
        "zu-ZA"
    ]
}

Динамическая регистрация клиентов

Вышеизложенное позволяет нам узнать всю необходимую клиенту информацию о нашем сервере авторизации. Однако как наш сервер авторизации узнает о нашем клиенте?

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

Есть два связанных RFC, касающихся разных частей проблемы:

  • RFC 7591: Протокол динамической регистрации клиентов, первичная регистрация клиентов
  • RFC 7592: протокол управления динамической регистрацией клиентов, обновление информации о клиенте

Давайте рассмотрим их по одному, начиная с 7591.

Как мы видим из вышеизложенного, основной поток довольно минимален. Начнем с двух необязательных шагов.

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

Второй выдает необязательное программное заявление. Это подписанный JWT, утверждающий некоторые метаданные о клиенте. Это может быть предоставлено клиенту или разработчику на этом этапе, или оно может быть сгенерировано непосредственно ими.

Этот токен JWT будет содержать утверждение iss, обозначающее, кто подписал токен. Это является частью процесса, когда сервер авторизации решает, разрешат ли они клиенту зарегистрироваться. Например, если токен подписан эмитентом, которому доверяет сервер авторизации, и это можно проверить, то, скорее всего, регистрация будет принята.

Пример такого заявления ниже.

{
  "software_id": "1234",
  "client_name": "Example Client",
  "client_uri": "https://www.example.com/"
}

Обратите внимание: нам не нужно заявление о программном обеспечении для динамической регистрации клиентов. Это совершенно необязательно.

Теперь мы переходим к основной части вопроса, запросу регистрации клиента и ответу регистрации клиента.

У нас есть некоторая информация о нашем клиенте, которую мы хотим передать на сервер авторизации. Мы приводим сокращенный список ниже:

  • redirect_uris: Для тех из вас, кто понимает OAuth2.0, вы знаете, что серверу авторизации нужен список URI перенаправления, чтобы отправить кого-то обратно, когда он будет авторизован. Вот как клиент может их предоставить.
  • grant_types: список всех типов грантов, поддерживаемых клиентом.
  • client_name: Имя клиента
  • jwks_uri: URL-адрес набора веб-ключей JSON клиента, содержащего его открытые ключи.
  • software_statement: Дополнительный оператор программного обеспечения, который мы обсуждали выше.

И так далее. Полный список находится здесь для ознакомления.

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

POST /register HTTP/1.1
     Content-Type: application/json
     Accept: application/json
     Host: www.example.com

     {
      "redirect_uris": [
        "https://www.example.com/one",
        "https://www.example.com/two"],
      "client_name": "Example Client",
     }

Затем ответ JSON 201 содержит информацию, необходимую для использования клиента, в том числе:

  • client_id: Идентификатор, который клиент должен будет отправить с запросами авторизации.
  • client_secret: Секрет клиента, если он требуется.
  • client_id_issued_at: Необязательно, когда был выдан идентификатор клиента.
  • client_secret_expires_at: требуется по истечении срока действия секрета клиента (используется в сочетании с указанным выше). Однако это может быть нулем, если срок его действия никогда не истекает.

Есть ответы об ошибках, но мы не будем вдаваться в них здесь. Их можно найти в этом разделе RFC.

Хорошо, теперь мы можем создать клиент, как нам его обновить? Представьте, что мы хотим обновить список URI перенаправления, которые мы можем использовать. Как это происходит? Введите RFC 7592.

Мы ввели три новых типа запроса/ответа: чтение, обновление и удаление. На этом операции CRUD для клиентов завершены!

В ответ на существующую регистрацию клиента также внесены некоторые изменения.

Сначала мы возвращаем конечную точку конфигурации клиента (часть registration_client_uri ответа JSON). После того, как мы зарегистрировались, мы можем использовать это для отправки наших запросов на чтение/обновление/удаление. Кроме того, мы можем вернуть новый токен доступа (по адресу registration_access_token), используемый для последующих запросов к нашим новым конечным точкам.

клиентский запрос на чтение — это GET-запрос к registration_client_uri с токеном доступа к регистрации.

Запрос на обновление клиента — это запрос PUT к registration_client_uri с токеном доступа к регистрации. Тело должно быть таким же, как и тело, полученное от конечной точки регистрации, и оно считается перезаписанным. Например, если убрать в теле параметр grant_types, то с сервера авторизации будут удалены все типы грантов.

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

запрос на удаление клиента — это запрос на УДАЛЕНИЕ к registration_client_uri с токеном доступа к регистрации.

Вот и все, теперь мы можем настраивать клиентов!

Заключение

В заключение мы рассмотрели, как найти метаданные, связанные с сервером авторизации. Мы также обсудили, как мы можем зарегистрировать клиента.