or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-python_jwt

Module for generating and verifying JSON Web Tokens with multiple signature algorithms

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/python-jwt@4.1.x

To install, run

npx @tessl/cli install tessl/pypi-python_jwt@4.1.0

0

# Python JWT

1

2

A Python library for generating and verifying JSON Web Tokens (JWTs) with support for multiple signature algorithms including RSA, ECDSA, HMAC, PSS, and EdDSA variants. Uses jwcrypto for cryptographic operations and provides comprehensive JWT validation capabilities.

3

4

**Important Note:** This package is deprecated and no longer maintained by the author. Using the library will trigger a deprecation warning at runtime.

5

6

## Package Information

7

8

- **Package Name**: python_jwt

9

- **Language**: Python

10

- **Installation**: `pip install python_jwt`

11

- **Dependencies**: `jwcrypto>=1.4.2`

12

- **Python Version**: 3.6+

13

- **License**: MIT

14

15

## Core Imports

16

17

```python

18

import python_jwt as jwt

19

import jwcrypto.jwk as jwk

20

from datetime import datetime, timedelta

21

```

22

23

## Basic Usage

24

25

```python

26

import python_jwt as jwt

27

import jwcrypto.jwk as jwk

28

from datetime import timedelta

29

30

# Generate RSA key pair

31

key = jwk.JWK.generate(kty='RSA', size=2048)

32

33

# Create payload with custom claims

34

payload = {'user': 'john', 'role': 'admin', 'permissions': ['read', 'write']}

35

36

# Generate JWT token with 5 minute expiration

37

token = jwt.generate_jwt(payload, key, 'PS256', timedelta(minutes=5))

38

39

# Verify the token

40

header, claims = jwt.verify_jwt(token, key, ['PS256'])

41

42

# Access claims

43

user_id = claims['user']

44

role = claims['role']

45

```

46

47

## Capabilities

48

49

### Token Generation

50

51

Generate JSON Web Tokens with custom claims, automatic timestamps, and replay attack protection.

52

53

```python { .api }

54

def generate_jwt(claims, priv_key=None, algorithm='PS512', lifetime=None,

55

expires=None, not_before=None, jti_size=16, other_headers=None):

56

"""

57

Generate a JSON Web Token with specified claims and signing parameters.

58

59

Args:

60

claims (dict): The claims to include in the token

61

priv_key (jwcrypto.jwk.JWK, optional): Private key for signing (None creates unsigned token)

62

algorithm (str): Signature algorithm (default: 'PS512')

63

lifetime (datetime.timedelta, optional): Token validity duration

64

expires (datetime.datetime, optional): Explicit expiration time

65

not_before (datetime.datetime, optional): Token valid-from time

66

jti_size (int): Size of unique token ID in bytes (default: 16, 0 to omit)

67

other_headers (dict, optional): Additional headers to include

68

69

Returns:

70

str: Unicode string containing the JWT

71

72

Raises:

73

ValueError: If other_headers redefines 'typ' or 'alg'

74

"""

75

```

76

77

**Supported Algorithms**: RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, ES256K, EdDSA, HS256, HS384, HS512, none

78

79

**Automatic Claims Added**:

80

- **exp** (expiration time): Based on `lifetime` or `expires` parameter

81

- **iat** (issued at): Current UTC time when token is generated

82

- **nbf** (not before): Based on `not_before` parameter or current time

83

- **jti** (JWT ID): Random unique identifier for replay attack prevention

84

85

#### Usage Examples

86

87

Basic token generation:

88

```python

89

# Simple token with automatic expiration

90

payload = {'sub': '1234567890', 'name': 'John Doe'}

91

token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1))

92

```

93

94

Token with explicit times:

95

```python

96

from datetime import datetime

97

98

# Token valid from tomorrow for 1 week

99

not_before = datetime.utcnow() + timedelta(days=1)

100

expires = not_before + timedelta(weeks=1)

101

token = jwt.generate_jwt(payload, key, 'PS384',

102

not_before=not_before, expires=expires)

103

```

104

105

Unsigned token (for testing):

106

```python

107

# Create unsigned token (algorithm forced to 'none')

108

token = jwt.generate_jwt(payload, None, 'PS256')

109

```

110

111

Custom headers:

112

```python

113

# Add custom headers

114

custom_headers = {'kid': 'key-id-123', 'cty': 'application/json'}

115

token = jwt.generate_jwt(payload, key, 'ES256', timedelta(minutes=30),

116

other_headers=custom_headers)

117

```

118

119

### Token Verification

120

121

Verify JWT signatures and validate time-based claims with comprehensive security checks.

122

123

