Подтвердить подпись в JWT от login.microsoftonline.com с помощью PHP

Я пытаюсь настроить службу единого входа для веб-страницы с помощью Службы Azure Active Directory/OpenID Connect от Microsoft.

У меня есть кое-что, в том смысле, что я могу заставить их службу отправить мне id_token, но я борюсь с тем, как аутентифицировать/проверить этот токен. Поскольку я получил его из браузера пользователя, а не через межсерверный запрос, мне нужно проверить его, верно?

Чтобы получить токен, я просто использую ссылку:

https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=[myclientid]&response_type=id_token&redirect_uri=https://localhost/ssotest.php&response_mode=form_post&scope=openid+profile&state=12345&nonce=678910

(Для тех, кто пытается сделать то же самое, мне потребовались годы, чтобы найти, но вы можете настроить свой идентификатор клиента здесь: https://apps.dev.microsoft.com/)

Затем эта страница отправляет данные в мой скрипт, который выглядит примерно так:

array(3) {
  ["id_token"]=>
  string(1026) "abc.def.geh"
  ["state"]=>
  string(5) "12345"
  ["session_state"]=>
  string(36) "dd7781aa-74e8-4aa8-ac7e-d3800c5c2247"
}

С этого момента я разделил токен идентификатора на заголовок, тело и подпись в зависимости от периодов/точек.

Затем я могу base64decode заголовок:

["typ"]=> string(3) "JWT"
["alg"]=> string(5) "RS256"
["kid"]=> string(27) "MnC_VZcATfM5pOYiJHMba9goEKY" 

и тело:

["aud"]=> string(36) "[client_id]"
["iss"]=> string(75) "https://login.microsoftonline.com/52f161e7.../v2.0"
["iat"]=> int(1466523280)
["nbf"]=> int(1466523280)
["exp"]=> int(1466527180)
["ipaddr"]=> string(15) "111.111.111.111"
["name"]=> string(12) "Mr E Xample"
["nonce"]=> string(6) "678910"
["oid"]=> string(36) "c3beeb42..."
["preferred_username"]=> string(23) "[email protected]"
["sub"]=> string(43) "oGAnGQ..."
["tid"]=> string(36) "52f161e7..."
["ver"]=> string(3) "2.0"

Теперь у меня есть подпись, но я не совсем уверен, что с ней делать. Я понимаю, что могу получить правильный общедоступный сертификат от https://login.microsoftonline.com/common/discovery/v2.0/keys, как указано в kid в заголовке, но я не уверен, как это поможет. Поскольку я знаю открытый ключ, я предполагаю, что мне нужно расшифровать подпись с его помощью - это правильно ??

Наверняка должен быть способ отправить запрос сервера на сервер для проверки информации, отправленной мне от клиента? Например. GET https://login.microsoftonline.com/verfifytoken/[token]

Я настроил Google SSO, что было проще простого по сравнению с этим — я уверен, что что-то упускаю, но это действительно кажется слишком сложным!

Любая помощь будет очень признательна - я читаю документацию уже много часов! Мне бы очень хотелось по возможности избегать использования библиотек для этого, чтобы я мог полностью понять, что происходит.


person Ben    schedule 21.06.2016    source источник
comment
По моему опыту, мы можем использовать [Authorization: id_token] в вашем заголовке. И вы можете запросить URL-адрес своего приложения (вы регистрируете приложение, используя URL-адрес) с этим заголовком.   -  person Will Shao - MSFT    schedule 28.06.2016
comment
Уилл, я думаю, вы имели в виду не Authorization: id_token, а Authorization: Bearer [id_token]?   -  person Konstantin    schedule 25.08.2016
comment
это может помочь   -  person spottedmahn    schedule 10.08.2017


Ответы (1)


Поскольку я знаю открытый ключ, я предполагаю, что мне нужно расшифровать подпись с его помощью - это правильно ??

На самом деле, что вам нужно сделать, это проверить подпись самостоятельно.

Свойство alg сообщает вам, что используется алгоритм RS256, что означает RSA 256. Я не специалист по Python, но быстрый поиск указывает мне здесь (не уверен, что эта библиотека лучшая...), где вы можете проверить подпись. Сообщение — это два первых блока JWT (разделенные символом '.'), а подпись — это третий блок.

person Bruno Brant    schedule 15.05.2020