Gsuite Directory API 403 Ошибка при вызове API или ошибка типа предоставления при генерации JWT - PullRequest
0 голосов
/ 06 марта 2020

Используя Python и создавая свой собственный JWT с использованием методологии HTTP / Rest, я просто не могу заставить делегирование работать.

С одной стороны, в документации по устранению неполадок Google JWT говорится, что ISS должен быть таким же как SUB (учетная запись службы).

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

Нет необходимости говорить, что, несмотря на включение делегирования на уровне домена, добавление правильных областей действия и т. Д. c, я получаю только 403 при попытке получить доступ к домену пользователя с использованием библиотеки запросов в python со следующим пример:


> requests.get("https://www.googleapis.com/admin/directory/v1/users/useremail@/
> google.org",headers={'Authorization':f' Bearer {oauth2tokenhere}'})

Вот пример моей претензии:



> claim = { "iss": 'serviceaccountemail', 
>         'sub': 'impersonatedaccountemail',
>         'scope': 'https://www.googleapis.com/auth/admin.directory.user.readonly',
>         'exp': ((datetime.datetime.today() + datetime.timedelta(minutes=60)).timestamp()),
>         'iat': ((datetime.datetime.today()).timestamp()),
>         'aud': "https://oauth2.googleapis.com/token"
>     }

Приведенная выше претензия приведет к генерализованной ошибке предоставления (мило, но не полезно).

Если я изменяю утверждение и проверяю, что sub и iss совпадают, генерируется oauth2token, но я получаю ошибку 403 при попытке попасть в API.

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

https://developers.google.com/identity/protocols/OAuth2ServiceAccount

Вот статья об устранении неполадок, описывающая ISS / Sub был тем же (хотя статья об облаке - самая близкая релевантная топи c, которую я мог найти)

https://cloud.google.com/endpoints/docs/openapi/troubleshoot-jwt

РЕДАКТИРОВАТЬ:

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

import json as j
import datetime
import jwt
import requests



#creates the claim, 'secret' (from the private key), and the kid, from the service account file, and returns these values in a tuple.
#the tuple can then be used to make dependable positional argument entries to the parameters of the createJWT function.

def create_claim_from_json(self,objpath,scope=["https://www.googleapis.com/auth/admin.directory.user.readonly" "https://www.googleapis.com/auth/admin.directory.user"]):

    with open(f'{objpath}','r') as jobj:
        data = j.load(jobj)

    claim = {
        "iss": str(data['client_id']),
        "sub": str(data['client_id']),
        "scope": str(scope),
        "exp": ((datetime.datetime.today() + datetime.timedelta(minutes=59)).timestamp()),
        "iat": ((datetime.datetime.today()).timestamp()),
        "aud": "https://oauth2.googleapis.com/token"
    }

    private_key = data['private_key']

    kid = {"kid": f"{data['private_key_id']}"}

    return claim, private_key, kid


#assembles the JWT using the claim, secret (Private key from the Service account file), the kid value, and the documented RS256 alg.
#returns the completed JWT object back to be used to send to the oauth2 endpoint
#the JWT will be used in the function call retrieve_oauth2token.

def createJWT(self, claim, secret, kid, alg='RS256'):

    encoded_jwt = (jwt.encode(claim, secret, alg, kid)).decode('UTF-8')

    return encoded_jwt


#Using the JWT created in memory, sends the JWT to the googleapi oauth2 uri and returns a token

def retrieve_oauth2token(self, jwt):

    oauth2 = requests.post(f'https://oauth2.googleapis.com/token?grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-    type%3Ajwt-bearer&assertion={jwt}')

    oauth2=oauth2.json()

    return oauth2 #['access_token'], oauth2['token_type']

1 Ответ

0 голосов
/ 08 марта 2020

Документация содержит четкий обзор. Выполнили ли вы шаги, описанные в приложении? Мне не хватает некоторых частей вашего кода. Но вы не упомянули использование ключа учетной записи службы (json). И документация также показывает, что вы должны использовать (делегированную) учетную запись службы как iss и sub. Кроме того, вам нужно использовать ребенка. Вот как это делается:

payload = {
    'iss': '123456-compute@developer.gserviceaccount.com',
    'sub': '123456-compute@developer.gserviceaccount.com',
    'aud': 'https://firestore.googleapis.com/',
    'iat': time.time(),
    'exp': iat + 3600
}
additional_headers = {'kid': PRIVATE_KEY_ID_FROM_JSON}
signed_jwt = jwt.encode(payload, PRIVATE_KEY_FROM_JSON, headers=additional_headers, algorithm='RS256')

url = "URL OF THE API TO CALL"
header = {'Authorization': f'Bearer {signed_jwt}'}
resp = requests.get(url, headers=header)

Примечание: вы можете найти PRIVATE_KEY_FROM_JSON в поле private_key_id вашей учетной записи службы JSON файл учетных данных.

...