Библиотека Python JWT Проблемы с подписью PyJWT с HS256 - HMAC с использованием алгоритма хеширования SHA-256
Попытка сгенерировать токен JWT, используя PyJWT
библиотека.
Когда я использую приведенную ниже программу для генерации токена JWT - токен не работает.
Однако когда я использую веб-сайт https://jwt.io/ с теми же подробностями - токен работает. Есть ли что-то, что мне не хватает.
Мне нужно, чтобы python генерировал токен правильно, чтобы я мог автоматизировать некоторые API, которым нужен этот токен.
Программа Python:
import jwt
import base64
code = jwt.encode({'sub':'String','nbf':'1501594247',
'exp':'1501767047', 'iss': 'string', 'aud': 'String'},
base64.b64encode('secret'), algorithm='HS256')
print code
Пример:
code = jwt.encode({'sub':'AccountNUmber.QTVR','nbf':'1501594247','exp':'1501860089', 'iss': 'client_id', 'aud': 'https://login.google.com/oauth'},
base64.b64encode('secret'), algorithm='HS256')
Результат:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjbGllbnRfaWQiLCJhdWQiOiJodHRwczovL2xvZ2luLmdvb2dsZS5jb20vb2F1dGgiLCJzdWIiOiJBY2NvdW50TlVtYmVyLlFUVlIiLCJleHAiOiIxNTAxODYwMDg5IiwibmJmIjoiMTUwMTU5NDI0NyJ9.dRUUQYJ-RmxgoExwPyrvHPzX9SsxcpX1rOWlhisxNsg
Токен, сгенерированный https://jwt.io/:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjbGllbnRfaWQiLCJhdWQiOiJodHRwczovL2xvZ2luLmdvb2dsZS5jb20vb2F1dGgiLCJzdWIiOiJBY2NvdW50TlVtYmVyLlFUVlIiLCJleHAiOiIxNTAxODYwMDg5IiwibmJmIjoiMTUwMTU5NDI0NyJ9.INp-ZnnL8Uj7MIwLYmpZtGyTyZG-oqZRNW8iZ145jVs
Токен, сгенерированный https://jwt.io/ работает, когда я вызываю конечную точку. И я получаю код состояния 200 (Успех).
Однако, когда я использую токен, сгенерированный из моей программы, он выдает "Invalid Token" - 400 (Bad Request).
2 ответа
Ошибка здесь base64.b64encode
в вашем утверждении Python. Вы не должны кодировать секрет, прежде чем передать его jwt.encode
, Я думаю, что отладчик jwt.io немного вводит в заблуждение в этом отношении:
Идея заключается в том, что у вас есть секрет, который хранится где-то в кодированном формате base64, и отладчик jwt.io расшифрует ваш секрет, когда вы скажете ему, что он закодирован.
Как вы можете легко проверить в idle
:
>>> base64.b64encode('secret')
'c2VjcmV0'
И если вы вставите закодированный секрет в секретное поле в jwt.io и установите флажок, как показано на рисунке выше, вы получите следующий токен:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJjbGllbnRfaWQiLCJhdWQiOiJodHRwczovL2xvZ2luLmdvb2dsZS5jb20vb2F1dGgiLCJzdWIiOiJBY2NvdW50TlVtYmVyLlFUVlIiLCJleHAiOiIxNTAxODYwMDg5IiwibmJmIjoiMTUwMTU5NDI0NyJ9.Nk6oCKBlT9lh4rtJZzF8JuyEsiH_HBaa3UhUx3DbWeI
который идентичен выводу следующих программ на python:
а) когда вы предоставляете секрет напрямую, не закодированы:
code = jwt.encode({'sub':'AccountNUmber.QTVR','nbf':'1501594247','exp':'1501860089', 'iss': 'client_id', 'aud': 'https://login.google.com/oauth'},
'secret', algorithm='HS256')
б) когда вы предоставляете закодированный секрет:
code = jwt.encode({'sub':'AccountNUmber.QTVR','nbf':'1501594247','exp':'1501860089', 'iss': 'client_id', 'aud': 'https://login.google.com/oauth'},
base64.b64decode('c2VjcmV0'), algorithm='HS256')
Это должно работать.
Есть ошибка в документации, я проверил исходный код этой библиотеки
class PyJWT(PyJWS):
header_type = 'JWT'
@staticmethod
def _get_default_options():
# type: () -> Dict[str, bool]
return {
'verify_signature': True,
'verify_exp': True,
'verify_nbf': True,
'verify_iat': True,
'verify_aud': True,
'verify_iss': True,
'require_exp': False,
'require_iat': False,
'require_nbf': False
}
def encode(self,
payload, # type: Union[Dict, bytes]
key, # type: str
algorithm='HS256', # type: str
headers=None, # type: Optional[Dict]
json_encoder=None # type: Optional[Callable]
):
# Check that we get a mapping
if not isinstance(payload, Mapping):
raise TypeError('Expecting a mapping object, as JWT only supports '
'JSON objects as payloads.')
# Payload
for time_claim in ['exp', 'iat', 'nbf']:
# Convert datetime to a intDate value in known time-format claims
if isinstance(payload.get(time_claim), datetime):
payload[time_claim] = timegm(payload[time_claim].utctimetuple()) # type: ignore
json_payload = json.dumps(
payload,
separators=(',', ':'),
cls=json_encoder
).encode('utf-8')
return super(PyJWT, self).encode(
json_payload, key, algorithm, headers, json_encoder
)
Так что решение будет
from jwt.api_jwt import PyJWT
payload = {
'id': 5,
'email': 'ASDASDA'
}
key = 'secret'
jwt_Obj=PyJWT()
jwt_token = jwt_Obj.encode( payload=payload,key= key )
decode_token=jwt_Obj.decode(jwt_token,key=key)
print (jwt_token)
print(decode_token)
Вывод должен или (должен) быть b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6IkFTREFTREEiLCJpZCI6NX0.-Woz4Crgi5KZj_D99eGaKxY4JaH77
{'email': 'ASDASDA', 'id': 5}