```python { .api }

124

def verify_jwt(jwt, pub_key=None, allowed_algs=None, iat_skew=timedelta(),

125

checks_optional=False, ignore_not_implemented=False):

126

"""

127

Verify a JSON Web Token's signature and validate claims.

128

129

Args:

130

jwt (str): The JWT to verify

131

pub_key (jwcrypto.jwk.JWK, optional): Public key for verification

132

allowed_algs (list, optional): List of allowed signature algorithms (None defaults to empty list)

133

iat_skew (datetime.timedelta): Clock skew tolerance for 'iat' claim

134

checks_optional (bool): Whether typ/iat/nbf/exp claims are optional

135

ignore_not_implemented (bool): Whether to ignore unsupported header properties

136

137

Returns:

138

tuple: (header, claims) containing parsed header and claims dictionaries

139

140

Raises:

141

Exception: Various exceptions if verification fails, including:

142

- Invalid JWT format

143

- Algorithm header not present or not in allowed list

144

- Unknown or unsupported header properties

145

- No public key provided but 'none' algorithm not allowed

146

- Invalid 'typ' header (must be 'JWT')

147

- Missing required claims (iat, nbf, exp) when checks_optional=False

148

- Token issued in future (iat validation)

149

- Token not yet valid (nbf validation)

150

- Token expired (exp validation)

151

- Signature verification failures

152

"""

153

```

154

155

**Validation Checks Performed**:

156

- Algorithm must be in allowed_algs

157

- Signature verification (unless algorithm is 'none')

158

- Header 'typ' must be 'JWT'

159

- Claims 'iat' must be in the past (with skew tolerance)

160

- Claims 'nbf' must be in the past (not before)

161

- Claims 'exp' must be in the future (expiration)

162

163

#### Usage Examples

164

165

Basic verification:

166

```python

167

# Verify with specific algorithm

168

header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])

169

```

170

171

Multiple allowed algorithms:

172

```python

173

# Allow multiple signature algorithms

174

header, claims = jwt.verify_jwt(token, pub_key, ['RS256', 'PS256', 'ES256'])

175

```

176

177

Clock skew tolerance:

178

```python

179

# Allow 30 seconds clock skew for distributed systems

180

header, claims = jwt.verify_jwt(token, pub_key, ['PS256'],

181

iat_skew=timedelta(seconds=30))

182

```

183

184

Relaxed validation:

185

```python

186

# Make time-based claims optional

187

header, claims = jwt.verify_jwt(token, pub_key, ['HS256'],

188

checks_optional=True)

189

```

190

191

### Token Processing

192

193

Extract header and claims from JWT without signature verification for inspection purposes.

194

195

```python { .api }

196

def process_jwt(jwt):

197

"""

198

Process a JWT without verifying it to extract header and claims.

199

200

Args:

201

jwt (str): The JWT to process

202

203

Returns:

204

tuple: (header, claims) containing parsed header and claims dictionaries

205

206

Raises:

207

Exception: If JWT format is invalid (must match pattern: header.payload.signature)

208

"""

209

```

210

211

Use this before `verify_jwt` when you need to examine token contents to determine verification parameters (e.g., selecting the appropriate public key based on issuer).

212

213

#### Usage Examples

214

215

Pre-verification inspection:

216

```python

217

# Examine token before verification

218

header, claims = jwt.process_jwt(token)

219

220

# Select appropriate key based on issuer

221

issuer = claims.get('iss')

222

if issuer == 'auth.example.com':

223

pub_key = load_example_key()

224

elif issuer == 'auth.other.com':

225

pub_key = load_other_key()

226

227

# Now verify with the correct key

228

verified_header, verified_claims = jwt.verify_jwt(token, pub_key, ['RS256'])

229

```

230

231

Algorithm inspection:

232

```python

233

# Check algorithm before verification

234

header, claims = jwt.process_jwt(token)

235

algorithm = header.get('alg')

236

237

# Use algorithm-specific key

238

if algorithm.startswith('RS'):

239

pub_key = rsa_public_key

240

elif algorithm.startswith('ES'):

241

pub_key = ecdsa_public_key

242

243

verified_header, verified_claims = jwt.verify_jwt(token, pub_key, [algorithm])

244

```

245

246

## Key Management

247

248

### PEM Key Import/Export

249

250

Work with PEM-format keys for interoperability with other systems.

251

252

```python

253

# Generate and export keys

254

key = jwk.JWK.generate(kty='RSA', size=2048)

255

priv_pem = key.export_to_pem(private_key=True, password=None)

256

pub_pem = key.export_to_pem()

257

258

# Import keys from PEM

259

priv_key = jwk.JWK.from_pem(priv_pem)

260

pub_key = jwk.JWK.from_pem(pub_pem)

261

262

# Use with JWT functions

263

token = jwt.generate_jwt(payload, priv_key, 'RS256', timedelta(hours=1))

264

header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])

265

```

