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

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

To install, run

npx @tessl/cli install tessl/pypi-python-jwt@3.3.0

0

# python-jwt

1

2

python-jwt is a comprehensive Python library for generating and verifying JSON Web Tokens (JWT). It provides secure token generation and verification for authentication and authorization systems with support for multiple signature algorithms including RSA, PSS, ECDSA, HMAC, EdDSA, and none. The library leverages jwcrypto for cryptographic operations and includes built-in security features to prevent common JWT vulnerabilities.

3

4

## Package Information

5

6

- **Package Name**: python_jwt

7

- **Package Type**: pypi

8

- **Language**: Python

9

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

10

11

## Core Imports

12

13

```python

14

import python_jwt as jwt

15

```

16

17

Alternative direct imports:

18

```python

19

from python_jwt import generate_jwt, verify_jwt, process_jwt

20

```

21

22

## Basic Usage

23

24

```python

25

import python_jwt as jwt

26

import jwcrypto.jwk as jwk

27

from datetime import timedelta

28

29

# Generate a key for signing

30

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

31

32

# Create JWT claims

33

payload = {'user_id': 123, 'role': 'admin'}

34

35

# Generate a JWT token

36

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

37

38

# Verify the JWT token

39

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

40

41

# Access the claims

42

print(f"User ID: {claims['user_id']}")

43

print(f"Role: {claims['role']}")

44

```

45

46

## Capabilities

47

48

### Token Generation

49

50

Generate JSON Web Tokens with customizable claims, expiration, and signature algorithms.

51

52

```python { .api }

53

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

54

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

55

"""

56

Generate a JSON Web Token.

57

58

Parameters:

59

- claims (dict): The claims you want included in the signature

60

- priv_key (jwcrypto.jwk.JWK, optional): The private key to be used to sign the token.

61

If None, token will be returned with empty signature and algorithm will be 'none'

62

- algorithm (str): The algorithm to use for generating the signature.

63

Supported: RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512,

64

ES256K, HS256, HS384, HS512, EdDSA, none. Default: 'PS512'

65

- lifetime (datetime.timedelta, optional): How long the token is valid for

66

- expires (datetime.datetime, optional): When the token expires (alternative to lifetime)

67

- not_before (datetime.datetime, optional): When the token is valid from.

68

Defaults to current time if None

69

- jti_size (int): Size in bytes of the unique token ID. Default: 16.

70

Specify 0 or None to omit JTI from token

71

- other_headers (dict, optional): Additional headers (cannot override 'typ' or 'alg')

72

73

Returns:

74

str: The JSON Web Token with header, claims, and cryptographic signature

75

76

Raises:

77

ValueError: If other_headers contains 'typ' or 'alg' headers

78

79

Note:

80

The following claims are automatically added per JWT spec:

81

- exp (IntDate): UTC expiry date and time in seconds since epoch

82

- iat (IntDate): UTC date and time when token was generated

83

- nbf (IntDate): UTC valid-from date and time

84

- jti (str): Unique identifier for the token (if jti_size > 0)

85

"""

86

```

87

88

#### Usage Examples

89

90

Basic token generation:

91

```python

92

import python_jwt as jwt

93

import jwcrypto.jwk as jwk

94

from datetime import timedelta

95

96

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

97

claims = {'user': 'alice', 'permissions': ['read', 'write']}

98

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

99

```

100

101

Token with custom expiration:

102

```python

103

from datetime import datetime, timedelta

104

105

expires_at = datetime.utcnow() + timedelta(days=7)

106

token = jwt.generate_jwt(claims, key, 'PS256', expires=expires_at)

107

```

108

109

Unsigned token (algorithm 'none'):

110

```python

111

# For testing or when signature verification is handled elsewhere

112

token = jwt.generate_jwt(claims, None, 'none')

113

```

114

115

Token with additional headers:

116

```python

117

extra_headers = {'kid': 'key-123', 'custom': 'value'}

118

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

119

other_headers=extra_headers)

120

```

121

122

### Token Verification

123

124

Verify and decode JSON Web Tokens with comprehensive security checks.

125

126

```python { .api }

127

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

128

checks_optional=False, ignore_not_implemented=False):

129

"""

130

Verify a JSON Web Token.

131

132

Parameters:

133

- jwt (str): The JSON Web Token to verify

134

- pub_key (jwcrypto.jwk.JWK, optional): The public key to be used to verify the token.

135

If None and 'none' in allowed_algs, signature will not be verified

136

- allowed_algs (list, optional): Algorithms expected to be used to sign the token.

137

Uses 'in' operator to test membership. None means empty list

138

- iat_skew (datetime.timedelta): Amount of leeway between issuer's and verifier's

139

clock when verifying token was generated in the past. Default: no leeway

140

- checks_optional (bool): If False, token must contain 'typ' header and

141

'iat', 'nbf', 'exp' claim properties. Default: False

142

- ignore_not_implemented (bool): If False, token must not contain 'jku',

143

'jwk', 'x5u', 'x5c', or 'x5t' header properties. Default: False

144

145

Returns:

146

tuple: (header, claims) if token was verified successfully

147

148

Raises:

149

Various exceptions: If token failed to verify

150

151

Verification Tests:

152

- Header must contain 'alg' property with value in allowed_algs

153

- Signature must verify using pub_key (unless algorithm is 'none' and 'none' in allowed_algs)

154

- If corresponding property is present or checks_optional is False:

155

- Header must contain 'typ' property with value 'JWT'

156

- Claims must contain 'iat' property representing date in past (with iat_skew tolerance)

157

- Claims must contain 'nbf' property representing date in the past

158

- Claims must contain 'exp' property representing date in the future

159

"""

160

```

