or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

common-utilities.mddjango-integration.mdflask-integration.mdhttp-clients.mdindex.mdjose.mdoauth1.mdoauth2.mdoidc.md

common-utilities.mddocs/

0

# Common Utilities

1

2

Shared utilities for encoding, security operations, URL handling, and error management used throughout the Authlib library. Provides consistent behavior, security best practices, and foundational functionality for all OAuth and JOSE operations.

3

4

## Capabilities

5

6

### Encoding and Serialization

7

8

Utilities for encoding, decoding, and serializing data in various formats used by OAuth and JOSE standards.

9

10

```python { .api }

11

def to_bytes(x: str, charset: str = "utf-8", errors: str = "strict") -> bytes:

12

"""

13

Convert string to bytes using specified encoding.

14

15

Args:

16

x: String to convert

17

charset: Character encoding to use

18

errors: Error handling strategy

19

20

Returns:

21

Bytes representation of the string

22

"""

23

24

def to_unicode(x, charset: str = "utf-8", errors: str = "strict") -> str:

25

"""

26

Convert bytes or string to unicode string.

27

28

Args:

29

x: Bytes or string to convert

30

charset: Character encoding to use

31

errors: Error handling strategy

32

33

Returns:

34

Unicode string representation

35

"""

36

37

def to_native(x, encoding: str = "ascii") -> str:

38

"""

39

Convert to native string type for the platform.

40

41

Args:

42

x: Input to convert

43

encoding: Character encoding to use

44

45

Returns:

46

Native string representation

47

"""

48

49

def json_loads(s: str) -> dict:

50

"""

51

Deserialize JSON string to Python object.

52

53

Args:

54

s: JSON string to deserialize

55

56

Returns:

57

Deserialized Python object

58

"""

59

60

def json_dumps(data: object, ensure_ascii: bool = False) -> str:

61

"""

62

Serialize Python object to JSON string.

63

64

Args:

65

data: Python object to serialize

66

ensure_ascii: Whether to escape non-ASCII characters

67

68

Returns:

69

JSON string representation

70

"""

71

72

def urlsafe_b64decode(s: str) -> bytes:

73

"""

74

Decode URL-safe base64 string.

75

76

Args:

77

s: URL-safe base64 string to decode

78

79

Returns:

80

Decoded bytes

81

"""

82

83

def urlsafe_b64encode(s: bytes) -> str:

84

"""

85

Encode bytes as URL-safe base64 string.

86

87

Args:

88

s: Bytes to encode

89

90

Returns:

91

URL-safe base64 string

92

"""

93

94

def base64_to_int(s: str) -> int:

95

"""

96

Convert base64 string to integer.

97

98

Args:

99

s: Base64 string representing an integer

100

101

Returns:

102

Integer value

103

"""

104

105

def int_to_base64(num: int) -> str:

106

"""

107

Convert integer to base64 string.

108

109

Args:

110

num: Integer to convert

111

112

Returns:

113

Base64 string representation

114

"""

115

116

def json_b64encode(text: str) -> str:

117

"""

118

JSON encode then base64 encode text.

119

120

Args:

121

text: Text to encode

122

123

Returns:

124

Base64-encoded JSON string

125

"""

126

```

127

128

### Security Utilities

129

130

Security functions for token generation, transport validation, and cryptographic operations.

131

132

```python { .api }

133

# Character set for token generation

134

UNICODE_ASCII_CHARACTER_SET: str

135

136

def generate_token(length: int = 30, chars: str = UNICODE_ASCII_CHARACTER_SET) -> str:

137

"""

138

Generate cryptographically secure random token.

139

140

Args:

141

length: Length of token to generate

142

chars: Character set to use for token generation

143

144

Returns:

145

Random token string

146

"""

147

148

def is_secure_transport(uri: str) -> bool:

149

"""

150

Check if URI uses secure transport (HTTPS).

151

152

Args:

153

uri: URI to check

154

155

Returns:

156

True if URI uses secure transport

157

"""

158

```

159

160

### URL Utilities

161

162

Comprehensive URL handling utilities for OAuth parameter encoding, decoding, and manipulation.

163

164