266

267

### Key Types and Algorithms

268

269

Different key types support different signature algorithms:

270

271

```python

272

# RSA keys (RS256, RS384, RS512, PS256, PS384, PS512)

273

rsa_key = jwk.JWK.generate(kty='RSA', size=2048)

274

275

# ECDSA keys (ES256, ES384, ES512, ES256K)

276

ec_key = jwk.JWK.generate(kty='EC', curve='P-256') # For ES256

277

ec_key = jwk.JWK.generate(kty='EC', curve='P-384') # For ES384

278

ec_key = jwk.JWK.generate(kty='EC', curve='P-521') # For ES512

279

280

# EdDSA keys (EdDSA)

281

ed_key = jwk.JWK.generate(kty='OKP', curve='Ed25519')

282

283

# HMAC keys (HS256, HS384, HS512)

284

hmac_key = jwk.JWK.generate(kty='oct', size=256)

285

```

286

287

## Security Features

288

289

### Algorithm Verification

290

The library prevents algorithm confusion attacks by requiring explicit specification of allowed algorithms:

291

292

```python

293

# Secure: explicitly allow only specific algorithms

294

header, claims = jwt.verify_jwt(token, pub_key, ['PS256'])

295

296

# Insecure: never pass None or empty list for allowed_algs

297

# This would allow any algorithm, including 'none'

298

```

299

300

### Replay Attack Prevention

301

Generate unique token IDs (JTI) to detect and prevent replay attacks:

302

303

```python

304

# Default: 16-byte (128-bit) random JTI

305

token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1))

306

307

# Custom JTI size

308

token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1), jti_size=32)

309

310

# Omit JTI (not recommended for security)

311

token = jwt.generate_jwt(payload, key, 'RS256', timedelta(hours=1), jti_size=0)

312

```

313

314

### Time-based Validation

315

Comprehensive time-based claim validation with configurable clock skew:

316

317

```python

318

# Strict time validation (default)

319

header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])

320

321

# Allow clock skew for distributed systems

322

header, claims = jwt.verify_jwt(token, pub_key, ['RS256'],

323

iat_skew=timedelta(minutes=1))

324

```

325

326

## Exception Handling

327

328

The library may raise various exceptions during verification. Always wrap JWT operations in try-catch blocks:

329

330

```python

331

try:

332

header, claims = jwt.verify_jwt(token, pub_key, ['RS256'])

333

# Token is valid

334

user_id = claims['sub']

335

except Exception as e:

336

# Token verification failed

337

print(f"JWT verification failed: {e}")

338

# Handle invalid token (redirect to login, etc.)

339

```

340

341

## Complete Example

342

343

```python

344

import python_jwt as jwt

345

import jwcrypto.jwk as jwk

346

from datetime import datetime, timedelta

347

348

# Generate RSA key pair

349

key = jwk.JWK.generate(kty='RSA', size=2048)

350

351

# Create comprehensive payload

352

payload = {

353

'sub': '1234567890', # Subject (user ID)

354

'name': 'John Doe', # User name

355

'iss': 'auth.example.com', # Issuer

356

'aud': 'api.example.com', # Audience

357

'roles': ['admin', 'user'], # Custom claim

358

'permissions': ['read', 'write', 'delete']

359

}

360

361

try:

362

# Generate token with 1 hour expiration

363

token = jwt.generate_jwt(

364

payload,

365

key,

366

'PS256', # RSA-PSS with SHA-256

367

timedelta(hours=1),

368

jti_size=16 # 128-bit unique token ID

369

)

370

371

print(f"Generated token: {token[:50]}...")

372

373

# Verify the token

374

header, claims = jwt.verify_jwt(

375

token,

376

key,

377

['PS256'], # Only allow PS256 algorithm

378

iat_skew=timedelta(seconds=30) # 30-second clock skew tolerance

379

)

380

381

print("Token verification successful!")

382

print(f"Subject: {claims['sub']}")

383

print(f"Issued at: {datetime.utcfromtimestamp(claims['iat'])}")

384

print(f"Expires at: {datetime.utcfromtimestamp(claims['exp'])}")

385

print(f"Roles: {claims['roles']}")

386

387

except ValueError as e:

388

print(f"Token generation failed: {e}")

389

except Exception as e:

390

print(f"Token verification failed: {e}")

391

```

392

393

## Interoperability

394

395

The library is designed for interoperability with other JWT implementations and includes test coverage for compatibility with the jose JavaScript library. Tokens generated by python-jwt can be verified by other JWT libraries and vice versa, as long as they follow the JWT specification.