Статьи

Модернизация архитектуры управления ключами WSO2 API Manager на основе открытых стандартов

WSO2 API Manager — это комплексное решение для разработки и публикации API, создания и управления сообществом разработчиков, а также для масштабируемой маршрутизации трафика API. Он использует проверенные, готовые к работе компоненты интеграции, безопасности и управления из корпоративной сервисной шины WSO2, Identity Server WSO2 и реестра управления WSO2. Кроме того, он использует монитор бизнес-активности WSO2 для анализа больших данных, предоставляя вам мгновенное представление о поведении API.

Одно из ограничений, которое у нас было в API Manager, это его тесная интеграция с
WSO2 Identity Server . WSO2 Identity Server выступает в роли диспетчера ключей, который выдает и проверяет токены OAuth.

С обновленной архитектурой (все еще обсуждаемой) мы планируем сделать все точки интеграции с помощью менеджера ключей расширяемыми, чтобы вы могли подключить свой собственный сервер авторизации OAuth. А также — мы отправим товар со стандартными точками расширения. Эти точки расширения построены вокруг соответствующих профилей OAuth 2.0. В случае, если ваш сервер авторизации отклоняется от стандарта, вам необходимо реализовать интерфейс KeyManager и подключить собственную реализацию.

Снимок экрана 2014-08-27 в 12.08.49

API Publisher

Сначала разработчик API входит в API Publisher, создает API со всеми связанными метаданными и публикует его в Магазине API и шлюзе API.

API Publisher также будет публиковать метаданные API на внешнем сервере авторизации через конечную точку регистрации набора ресурсов OAuth [1].

Запрос образца:

1
2
3
4
5
6
7
{
"name": "Photo Album",
                  "http://photoz.example.com/dev/scopes/all" ],
}

имя (обязательно. Удобная для чтения строка, описывающая набор из одного или нескольких ресурсов. Это имя МОЖЕТ использоваться сервером авторизации в его пользовательском интерфейсе владельца ресурса для владельца ресурса.

icon_uri НЕОБЯЗАТЕЛЬНО. URI для графического значка, представляющего набор ресурсов. Указанный значок МОЖЕТ использоваться сервером авторизации в его пользовательском интерфейсе владельца ресурса для владельца ресурса.

ОБЯЗАТЕЛЬНЫ. Массив, предоставляющий ссылки URI описаний области, которые доступны для этого набора ресурсов.

тип ДОПОЛНИТЕЛЬНО. Строка, однозначно идентифицирующая семантику набора ресурсов. Например, если набор ресурсов состоит из единственного ресурса, который является заявкой на идентификацию, которая использует стандартизированную семантику заявки для «проверенного адреса электронной почты», значение этого свойства может быть идентифицирующим URI для этой заявки.

Образец ответа:

1
2
3
4
5
6
7
HTTP/1.1 201
Created Content-Type: application/json
ETag: (matches "_rev" property in returned object) ...
 
{ "status": "created", "_id": (id of created resource set),
  "_rev": (ETag of created resource set)
}

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

API Store

Разработчик приложения входит в API Store и обнаруживает API-интерфейсы, которые он / она хочет для своего приложения, подписывается на них и, наконец, создает приложение. Каждое приложение уникально идентифицируется по его идентификатору клиента. Существует два способа связать идентификатор клиента с приложением, созданным в API Store.

  1. Разработчик приложения вводит идентификатор клиента.

    Разработчик приложения создает идентификатор клиента вне диапазона с сервером авторизации и связывает идентификатор клиента с приложением, которое он только что создал в Магазине API. В этом случае конечная точка динамической регистрации клиента службы авторизации не используется (без шагов 3 и 4).

  2. API Store вызывает конечную точку динамической регистрации клиента внешнего сервера авторизации.

    После создания приложения разработчиком приложения (путем группировки набора API) — API Store вызовет конечную точку динамической регистрации клиента сервера авторизации.

Пример запроса (шаг 3):

01
02
03
04
05
06
07
08
09
10
11
12
POST /register HTTP/1.1
Content-Type: application/json
Accept: application/json
Host: authz.server.com
 
{
"client_name": "My Application”,
"redirect_uris":[" https://client.org/callback","https://client.org/callback2 "], "token_endpoint_auth_method":"client_secret_basic",
"grant_types": ["authorization_code" , "implicit"],
"response_types": ["code" , "token"],
"scope": ["sc1" , "sc2"],
}

client_name: удобочитаемое имя клиента, которое будет представлено пользователю во время авторизации. Если опущен, сервер авторизации МОЖЕТ отобразить необработанное значение «client_id» пользователю. РЕКОМЕНДУЕТСЯ, чтобы клиенты всегда отправляли это поле.

client_uri: URL-адрес веб-страницы с информацией о клиенте. Если он присутствует, сервер ДОЛЖЕН отображать этот URL-адрес для конечного пользователя в интерактивном режиме. РЕКОМЕНДУЕТСЯ, чтобы клиенты всегда отправляли это поле.

logo_uri: URL, который ссылается на логотип для клиента. Если он присутствует, сервер ДОЛЖЕН отображать это изображение конечному пользователю во время утверждения. Значение этого поля ДОЛЖНО указывать на действительный файл изображения.

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

grant_types: Массив типов предоставления OAuth 2.0, которые может использовать клиент.

response_types: массив типов ответов OAuth 2.0, которые может использовать клиент.

token_endpoint_auth_method: запрошенный метод аутентификации для конечной точки токена.

redirect_uris: массив значений URI перенаправления для использования в потоках на основе перенаправления, таких как код авторизации и неявные потоки.

Пример ответа (шаг 4):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
 
{
"client_id":"iuyiSgfgfhffgfh",
"client_secret": "hkjhkiiu89hknhkjhuyjhk",
"client_id_issued_at":2343276600,
"client_secret_expires_at":2503286900,
"grant_types": "authorization_code",
"token_endpoint_auth_method": "client_secret_basic"
}

Клиентское приложение OAuth

Это выходит за рамки API Manager. Клиентское приложение может общаться с внешним сервером авторизации через любой из поддерживаемых им типов разрешений и получать токен доступа [3]. Параметр области действия является необязательным во всех запросах токена — если клиент опускает его, сервер авторизации может связать область действия по умолчанию с токеном доступа. Если области вообще не используются, то API-шлюз может выполнять проверку авторизации на основе других параметров, связанных с клиентом OAuth, конечным пользователем, ресурсом и действием.

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

Образец запроса типа предоставления учетных данных клиента:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
POST /token HTTP/1.1
Host: server.example.com Authorization: Basic Base64Encode(Client ID:Client Secret) Content-Type: application/x-www-form-urlencoded
 
grant_type=client_credentials
 
Sample Response:
 
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store Pragma: no-cache
 
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"example_parameter":"example_value"
}