```python { .api }

165

def url_encode(params: dict) -> str:

166

"""

167

URL-encode parameters dictionary.

168

169

Args:

170

params: Dictionary of parameters to encode

171

172

Returns:

173

URL-encoded parameter string

174

"""

175

176

def url_decode(query: str) -> dict:

177

"""

178

URL-decode query string with validation.

179

180

Args:

181

query: Query string to decode

182

183

Returns:

184

Dictionary of decoded parameters

185

"""

186

187

def add_params_to_qs(query: str, params: dict) -> str:

188

"""

189

Add parameters to existing query string.

190

191

Args:

192

query: Existing query string

193

params: Parameters to add

194

195

Returns:

196

Updated query string

197

"""

198

199

def add_params_to_uri(uri: str, params: dict, fragment: bool = False) -> str:

200

"""

201

Add parameters to URI.

202

203

Args:

204

uri: Base URI

205

params: Parameters to add

206

fragment: Whether to add to fragment instead of query

207

208

Returns:

209

URI with added parameters

210

"""

211

212

def quote(s: str, safe: bytes = b"/") -> str:

213

"""

214

URL quote string with specified safe characters.

215

216

Args:

217

s: String to quote

218

safe: Characters to leave unquoted

219

220

Returns:

221

URL-quoted string

222

"""

223

224

def unquote(s: str) -> str:

225

"""

226

URL unquote string.

227

228

Args:

229

s: String to unquote

230

231

Returns:

232

Unquoted string

233

"""

234

235

def quote_url(s: str) -> str:

236

"""

237

Quote URL with extended safe characters for OAuth.

238

239

Args:

240

s: URL to quote

241

242

Returns:

243

Quoted URL string

244

"""

245

246

def extract_params(raw: object) -> dict:

247

"""

248

Extract parameters from various formats (dict, list, string).

249

250

Args:

251

raw: Raw parameter data

252

253

Returns:

254

Dictionary of extracted parameters

255

"""

256

257

def is_valid_url(url: str, fragments_allowed: bool = True) -> bool:

258

"""

259

Validate URL format.

260

261

Args:

262

url: URL to validate

263

fragments_allowed: Whether fragments (#) are allowed

264

265

Returns:

266

True if URL is valid

267

"""

268

```

269

270

### Error Handling

271

272

Comprehensive error handling classes for different OAuth and JOSE scenarios.

273

274

```python { .api }

275

class AuthlibBaseError(Exception):

276

"""

277

Base exception class for all Authlib errors.

278

279

Provides common error handling functionality for OAuth and JOSE operations.

280

"""

281

282

error: str = None

283

error_description: str = None

284

error_uri: str = None

285

286

def __init__(self, error: str = None, description: str = None, uri: str = None) -> None:

287

"""

288

Initialize base error.

289

290

Args:

291

error: Error code

292

description: Human-readable error description

293

uri: URI with error information

294

"""

295

296

class AuthlibHTTPError(AuthlibBaseError):

297

"""

298

HTTP-specific error class with status codes.

299

300

Used for OAuth and API errors that have HTTP status code semantics.

301

"""

302

303

status_code: int = 400

304

305

def __init__(self, error: str = None, description: str = None, uri: str = None, status_code: int = None) -> None:

306

"""

307

Initialize HTTP error.

308

309

Args:

310

error: Error code

311

description: Error description

312

uri: Error URI

313

status_code: HTTP status code

314

"""

315

316

class ContinueIteration(AuthlibBaseError):

317

"""

318

Special control flow exception for continuing iteration.

319

320

Used internally for flow control in OAuth grant processing.

321

"""

322

pass

323

```

324

325

### Request and Response Utilities

326

327

Utilities for handling HTTP requests and responses in OAuth flows.

328

329

```python { .api }

330

class OAuth2Request:

331

"""OAuth 2.0 request wrapper for framework-agnostic request handling."""

332

333

def __init__(self, method: str, uri: str, body: str = None, headers: dict = None) -> None:

334

"""

335

Initialize OAuth 2.0 request wrapper.

336

337

Args:

338

method: HTTP method

339

uri: Request URI

340

body: Request body

341

headers: HTTP headers dictionary

342

"""

343

344

class JsonRequest:

345

"""JSON request wrapper for API endpoints."""

346

347

def __init__(self, method: str, uri: str, body: str = None, headers: dict = None) -> None:

348

"""

349

Initialize JSON request wrapper.

350

351

Args:

352

method: HTTP method

353

uri: Request URI

354

body: JSON request body

355

headers: HTTP headers dictionary

356

"""

357

358

class OAuth2Payload:

359

"""OAuth 2.0 request payload wrapper."""

360

361

def __init__(self, params: dict = None) -> None:

362

"""

363

Initialize payload wrapper.

364

365

Args:

366

params: Payload parameters dictionary

367

"""

368

369

class JsonPayload:

370

"""JSON payload wrapper for structured data."""

371

372

def __init__(self, params: dict = None) -> None:

373

"""

374

Initialize JSON payload wrapper.

375

376

Args:

377

params: JSON payload parameters

378

"""

379

```

