Bagaimana cara menggunakan pyJWT untuk memverifikasi tanda tangan di JWT ini?

Saya telah menerima token JWT. Saya tertarik untuk membongkarnya dan memvalidasi isinya.

Saya ingin menggunakan perpustakaan pyJWT untuk melakukannya. Lihat program kecil di bawah ini.

Saya telah berhasil mendekodekan JWT base64 saya. Dan saya telah mengambil JWK yang cocok dari web. Tapi saya tidak tahu apa yang harus saya lakukan selanjutnya untuk memverifikasi tanda tangan.

Ketika saya mencoba melakukan jwt.decode() di bawah ini saya mendapatkan kesalahan jwt.exceptions.DecodeError: Not enough segments.

# !/usr/bin/env python

import jwt
import base64
import json
import requests

my_jwt = "eyJqa3UiOiJodHRwczovL2U5N2I4YTlkNjcyZTRjZTQ4NDVlYzY5NDdjZDY2ZW" \
         "Y2LXNiLmJhYXMubmludGVuZG8uY29tLzEuMC4wL2NlcnRpZmljYXRlcyIsImtp" \
         "ZCI6ImZlOWRiYmZmLTQ3MGItNDZjOC04YmFmLTFiNzY5OGRlZTViZSIsImFsZy" \
         "I6IlJTMjU2In0.eyJpc3MiOiJodHRwczovL2U5N2I4YTlkNjcyZTRjZTQ4NDVl" \
         "YzY5NDdjZDY2ZWY2LXNiLmJhYXMubmludGVuZG8uY29tIiwiZXhwIjoxNTQ1MT" \
         "g1NDk2LCJ0eXAiOiJpZF90b2tlbiIsImF1ZCI6IjhkOTc1NTllNjNlY2NkNTYi" \
         "LCJiczpkaWQiOiI2NjJhZTQwOWYwNTQyYTBjIiwic3ViIjoiOTNkYmYwNDdiYT" \
         "I3NzQ5NSIsImp0aSI6IjY1NDg4ZjJmLTI1NzAtNDBkYy04ODQ3LTMzODNlZWIx" \
         "MGJiYiIsIm5pbnRlbmRvIjp7ImFpIjoiMDEwMGY4MDAwMDQ5MjAwMCIsImF2Ij" \
         "oiMDAwMCIsImVkaSI6ImJjNTdiYmM3MTZlMDA1MGFmOWRhN2NkYTIzMWRjZDgy" \
         "IiwiYXQiOjE1NDUxNzQ2OTZ9LCJpYXQiOjE1NDUxNzQ2OTZ9.ZMUIt3wYrbfhX" \
         "nnDh4WraGlKrZy0YuL5prluY70sU_-0W5XvWIB-xmTrLz7LJWHEGwTskcWf81_" \
         "HBq_mSb75rMfTAEBwBmOJ4ITmhdnXksz8w7EDOWuPPSEft5XLMNOMD16ztEOYe" \
         "5ddU_iqNEbT56L7fcAJEXv0FWy6H_OutxOglYpDaNkcj6CWJ7dpA0JbqerR9dE" \
         "szaLwyn1ZBDPVD0YeAIm5bEr61imeedzMb0amxlTl4R87mqK6epsFUnRy6p6Kl" \
         "r27_DlTLQ-gej09W7NeNzONCj4thHgCr9szAiaN28krfTc2fobz3qFCoC_eQgh" \
         "iIIZBe_-Lksng3Eg6tw"

decoded_token = [
    base64.b64decode(i + '=' * (-len(i) % 4))
    for i in my_jwt.split('.')
]
header = json.loads(decoded_token[0])
claims = json.loads(decoded_token[1])
signature = decoded_token[2]

print 'Header = \n{}\n\n'.format(header)
print 'Claims = \n{}\n\n'.format(claims)
print 'Signature = \n{}\n\n'.format(signature)

key_found = False
for curr_jwk in requests.get(header['jku']).json()['keys']:
    if curr_jwk['kid'] == header['kid']:
        key_found = True
        break
assert key_found
print 'curr_jwk = {}\n\n'.format(curr_jwk)

# I am not sure if the following line is correct
jwt.decode(signature, curr_jwk['x5c'][0], algorithms=['RS256'])

