or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

constants-algorithms.mdindex.mdjwe-operations.mdjwk-management.mdjws-operations.mdjwt-operations.md

jwt-operations.mddocs/

0

# JWT Operations

1

2

High-level JSON Web Token functionality providing comprehensive support for encoding, decoding, and validating JWT tokens with automatic claim validation, flexible key handling, and extensive configuration options.

3

4

## Capabilities

5

6

### Token Encoding

7

8

Creates JWT tokens from claims dictionaries with support for various signing algorithms and additional headers.

9

10

```python { .api }

11

def encode(claims, key, algorithm='HS256', headers=None, access_token=None):

12

"""

13

Encodes a claims set and returns a JWT string.

14

15

Args:

16

claims (dict): A claims set to sign. Can include standard claims

17

(iss, sub, aud, exp, nbf, iat, jti) and custom claims

18

key (str or bytes or dict): The key to use for signing. Supports:

19

- String secrets for HMAC algorithms

20

- RSA/EC private keys in PEM format

21

- JWK dictionaries

22

algorithm (str): The algorithm to use for signing. Defaults to 'HS256'.

23

Supported algorithms: HS256, HS384, HS512, RS256, RS384, RS512,

24

ES256, ES384, ES512

25

headers (dict, optional): Additional headers to include in the JWT header.

26

Will override default headers with the same keys

27

access_token (str, optional): If present, the 'at_hash' claim will be

28

calculated and added to the claims

29

30

Returns:

31

str: The JWT token string in the format header.payload.signature

32

33

Raises:

34

JWTError: If there is an error encoding the claims

35

"""

36

```

37

38

**Usage Examples:**

39

40

```python

41

from jose import jwt

42

from jose.constants import ALGORITHMS

43

44

# Basic HMAC signing

45

token = jwt.encode({'user': 'john', 'role': 'admin'}, 'secret', algorithm=ALGORITHMS.HS256)

46

47

# With expiration time

48

import time

49

claims = {

50

'user': 'jane',

51

'exp': int(time.time()) + 3600, # Expires in 1 hour

52

'iat': int(time.time()), # Issued now

53

'iss': 'my-app' # Issuer

54

}

55

token = jwt.encode(claims, 'secret')

56

57

# RSA signing with private key

58

rsa_private_key = """-----BEGIN PRIVATE KEY-----

59

MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...

60

-----END PRIVATE KEY-----"""

61

62

token = jwt.encode({'user': 'alice'}, rsa_private_key, algorithm=ALGORITHMS.RS256)

63

64

# With additional headers

65

headers = {'kid': 'key-1', 'typ': 'JWT'}

66

token = jwt.encode({'user': 'bob'}, 'secret', headers=headers)

67

68

# With access token hash for OpenID Connect

69

access_token = 'SlAV32hkKG'

70

token = jwt.encode({'user': 'charlie'}, 'secret', access_token=access_token)

71

```

72

73

### Token Decoding and Verification

74

75

Decodes and verifies JWT tokens with comprehensive claim validation and flexible verification options.

76

77

```python { .api }

78

def decode(token, key, algorithms=None, options=None, audience=None, issuer=None, subject=None, access_token=None):

79

"""

80

Decodes and verifies a JWT token.

81

82

Args:

83

token (str): The JWT token to decode

84

key (str or bytes or dict or list): The verification key(s). Supports:

85

- String secrets for HMAC algorithms

86

- RSA/EC public keys in PEM format

87

- JWK dictionaries

88

- List of keys to try multiple keys

89

algorithms (str or list): Allowed algorithms for verification. If None,

90

raises an error. Use specific algorithms like ['HS256'] for security

91

options (dict, optional): Verification options controlling which claims

92

to verify and validation behavior

93

audience (str, optional): Expected audience claim ('aud'). Token must

94

contain this exact audience value

95

issuer (str or list or tuple, optional): Expected issuer claim(s) ('iss').

96

Token issuer must match one of the provided values

97

subject (str, optional): Expected subject claim ('sub'). Token must

98

contain this exact subject value

99

access_token (str, optional): Access token for 'at_hash' verification

100

in OpenID Connect scenarios

101

102

Returns:

103

dict: The decoded payload claims

104

105

Raises:

106

JWTError: If the token is invalid or verification fails

107

ExpiredSignatureError: If the token has expired

108

JWTClaimsError: If claim validation fails

109

"""

110

```

