Перенос бэкэнда Python из Gitkit в Firebase-Auth с python-jose для проверки токена

На GitHub полезный разработчик Google сказал мне, что

чтобы создать сеанс пользователя, вашему фоновому серверу Python требуется только библиотека JWT для проверки токена Firebase Auth (подписи и аудитории) в запросе и извлечения информации о пользователе из полезной нагрузки токена.

У меня проблемы с проверкой токена.

Это где я нахожусь; Чтобы начать миграцию, я сделал следующее:

  1. Я добавил Firebase-Auth в приложение для Android, оставив Gitkit в приложении до тех пор, пока не будет работать Firebase-Auth. Теперь у меня есть две кнопки входа, одна для входа в Firebase, а другая для "почти устаревшего" Gitkit.

  2. На firebase.com я импортировал проект Google в новый проект Firebase, поэтому база данных пользователей такая же. Мне уже удалось использовать Firebase-Auth в приложении для Android, я могу войти в систему как известный пользователь, и я могу успешно получить токен, который мне понадобится для моего внутреннего сервера, вызвав mFirebaseAuth.getCurrentUser().getToken(false).getResult().getToken(), Он содержит то же самое user_id в качестве токена GitKit.

Сейчас я пытаюсь заменить identity-toolkit-python-client библиотека с python-jose, Поскольку в настоящее время я не отправляю токен Firebase на сервер, а только токен Gitkit, я хочу проверить это python-jose библиотека на токене Gitkit.

На бэкэнд, перед звонком GitKit.VerifyGitkitToken() я сейчас распечатываю результаты jose.jwt.get_unverified_header() а также jose.jwt.get_unverified_claims() чтобы проверить, смогу ли я увидеть то, что ожидаю. Результаты хорошие, я могу просматривать содержимое токена Gitkit так, как ожидалось.

Моя проблема связана с проверкой. Я не могу использовать jose.jwt.decode() для проверки, потому что я не знаю, какой ключ мне нужно использовать.

jose.jwt.decode(token, key, algorithms=None, options=None, audience=None, issuer=None, subject=None, access_token=None)

Я знаю алгоритм из заголовка, и поле 'aud' также хранится в формулах, если это поможет.

Возвращаясь к комментариям инженеров

проверить токен Firebase Auth (подпись и аудитория)

Как мне сделать это с информацией, имеющейся у меня? Я предполагаю, что аудитория - это поле "aud" в заявках, но как мне проверить подпись?

После удаления зависимости Gitkit от сервера я продолжу миграцию.

Из того, что я видел, библиотека GitKit, очевидно, выполняет RPC-вызов на сервер Google для проверки, но я могу ошибаться.

Итак, какой будет ключ для проверки токена Gitkit, а также для проверки токена Firebase?

1 ответ

Решение

Ключи можно получить

для Firebase в https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com

и для Gitkit в https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys

Использование Googles oauth2client библиотека делает проверку очень простой.

Но если вы хотите использовать python-jose вместо oauth2client затем вам нужно сначала преобразовать сертификат PEM в открытый ключ RSA (обновление: эта проблема исправлена, для Firebase эта проблема теперь обрабатывается библиотекой, прокрутите вниз до конца ссылку GitHub, предшествующую этому комментарию. Не уверен насчет Gitkit). Этот открытый ключ является ключом, который необходимо использовать. И аудиторию не следует извлекать из заголовка JWT, а жестко закодировать в исходный код, где в Firebase аудитория - это идентификатор проекта, а в Gitkit - один из идентификаторов клиента OAuth 2.0, который можно найти в консоли разработчика Google. Раздел учетных данных.

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

  # firebase
  # target_audience = "firebase-project-id"
  # certificate_url = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com'

  # gitkit
  target_audience = "123456789-abcdef.apps.googleusercontent.com" # (from developer console, OAuth 2.0 client IDs)
  certificate_url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys'

  response = urllib.urlopen(certificate_url)
  certs = response.read()
  certs = json.loads(certs)
  print "CERTS", certs
  print ''
  print ''

  # -------------- verify via oauth2client
  from oauth2client import crypt
  crypt.MAX_TOKEN_LIFETIME_SECS = 30 * 86400 # according to https://github.com/google/identity-toolkit-python-client/blob/master/identitytoolkit/gitkitclient.py
  print "VALID TOKEN", crypt.verify_signed_jwt_with_certs(idtoken, certs, target_audience)  
  print ''
  print ''

  # -------------- verify via python-jose
  from jose import jwt
  unverified_header = jwt.get_unverified_header(idtoken)
  print "UNVERIFIED HEADER", unverified_header
  print ''
  print ''
  unverified_claims = jwt.get_unverified_claims(idtoken)
  print "UNVERIFIED CLAIMS", unverified_claims
  print ''
  print ''
  from ssl import PEM_cert_to_DER_cert
  from Crypto.Util.asn1 import DerSequence
  pem = certs[unverified_header['kid']]
  der = PEM_cert_to_DER_cert(pem)
  cert = DerSequence()
  cert.decode(der)
  tbsCertificate = DerSequence()
  tbsCertificate.decode(cert[0])
  rsa_public_key = tbsCertificate[6]
  print "VALID TOKEN", jwt.decode(idtoken, rsa_public_key, algorithms=unverified_header['alg'], audience=target_audience)
Другие вопросы по тегам