Как программно пройти аутентификацию на ресурсе, защищенном облачным Identity-Aware Proxy (Cloud IAP), используя учетные данные пользователя по умолчанию?

Я хотел бы иметь возможность программно сгенерировать токен id для iap, используя учетные данные пользователя по умолчанию в среде разработчика (то есть на моем собственном ноутбуке с установленным и вошедшим в систему Google Cloud SDK).

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

Когда используешь google.auth.default на моем персональном компьютере я вижу учетные данные типа google.oauth2.credentials.Credentials иметь refresh_token, Я хотел использовать его для генерации токена, как это делается с помощью curl в документации под Authenticating from a desktop app -> Accessing the application но я не мог заставить это работать. Кто-нибудь знает, есть ли способ аутентификации таким образом?

2 ответа

Как сказал Мэтью, проект для идентификатора клиента, используемый для получения токена обновления, должен соответствовать проекту для идентификатора клиента IAP. Gcloud использует идентификатор клиента и секрет, определенные в path_to/google-cloud-sdk/lib/googlecloudsdk/api_lib/auth/util.py для учетных данных по умолчанию (DEFAULT_CREDENTIALS_DEFAULT_CLIENT_ID а также DEFAULT_CREDENTIALS_DEFAULT_CLIENT_SECRET). Из-за этого вы не можете использовать токен обновления из google.auth.default() без util.py изменить, так как попытка получить идентификатор токена не удастся с:

{
 "error": "invalid_audience",
 "error_description": "The audience client and the client need to be in the same project."
}

Ваши варианты:

  1. Получите токен обновления (кэшируйте его, чтобы избежать необходимости каждый раз предоставлять пользовательские права) и токен ID в соответствии с ответом / документацией Мэтью.
  2. Патч ID клиента и секретный ключ присутствуют в gcloud util.py (может быть изменен с помощью обновлений gcloud).

Пример кода для обоих вариантов:

import google.auth
import requests
import json

from webbrowser import open_new_tab
from time import sleep

# use gcloud app default credentials if gcloud's util.py is patched
def id_token_from_default_creds(audience): 
    cred, proj = google.auth.default()
    # data necessary for ID token
    client_id = cred.client_id
    client_secret= cred.client_secret
    refresh_token = str(cred.refresh_token)
    return id_token_from_refresh_token(client_id, client_secret, refresh_token, audience)

def id_token_from_refresh_token(client_id, client_secret, refresh_token, audience):
    oauth_token_base_URL = "https://www.googleapis.com/oauth2/v4/token"
    payload = {"client_id": client_id, "client_secret": client_secret,
                "refresh_token": refresh_token, "grant_type": "refresh_token",
                "audience": audience}
    res = requests.post(oauth_token_base_URL, data=payload)
    return (str(json.loads(res.text)[u"id_token"]))

# obtain ID token for provided Client ID: get authorization code -> exchange for refresh token -> obtain and return ID token
def id_token_from_client_id(client_id, client_secret, audience):
    auth_code = get_auth_code(client_id)
    refresh_token = get_refresh_token_from_code(auth_code, client_id, client_secret)
    return id_token_from_refresh_token(client_id, client_secret, refresh_token, audience)

def get_auth_code(client_id):
    auth_url = "https://accounts.google.com/o/oauth2/v2/auth?client_id=%s&response_type=code&scope=openid%%20email&access_type=offline&redirect_uri=urn:ietf:wg:oauth:2.0:oob"%client_id
    open_new_tab(auth_url)
    sleep(1)
    return raw_input("Authorization code: ")

def get_refresh_token_from_code(auth_code, client_id, client_secret):
    oauth_token_base_URL = 'https://www.googleapis.com/oauth2/v4/token'
    payload = {"code": auth_code, "client_id": client_id, "client_secret": client_secret,
                "redirect_uri": "urn:ietf:wg:oauth:2.0:oob", "grant_type": "authorization_code"}
    res = requests.post(oauth_token_base_URL, data=payload)
    return (str(json.loads(res.text)[u"refresh_token"]))

print("ID token from client ID: %s" % id_token_from_client_id("<Other client ID>", "<Other client secret>", "<IAP Client ID>")) # other client ID should be from the same project as IAP Client ID 
print("ID token from \"default\" credentials: %s" % id_token_from_default_creds("<IAP Client ID>"))

Спасибо за указание на это! Я был бы рад, если бы у нас были примеры кода для этого, но, как вы обнаружили, по крайней мере для Python пример кода, который мы имеем для аутентификации служебной учетной записи, не работает с учетными записями пользователей.

Я не достаточно знаком с нашими клиентскими библиотеками Python, чтобы сказать вам, могут ли они помочь вам с этим, но суть того, что https://cloud.google.com/iap/docs/authentication-howto есть проведя вас через это:

  1. Создайте новый идентификатор клиента (в том же проекте, что и приложение с защитой IAP) для своего клиентского приложения и получите токен обновления, используя этот идентификатор клиента. Вы не можете просто использовать токен обновления из учетных данных приложения по умолчанию, поскольку у него будет неправильный идентификатор клиента и, вероятно, области. Вместо этого вам нужно добавить в приложение такую ​​функциональность, как "gcloud auth login", и сохранить маркер обновления.

  2. Когда у вас есть токен обновления, когда ваше клиентское приложение хочет получить доступ к приложению IAP: отправьте POST на https://www.googleapis.com/oauth2/v4/token с идентификатором клиента и секретом для клиента OAuth вашего приложения, токен обновления и идентификатор клиента IAP. Это возвращает токен OpenID Connect, который будет действителен для аутентификации в IAP в течение одного часа.

Этого по крайней мере достаточно, чтобы начать?

Другие вопросы по тегам