380

381

### Validation Utilities

382

383

Utilities for validating OAuth parameters, URIs, and other data.

384

385

```python { .api }

386

def validate_redirect_uri(redirect_uri: str, allowed_uris: list = None) -> bool:

387

"""

388

Validate OAuth redirect URI.

389

390

Args:

391

redirect_uri: Redirect URI to validate

392

allowed_uris: List of allowed redirect URIs

393

394

Returns:

395

True if redirect URI is valid

396

"""

397

398

def validate_scope(scope: str, allowed_scopes: list = None) -> bool:

399

"""

400

Validate OAuth scope parameter.

401

402

Args:

403

scope: Scope string to validate

404

allowed_scopes: List of allowed scopes

405

406

Returns:

407

True if scope is valid

408

"""

409

410

def validate_response_type(response_type: str, allowed_types: list = None) -> bool:

411

"""

412

Validate OAuth response type.

413

414

Args:

415

response_type: Response type to validate

416

allowed_types: List of allowed response types

417

418

Returns:

419

True if response type is valid

420

"""

421

422

def validate_grant_type(grant_type: str, allowed_grants: list = None) -> bool:

423

"""

424

Validate OAuth grant type.

425

426

Args:

427

grant_type: Grant type to validate

428

allowed_grants: List of allowed grant types

429

430

Returns:

431

True if grant type is valid

432

"""

433

```

434

435

## Usage Examples

436

437

### Token Generation

438

439

```python

440

from authlib.common.security import generate_token

441

442

# Generate random access token

443

access_token = generate_token(32)

444

print(f"Access token: {access_token}")

445

446

# Generate client secret

447

client_secret = generate_token(48)

448

print(f"Client secret: {client_secret}")

449

450

# Generate with custom character set

451

import string

452

alphanumeric = string.ascii_letters + string.digits

453

short_token = generate_token(16, alphanumeric)

454

print(f"Short token: {short_token}")

455

```

456

457

### URL Parameter Handling

458

459

```python

460

from authlib.common.urls import url_encode, url_decode, add_params_to_uri, is_valid_url

461

462

# Encode parameters for OAuth requests

463

params = {

464

'client_id': 'my-client-id',

465

'redirect_uri': 'https://example.com/callback',

466

'scope': 'read write',

467

'state': 'random-state-value'

468

}

469

query_string = url_encode(params)

470

print(f"Query string: {query_string}")

471

472

# Decode query string from callback

473

callback_query = "code=abc123&state=random-state-value"

474

decoded_params = url_decode(callback_query)

475

print(f"Decoded params: {decoded_params}")

476

477

# Add parameters to authorization URL

478

base_url = "https://provider.com/authorize"

479

auth_url = add_params_to_uri(base_url, params)

480

print(f"Authorization URL: {auth_url}")

481

482

# Validate redirect URIs

483

valid_uris = [

484

"https://example.com/callback",

485

"https://app.example.com/oauth/callback"

486

]

487

488

for uri in valid_uris:

489

if is_valid_url(uri):

490

print(f"Valid URI: {uri}")

491

```

492

493

### Encoding and Serialization

494

495

```python

496

from authlib.common.encoding import (

497

json_loads, json_dumps, urlsafe_b64encode, urlsafe_b64decode,

498

to_bytes, to_unicode

499

)

500

501

# JSON operations

502

data = {'user_id': 123, 'username': 'alice', 'scopes': ['read', 'write']}

503

json_string = json_dumps(data)

504

print(f"JSON: {json_string}")

505

506

parsed_data = json_loads(json_string)

507

print(f"Parsed: {parsed_data}")

508

509

# Base64 operations for JWT

510

payload = json_dumps(data)

511

payload_bytes = to_bytes(payload)

512

encoded_payload = urlsafe_b64encode(payload_bytes)

513

print(f"Base64 payload: {encoded_payload}")

514

515

# Decode

516

decoded_bytes = urlsafe_b64decode(encoded_payload)

517

decoded_string = to_unicode(decoded_bytes)

518

original_data = json_loads(decoded_string)

519

print(f"Original data: {original_data}")

520

```

521

522

### Error Handling

523

524