111

112

**Verification Options:**

113

114

The `options` parameter accepts a dictionary with the following keys:

115

116

```python { .api }

117

# Default options

118

options = {

119

'verify_signature': True, # Verify the token signature

120

'verify_exp': True, # Verify expiration time claim

121

'verify_nbf': True, # Verify not before time claim

122

'verify_iat': True, # Verify issued at time claim

123

'verify_aud': True, # Verify audience claim

124

'verify_iss': True, # Verify issuer claim

125

'verify_sub': True, # Verify subject claim

126

'verify_jti': True, # Verify JWT ID claim

127

'require_exp': False, # Require exp claim to be present

128

'require_iat': False, # Require iat claim to be present

129

'require_nbf': False, # Require nbf claim to be present

130

'require_aud': False, # Require aud claim to be present

131

'require_iss': False, # Require iss claim to be present

132

'require_sub': False, # Require sub claim to be present

133

'require_jti': False, # Require jti claim to be present

134

'leeway': 0 # Leeway in seconds for time-based claims

135

}

136

```

137

138

**Usage Examples:**

139

140

```python

141

from jose import jwt

142

from jose.exceptions import ExpiredSignatureError, JWTError

143

from datetime import timedelta

144

145

# Basic verification

146

try:

147

claims = jwt.decode(token, 'secret', algorithms=['HS256'])

148

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

149

except JWTError as e:

150

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

151

152

# Verification with audience and issuer

153

claims = jwt.decode(

154

token,

155

'secret',

156

algorithms=['HS256'],

157

audience='my-app',

158

issuer='trusted-issuer'

159

)

160

161

# Verification with leeway for clock skew

162

options = {'leeway': 30} # 30 seconds leeway

163

claims = jwt.decode(token, 'secret', algorithms=['HS256'], options=options)

164

165

# Skip signature verification (for debugging only)

166

options = {'verify_signature': False}

167

claims = jwt.decode(token, 'secret', algorithms=['HS256'], options=options)

168

169

# Require specific claims

170

options = {

171

'require_exp': True,

172

'require_iss': True,

173

'require_aud': True

174

}

175

claims = jwt.decode(token, 'secret', algorithms=['HS256'], options=options)

176

177

# Multiple key verification (JWK set scenario)

178

keys = [

179

{'kty': 'oct', 'k': 'key1'},

180

{'kty': 'oct', 'k': 'key2'},

181

'backup-secret'

182

]

183

claims = jwt.decode(token, keys, algorithms=['HS256'])

184

185

# RSA public key verification

186

rsa_public_key = """-----BEGIN PUBLIC KEY-----

187

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...

188

-----END PUBLIC KEY-----"""

189

190

claims = jwt.decode(token, rsa_public_key, algorithms=['RS256'])

191

```

192

193

### Header and Claims Inspection

194

195

Retrieve JWT headers and claims without performing verification, useful for debugging and token inspection.

196

197

```python { .api }

198

def get_unverified_header(token):

199

"""

200

Get JWT header without verification.

201

202

Args:

203

token (str): The JWT token

204

205

Returns:

206

dict: The JWT header dictionary

207

208

Raises:

209

JWTError: If the token format is invalid

210

"""

211

212

def get_unverified_headers(token):

213

"""

214

Get JWT header without verification (alias for get_unverified_header).

215

216

Args:

217

token (str): The JWT token

218

219

Returns:

220

dict: The JWT header dictionary

221

222

Raises:

223

JWTError: If the token format is invalid

224

"""

225

226

def get_unverified_claims(token):

227

"""

228

Get JWT payload claims without verification.

229

230

Args:

231

token (str): The JWT token

232

233

Returns:

234

dict: The JWT payload claims dictionary

235

236

Raises:

237

JWTError: If the token format is invalid

238

"""

239

```