Пример запроса типа пароля владельца ресурса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
POST /token HTTP/1.1 Host: server.example.com
Authorization: Basic Base64Encode(Client ID:Client Secret)
Content-Type: application/x-www-form-urlencoded
 
grant_type=password&username=johndoe&password=A3ddj3w
 
Sample Response:
 
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store Pragma: no-cache
 
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example", "expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}

API-шлюз

Шлюз API будет перехватывать все сообщения, передаваемые между клиентским приложением OAuth и API, и извлекать маркер доступа, который содержится в заголовке авторизации HTTP. После извлечения токена доступа API Gateway вызывает конечную точку самоанализа Token [4] сервера авторизации.

Запрос образца:

1
2
3
4
5
6
7
POST /introspect HTTP/1.1
Host: authserver.example.com
Content-type: application/x-www-form-urlencoded
Accept: application/json
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
 
token=X3241Affw.4233-99JXJ

Образец ответа:

1
2
3
4
5
6
7
8
9
{
"active": true,
"client_id":"s6BhdRkqt3",
"scope": "read write dolphin",
"sub": "2309fj32kl",
"user_id": "jdoe",
}

активный ТРЕБУЕТСЯ. Логический индикатор того, является ли представленный токен активным в данный момент.

exp НЕОБЯЗАТЕЛЬНО. Целая временная метка, измеренная в количестве секунд с 1 января 1970 года по Гринвичу, указывающая, когда истечет срок действия этого токена.

это опционально. Целая временная метка, измеренная в количестве секунд с 1 января 1970 года по Гринвичу, указывающая, когда этот токен был первоначально выпущен.

сфера ОПЦИЯ. Разделенный пробелами список строк, представляющих области, связанные с этим токеном.

client_id ТРЕБУЕТСЯ. Идентификатор клиента для клиента OAuth, который запросил этот токен.

суб необязательный. Машиночитаемый идентификатор, локальный для AS Владельца ресурса, который авторизовал этот токен.

user_id ТРЕБУЕТСЯ. Удобочитаемый идентификатор пользователя, который авторизовал этот токен.

по желанию. Специфичный для службы строковый идентификатор или список строковых идентификаторов, представляющих целевую аудиторию для данного токена.

не является обязательным. Строка, представляющая эмитента этого токена.

token_type НЕОБЯЗАТЕЛЬНО. Тип токена, как определено в OAuth 2.0

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

Если все в порядке, API Gateway сгенерирует JWT и отправит его в последующий API. Сгенерированный JWT может также включать пользовательские атрибуты. В этом случае API-шлюз будет взаимодействовать с конечной точкой UserInfo сервера авторизации.

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

Защищенные конечные точки

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

  • Регистрация набора ресурсов
  • Конечная точка динамической регистрации клиента
  • Самоанализ конечной точки
  • Конечная точка UserInfo

Для первых трех конечных точек API Manager будет действовать как доверенная система. Соответствующая реализация KeyManager должна знать, как проходить аутентификацию на этих конечных точках. Конечная точка OpenID Connect UserInfo будет вызываться с предоставленным пользователем токеном доступа во время выполнения. Это будет работать, только если соответствующий токен доступа имеет права на чтение профиля пользователя с сервера авторизации.

использованная литература

[1]: http://tools.ietf.org/html/draft-hardjono-oauth-resource-reg-02
[2]: http://tools.ietf.org/html/draft-ietf-oauth-dyn-reg-19
[3]: http://tools.ietf.org/html/rfc6749
[4]: http://tools.ietf.org/html/draft-richer-oauth-introspection-06