161

162

#### Usage Examples

163

164

Basic token verification:

165

```python

166

try:

167

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

168

print(f"Token valid. User: {claims.get('user')}")

169

except Exception as e:

170

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

171

```

172

173

Verification with multiple allowed algorithms:

174

```python

175

# Allow multiple signature algorithms

176

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

177

```

178

179

Verification with clock skew tolerance:

180

```python

181

from datetime import timedelta

182

183

# Allow 5 minutes of clock skew

184

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

185

iat_skew=timedelta(minutes=5))

186

```

187

188

Verification with optional checks:

189

```python

190

# Skip strict validation of standard claims

191

header, claims = jwt.verify_jwt(token, key, ['HS256'], checks_optional=True)

192

```

193

194

### Token Processing

195

196

Process JWT tokens without verification to inspect headers and claims.

197

198

```python { .api }

199

def process_jwt(jwt):

200

"""

201

Process a JSON Web Token without verifying it.

202

203

Call this before verify_jwt if you need access to the header or claims

204

in the token before verifying it. For example, the claims might identify

205

the issuer such that you can retrieve the appropriate public key.

206

207

Parameters:

208

- jwt (str): The JSON Web Token to process

209

210

Returns:

211

tuple: (header, claims)

212

213

Raises:

214

_JWTError: If JWT format is invalid

215

"""

216

```

217

218

#### Usage Examples

219

220

Inspect token before verification:

221

```python

222

# Get issuer from claims to determine which key to use

223

header, claims = jwt.process_jwt(token)

224

issuer = claims.get('iss')

225

226

# Select appropriate key based on issuer

227

if issuer == 'service-a':

228

verification_key = service_a_key

229

elif issuer == 'service-b':

230

verification_key = service_b_key

231

else:

232

raise ValueError(f"Unknown issuer: {issuer}")

233

234

# Now verify with appropriate key

235

header, verified_claims = jwt.verify_jwt(token, verification_key, ['RS256'])

236

```

237

238

Debug token contents:

239

```python

240

try:

241

header, claims = jwt.process_jwt(token)

242

print(f"Algorithm: {header.get('alg')}")

243

print(f"Claims: {claims}")

244

except Exception as e:

245

print(f"Invalid JWT format: {e}")

246

```

247

248

## Supported Algorithms

249

250

The library supports the following JWT signature algorithms:

251

252

- **RSA**: RS256, RS384, RS512 - RSA PKCS#1 signature with SHA-256/384/512

253

- **PSS**: PS256, PS384, PS512 - RSA PSS signature with SHA-256/384/512

254

- **ECDSA**: ES256, ES384, ES512, ES256K - ECDSA signature with various curves

255

- **HMAC**: HS256, HS384, HS512 - HMAC with SHA-256/384/512

256

- **EdDSA**: EdDSA - Edwards-curve Digital Signature Algorithm

257

- **None**: none - Unsigned tokens (use with caution)

258

259

## Standard JWT Claims

260

261

The library automatically handles these standard JWT claims:

262

263

- **exp** (expiration time): Automatically added when `lifetime` or `expires` specified

264

- **iat** (issued at): Automatically added during token generation

265

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

266

- **jti** (JWT ID): Added if `jti_size` > 0 (default 16 bytes, base64url encoded)

267

268

## Key Management Integration

269

270

python-jwt integrates with jwcrypto for key management:

271

272

```python

273

import jwcrypto.jwk as jwk

274

275

# Generate keys

276

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

277

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

278

279

# Load from PEM

280

private_pem = "-----BEGIN PRIVATE KEY-----\n..."

281

private_key = jwk.JWK.from_pem(private_pem.encode())

282

283

public_pem = "-----BEGIN PUBLIC KEY-----\n..."

284

public_key = jwk.JWK.from_pem(public_pem.encode())

285

286

# Export to PEM

287

private_pem = rsa_key.export_to_pem(private_key=True, password=None)

288

public_pem = rsa_key.export_to_pem(private_key=False)

289

```

290

291

## Error Handling

292

293

The library raises various exceptions during token operations:

294

295

- **ValueError**: For invalid parameters (e.g., conflicting headers in `other_headers`)

296

- **jwcrypto exceptions**: For cryptographic failures during signing/verification

297

- **_JWTError**: Internal JWT-specific validation failures (format, claims, algorithms)

298

299

```python { .api }

300

class _JWTError(Exception):

301

"""

302

Exception raised for JWT-specific validation failures.

303

304

This is a private exception class used internally by python-jwt

305

for JWT format validation, claims verification, and algorithm checks.

306

Applications should catch general Exception or specific jwcrypto

307

exceptions rather than relying on this internal exception type.

308

"""

309

```

310

311

Common error scenarios:

312

```python

313

try:

314

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

315

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

316

except ValueError as e:

317

print(f"Invalid parameters: {e}")

318

except Exception as e:

319

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

320

```

321

322

## Security Considerations

323

324

- **Algorithm specification**: Always specify `allowed_algs` in verification to prevent algorithm confusion attacks

325

- **Key management**: Use appropriate key sizes (RSA 2048+ bits, EC P-256+ curves)

326

- **Clock skew**: Consider `iat_skew` parameter for distributed systems

327

- **Token lifetime**: Use reasonable expiration times to limit exposure

328

- **Signature verification**: Never skip signature verification in production (avoid 'none' algorithm)

329

- **Unique identifiers**: Use `jti` parameter to detect replay attacks when needed