240

241

**Usage Examples:**

242

243

```python

244

# Inspect token header (useful for getting 'kid' for key selection)

245

header = jwt.get_unverified_header(token)

246

print(f"Algorithm: {header['alg']}")

247

print(f"Key ID: {header.get('kid')}")

248

249

# Inspect token claims (useful for debugging expired tokens)

250

claims = jwt.get_unverified_claims(token)

251

print(f"Issuer: {claims.get('iss')}")

252

print(f"Subject: {claims.get('sub')}")

253

print(f"Expires: {claims.get('exp')}")

254

255

# Conditional verification based on header

256

header = jwt.get_unverified_header(token)

257

if header['alg'] == 'HS256':

258

claims = jwt.decode(token, hmac_secret, algorithms=['HS256'])

259

elif header['alg'] == 'RS256':

260

claims = jwt.decode(token, rsa_public_key, algorithms=['RS256'])

261

```

262

263

## Standard JWT Claims

264

265

The JWT specification defines several standard claims:

266

267

```python { .api }

268

# Standard claims supported by python-jose

269

claims = {

270

'iss': 'issuer', # Issuer - who issued the token

271

'sub': 'subject', # Subject - who the token is about

272

'aud': 'audience', # Audience - who the token is intended for

273

'exp': 1234567890, # Expiration time (Unix timestamp)

274

'nbf': 1234567890, # Not before time (Unix timestamp)

275

'iat': 1234567890, # Issued at time (Unix timestamp)

276

'jti': 'unique-id', # JWT ID - unique identifier for the token

277

'at_hash': 'hash-value' # Access token hash (OpenID Connect)

278

}

279

```

280

281

## Error Handling

282

283

JWT operations can raise several specific exceptions:

284

285

```python { .api }

286

class JWTError(JOSEError):

287

"""Base exception for JWT-related errors."""

288

289

class JWTClaimsError(JWTError):

290

"""JWT claims validation failed."""

291

292

class ExpiredSignatureError(JWTError):

293

"""JWT token has expired."""

294

```

295

296

**Common Error Scenarios:**

297

298

```python

299

from jose import jwt

300

from jose.exceptions import JWTError, ExpiredSignatureError, JWTClaimsError

301

302

try:

303

claims = jwt.decode(token, key, algorithms=['HS256'], audience='my-app')

304

except ExpiredSignatureError:

305

# Token has expired (exp claim)

306

print("Token has expired")

307

except JWTClaimsError as e:

308

# Claims validation failed (aud, iss, sub, etc.)

309

print(f"Claims validation failed: {e}")

310

except JWTError as e:

311

# Other JWT errors (invalid format, signature, etc.)

312

print(f"JWT error: {e}")

313

```

314

315

## OpenID Connect Support

316

317

The library provides built-in support for OpenID Connect JWT features:

318

319

```python

320

# Access token hash calculation (at_hash claim)

321

access_token = 'SlAV32hkKG'

322

id_token = jwt.encode(

323

{'sub': '12345', 'aud': 'client-id'},

324

key,

325

access_token=access_token

326

)

327

328

# Verification includes at_hash validation

329

claims = jwt.decode(

330

id_token,

331

key,

332

algorithms=['HS256'],

333

access_token=access_token

334

)

335

```

336

337

## Best Practices

338

339

1. **Always specify algorithms**: Never use `algorithms=None` in production

340

2. **Use appropriate algorithms**: HS256 for symmetric keys, RS256/ES256 for asymmetric

341

3. **Validate claims**: Always verify `aud`, `iss`, and other relevant claims

342

4. **Handle expiration**: Use appropriate `exp` times and handle `ExpiredSignatureError`

343

5. **Clock skew**: Use `leeway` option to handle small time differences between systems

344

6. **Key management**: Rotate keys regularly and use `kid` header for key identification