Di bawah ini adalah keluaran lengkapnya. Tolong tunjukkan saya bagaimana saya bisa memverifikasi tanda tangan. Saya belum menemukan contoh python di web yang cocok untuk saya.

Header =
{u'jku': u'https://e97b8a9d672e4ce4845ec6947cd66ef6-sb.baas.nintendo.com/1.0.0/certificates', u'alg': u'RS256', u'kid': u'fe9dbbff-470b-46c8-8baf-1b7698dee5be'}


Claims =
{u'aud': u'8d97559e63eccd56', u'iss': u'https://e97b8a9d672e4ce4845ec6947cd66ef6-sb.baas.nintendo.com', u'jti': u'65488f2f-2570-40dc-8847-3383eeb10bbb', u'exp': 1545185496, u'nintendo': {u'ai': u'0100f80000492000', u'edi': u'bc57bbc716e0050af9da7cda231dcd82', u'at': 1545174696, u'av': u'0000'}, u'iat': 1545174696, u'bs:did': u'662ae409f0542a0c', u'typ': u'id_token', u'sub': u'93dbf047ba277495'}


Signature =
�dr>�X�ݤn��G�D�6��)�d�T=x&�+�X�y�s1��S��|�j���lI�˪z*Z��9S�OV�׍��B��a������v�J�M͟���P�m>z/� �d�����H:�)


curr_jwk = {
    u'use': u'sig', 
    u'e': u'AQAB', 
    u'kty': u'RSA', 
    u'alg': u'RS256', 
    u'n': u'twZRFUFinbzSF9aCaLqSdDSfS4Lfz6bSB-4ymwqkgJPLMLtX0meEVOSsx2qP_OQFkb6_RAZk3GK2CSM46V8A-bZqYn1jHyRyQeQmAfrzvXxAiXBdSq4Eso1C_roFQDjR3p-RnLWDLdMPUHkmAQSPEpVAUbcCvUD8zZwQ-go8GAzG0iQNNvZxma1JQoDsHPgY5LiBVBlqY43tp_jeW_sb3SxZ30zzIckKtQfYDfph_vns-q1_raNRPgS0TQw4E470n27UgLE30yoVn_DlYwmtZneCOWIByVPrMBMIkrv_Gh9VW3GszbqZz2u3K9Aj7rtnCtmUrI9dQbeTnruWOn_Fjw', 
    u'x5c': [u'MIIC/zCCAeegAwIBAgIHBX0u6g3YCzANBgkqhkiG9w0BAQUFADBAMT4wPAYDVQQDEzVlOTdiOGE5ZDY3MmU0Y2U0ODQ1ZWM2OTQ3Y2Q2NmVmNi1zYi5iYWFzLm5pbnRlbmRvLmNvbTAeFw0xNzEyMTYwMDAwMDBaFw0xOTEyMTcwMDAwMDBaMEAxPjA8BgNVBAMTNWU5N2I4YTlkNjcyZTRjZTQ4NDVlYzY5NDdjZDY2ZWY2LXNiLmJhYXMubmludGVuZG8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtwZRFUFinbzSF9aCaLqSdDSfS4Lfz6bSB+4ymwqkgJPLMLtX0meEVOSsx2qP/OQFkb6/RAZk3GK2CSM46V8A+bZqYn1jHyRyQeQmAfrzvXxAiXBdSq4Eso1C/roFQDjR3p+RnLWDLdMPUHkmAQSPEpVAUbcCvUD8zZwQ+go8GAzG0iQNNvZxma1JQoDsHPgY5LiBVBlqY43tp/jeW/sb3SxZ30zzIckKtQfYDfph/vns+q1/raNRPgS0TQw4E470n27UgLE30yoVn/DlYwmtZneCOWIByVPrMBMIkrv/Gh9VW3GszbqZz2u3K9Aj7rtnCtmUrI9dQbeTnruWOn/FjwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBsXUY5j/m4pAB0R3zDEHHBXZUCkdN53zCr5M7/Kn4ak0vKb9Hk1gNJqdS+dNyW1C7aNGFPmmcMhOos3tv0KsjNoftA4A27uIA7U6QYtJSUVbtVJgYCu8XUa2VDongGNxB72UvFiD++qY3Xe95b0kzsoSOqGaguicAeRSG/HARDaNJT5I9MhCYdCmjU/z83dGI0t8v33Zua92YVmzL6E06lxQ7KrVa9MlKgVJEiAnju3GESVFmrhEoVt516EVxvTVmFlrsvN6rh+c/jC3mBDkE7E23ukg6FpM8oCVRU/5o8/lnKVcRhYPnBgHwg/wTL/Is5rteMtLihV/mvgt3InWkc'],
    u'usage': u'developer', 
    u'kid': u'fe9dbbff-470b-46c8-8baf-1b7698dee5be'
}