```python

525

from authlib.common.errors import AuthlibHTTPError, AuthlibBaseError

526

527

def validate_client_credentials(client_id, client_secret):

528

"""Example function that validates client credentials."""

529

530

if not client_id:

531

raise AuthlibHTTPError(

532

error='invalid_client',

533

description='Client ID is required',

534

status_code=400

535

)

536

537

if not client_secret:

538

raise AuthlibHTTPError(

539

error='invalid_client',

540

description='Client secret is required',

541

status_code=400

542

)

543

544

# Check credentials in database

545

client = get_client_by_id(client_id)

546

if not client or not client.check_secret(client_secret):

547

raise AuthlibHTTPError(

548

error='invalid_client',

549

description='Invalid client credentials',

550

status_code=401

551

)

552

553

return client

554

555

# Usage with error handling

556

try:

557

client = validate_client_credentials('client-id', 'wrong-secret')

558

except AuthlibHTTPError as error:

559

print(f"HTTP Error {error.status_code}: {error.error}")

560

print(f"Description: {error.error_description}")

561

except AuthlibBaseError as error:

562

print(f"Authlib Error: {error.error}")

563

```

564

565

### Security Validation

566

567

```python

568

from authlib.common.security import is_secure_transport

569

570

# Validate redirect URIs for security

571

redirect_uris = [

572

'https://example.com/callback', # Valid - HTTPS

573

'http://localhost:8080/callback', # Valid - localhost HTTP allowed

574

'http://example.com/callback', # Invalid - HTTP not allowed for production

575

'custom-app://oauth/callback' # Valid - custom scheme for mobile apps

576

]

577

578

for uri in redirect_uris:

579

if is_secure_transport(uri) or uri.startswith('http://localhost'):

580

print(f"✓ Secure: {uri}")

581

else:

582

print(f"✗ Insecure: {uri}")

583

```

584

585

### Request Wrapping

586

587

```python

588

from authlib.common.urls import extract_params

589

from authlib.oauth2 import OAuth2Request

590

591

# Create OAuth 2.0 request wrapper

592

def create_oauth_request(flask_request):

593

"""Convert Flask request to OAuth2Request."""

594

595

# Extract parameters from various sources

596

query_params = extract_params(flask_request.args)

597

form_params = extract_params(flask_request.form)

598

json_params = extract_params(flask_request.get_json() or {})

599

600

# Combine all parameters

601

all_params = {**query_params, **form_params, **json_params}

602

603

# Create OAuth request wrapper

604

oauth_request = OAuth2Request(

605

method=flask_request.method,

606

uri=flask_request.url,

607

body=flask_request.get_data(),

608

headers=dict(flask_request.headers)

609

)

610

611

# Add parsed parameters

612

oauth_request.data = all_params

613

614

return oauth_request

615

616

# Usage in Flask view

617

@app.route('/token', methods=['POST'])

618

def token_endpoint():

619

oauth_request = create_oauth_request(request)

620

621

# Process OAuth request

622

try:

623

response = authorization_server.create_token_response(oauth_request)

624

return response

625

except AuthlibHTTPError as error:

626

return {'error': error.error, 'error_description': error.error_description}, error.status_code

627

```

628

629

### Custom Validation

630

631

```python

632

def validate_oauth_parameters(request):

633

"""Validate common OAuth parameters."""

634

635

# Validate required parameters

636

required_params = ['client_id', 'response_type']

637

for param in required_params:

638

if not request.data.get(param):

639

raise AuthlibHTTPError(

640

error='invalid_request',

641

description=f'Missing required parameter: {param}'

642

)

643

644

# Validate redirect URI format

645

redirect_uri = request.data.get('redirect_uri')

646

if redirect_uri and not is_valid_url(redirect_uri):

647

raise AuthlibHTTPError(

648

error='invalid_request',

649

description='Invalid redirect URI format'

650

)

651

652

# Validate response type

653

response_type = request.data.get('response_type')

654

allowed_response_types = ['code', 'token', 'id_token']

655

if response_type not in allowed_response_types:

656

raise AuthlibHTTPError(

657

error='unsupported_response_type',

658

description=f'Response type "{response_type}" is not supported'

659

)

660

661

return True

662

663

# Usage in authorization endpoint

664

@app.route('/authorize')

665

def authorize():

666

oauth_request = create_oauth_request(request)

667

668

try:

669

validate_oauth_parameters(oauth_request)

670

# Continue with authorization flow

671

except AuthlibHTTPError as error:

672

return redirect(f"{oauth_request.data['redirect_uri']}?error={error.error}&error_description={error.error_description}")

673

```