Traceback (most recent call last):
  File "./saqib_test.py", line 46, in <module>
    jwt.decode(signature, curr_jwk['x5c'][0], algorithms=['RS256'])
  File "/Users/saqib.ali/saqib-env-987/lib/python2.7/site-packages/jwt/api_jwt.py", line 84, in decode
    payload, _, _, _ = self._load(jwt)
  File "/Users/saqib.ali/saqib-env-987/lib/python2.7/site-packages/jwt/api_jws.py", line 183, in _load
    raise DecodeError('Not enough segments')
jwt.exceptions.DecodeError: Not enough segments

person Saqib Ali    schedule 19.12.2018    source sumber


Jawaban (2)


Pertama, Anda harus langsung mendekode pesan yang disandikan base64. Itu adalah pesan jwt keseluruhan, bukan hanya tanda tangannya. Yang seharusnya:

jwt.decode(my_jwt, algorithms='RS256')

Kedua, ini tidak akan berfungsi karena secara default tidak ada dukungan RS256. Anda dapat merujuk ke masalah ini: https://github.com/jpadilla/pyjwt/issues/181

Terakhir, menurut saya Anda tidak dapat memecahkan kode pesan berkode RS256 ini tanpa kunci publik. Apakah kamu punya kunci itu?

person Sraw    schedule 19.12.2018
comment
Saya tidak yakin apakah saya memiliki kunci publik. Saya pikir saya tahu. Tapi saya tidak 100% yakin. Apakah curr_jwk['x5c'][0] adalah kunci publik? - person Saqib Ali; 20.12.2018
comment
Sejujurnya saya tidak tahu. Anda bisa mencoba. Jika Anda berhasil, maka itu berhasil. - person Sraw; 20.12.2018
comment
Pemahaman saya adalah Anda dapat mendekode token RS256 (yang hanya dikodekan base64 - gunakan argumen: verifikasi=False) - tetapi Anda tidak dapat memverifikasi tanpa kunci publik. - person python1981; 06.08.2019

Anda membuat proses decoding Anda menjadi sangat sulit.

Ini adalah satu baris untuk memecahkan kode token JWT:

JWT_SECRET = 'secretpassphrase'
JWT_ALGORITHM = 'HS256'
decoded = json.loads(json.dumps(jwt.decode(token, JWT_SECRET, JWT_ALGORITHM)))

Apa yang dilakukan baris ini adalah mendekode token menggunakan kata sandi rahasia yang digunakan untuk membuatnya, lalu json.dumps memuatnya ke dalam format byte, selanjutnya json.loads memungkinkan Anda menguraikannya dengan kode di bawah ini.

Setelah ini Anda bisa mendapatkan atribut individual dari token seperti ini:

user_id = decoded['user_id']
expiry_time = decoded['exp']

CATATAN: Ini harus dimasukkan ke dalam pernyataan Coba: Tangkap karena jika token kedaluwarsa atau tidak menggunakan tanda tangan yang sama maka python akan menimbulkan kesalahan. Tanda Tangan Tidak Valid atau Token telah Kedaluwarsa.

def verify_token(token):
    try:
        decoded = json.loads(json.dumps(jwt.decode(token, JWT_SECRET, JWT_ALGORITHM)))
        return {
           'name': decoded['user_id'],
           'exp': decoded['exp']
           }
    except:
        print("Generic Error")

Semoga ini membantu

person D3vRandom    schedule 26.07.2020
comment
Itu sangat membantu saya, terima kasih banyak. Saya telah melihat masalah token jwt ini selama beberapa waktu di fungsi Lambda saya tetapi tidak tahu cara melakukannya. @D3vRandom, komentar Anda benar-benar datang pada waktu yang tepat bagi saya. - person flyiinhigh; 26.07.2020