or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

common-utilities.mddevice-flow.mderror-handling.mdindex.mdoauth1.mdoauth2-clients.mdoauth2-servers.mdopenid-connect.mdrequest-validation.mdtoken-management.md

oauth1.mddocs/

0

# OAuth 1.0 Implementation

1

2

Complete OAuth 1.0 (RFC 5849) client and server implementation supporting the full three-legged authentication flow. Includes request token acquisition, user authorization, access token exchange, and protected resource access with multiple signature methods.

3

4

## Capabilities

5

6

### OAuth 1.0 Client

7

8

OAuth 1.0 client for signing requests and managing the authentication flow. Supports multiple signature methods including HMAC-SHA1, HMAC-SHA256, HMAC-SHA512, RSA-SHA1, RSA-SHA256, RSA-SHA512, and PLAINTEXT.

9

10

```python { .api }

11

class Client:

12

def __init__(

13

self,

14

client_key: str,

15

client_secret: str | None = None,

16

resource_owner_key=None,

17

resource_owner_secret=None,

18

callback_uri=None,

19

signature_method: str = "HMAC-SHA1",

20

signature_type: str = "AUTH_HEADER",

21

rsa_key=None,

22

verifier=None,

23

realm=None,

24

encoding: str = "utf-8",

25

decoding=None,

26

nonce=None,

27

timestamp=None,

28

):

29

"""

30

OAuth 1.0 client for request signing and token management.

31

32

Parameters:

33

- client_key: Client identifier

34

- client_secret: Client secret for HMAC signatures

35

- resource_owner_key: Resource owner token (request or access token)

36

- resource_owner_secret: Resource owner token secret

37

- callback_uri: Callback URI for authorization

38

- signature_method: Signature method (HMAC-SHA1, RSA-SHA1, PLAINTEXT, etc.)

39

- signature_type: Where to place signature (AUTH_HEADER, QUERY, BODY)

40

- rsa_key: RSA private key for RSA signatures

41

- verifier: Authorization verifier code

42

- realm: Authorization realm

43

- encoding: String encoding

44

- nonce: Custom nonce generator

45

- timestamp: Custom timestamp generator

46

"""

47

48

def sign(

49

self,

50

uri: str,

51

http_method: str = "GET",

52

body: str | dict[str, str] | list[tuple[str, str]] | None = None,

53

headers: dict[str, str] | None = None,

54

realm=None,

55

):

56

"""

57

Sign an OAuth 1.0 request.

58

59

Parameters:

60

- uri: Request URI

61

- http_method: HTTP method (GET, POST, etc.)

62

- body: Request body

63

- headers: Request headers

64

- realm: Authorization realm

65

66

Returns:

67

Tuple of (uri, headers, body) with OAuth signature applied

68

"""

69

70

def get_oauth_signature(self, request):

71

"""Get OAuth signature for a request."""

72

73

def get_oauth_params(self, request):

74

"""Get OAuth parameters for a request."""

75

76

@classmethod

77

def register_signature_method(cls, method_name: str, method_callback):

78

"""Register a custom signature method."""

79

```

80

81

Usage example:

82

83

```python

84

from oauthlib.oauth1 import Client

85

86

# Create client with consumer credentials

87

client = Client(

88

'your-client-key',

89

client_secret='your-client-secret'

90

)

91

92

# Sign a request

93

uri, headers, body = client.sign(

94

'https://api.example.com/data',

95

http_method='GET'

96

)

97

98

# Make signed request

99

import requests

100

response = requests.get(uri, headers=headers)

101

```

102

103

### Request Token Endpoint

104

105

Server endpoint for handling OAuth 1.0 request token requests. Issues temporary credentials that clients use to obtain authorization from resource owners.

106

107

```python { .api }

108

class RequestTokenEndpoint:

109

def __init__(self, request_validator): ...

110

111

def create_request_token(self, request, credentials):

112

"""

113

Create a request token.

114

115

Parameters:

116

- request: OAuth request object

117

- credentials: Server credentials

118

119

Returns:

120

OAuth token dictionary

121

"""

122

123

def create_request_token_response(

124

self,

125

uri: str,

126

http_method: str = "GET",

127

body: str | None = None,

128

headers: dict[str, str] | None = None,

129

credentials: dict[str, str] | None = None,

130

):

131

"""Create request token endpoint response."""

132

133

def validate_request_token_request(self, request):

134

"""Validate request token request."""

135

```

136

137

### Authorization Endpoint

138

139

Server endpoint for handling OAuth 1.0 authorization requests. Manages user authorization and verifier code generation.

140

141

```python { .api }

142

class AuthorizationEndpoint:

143

def __init__(self, request_validator): ...

144

145

def create_verifier(self, request, credentials):

146

"""Create authorization verifier."""

147

148

def create_authorization_response(

149

self,

150

uri: str,

151

http_method: str = "GET",

152

body: str | None = None,

153

headers: dict[str, str] | None = None,

154

realms: list[str] | None = None,

155

credentials: dict[str, str] | None = None,

156

):

157

"""Create authorization endpoint response."""

158

159

def get_realms_and_credentials(

160

self,

161

uri: str,

162

http_method: str = "GET",

163

body: str | None = None,

164

headers: dict[str, str] | None = None,

165

):

166

"""Get authorization realms and credentials."""

167

```

168

169

### Access Token Endpoint

170

171

Server endpoint for handling OAuth 1.0 access token requests. Exchanges authorized request tokens for access tokens that can access protected resources.

172

173

```python { .api }

174

class AccessTokenEndpoint:

175

def __init__(self, request_validator): ...

176

177

def create_access_token(self, request, credentials):

178

"""Create an access token."""

179

180

def create_access_token_response(

181

self,

182

uri: str,

183

http_method: str = "GET",

184

body: str | None = None,

185

headers: dict[str, str] | None = None,

186

credentials: dict[str, str] | None = None,

187

):

188

"""Create access token endpoint response."""

189

190

def validate_access_token_request(self, request):

191

"""Validate access token request."""

192

```

193

194

### Resource Endpoint

195

196

Server endpoint for validating OAuth 1.0 signed requests to protected resources. Verifies access tokens and signatures before granting access to protected resources.

197

198

```python { .api }

199

class ResourceEndpoint:

200

def __init__(self, request_validator): ...

201

202

def validate_protected_resource_request(

203

self,

204

uri: str,

205

http_method: str = "GET",

206

body: str | None = None,

207

headers: dict[str, str] | None = None,

208

realms: list[str] | None = None,

209

) -> tuple[bool, dict]:

210

"""

211

Validate request to protected resource.

212

213

Returns:

214

Tuple of (valid, request) where valid is boolean and request contains OAuth params

215

"""

216

```

217

218

### Web Application Server

219

220

Pre-configured OAuth 1.0 server combining all endpoints for web application flows. Provides a complete server implementation with request token, authorization, access token, and resource protection capabilities.

221

222

```python { .api }

223

class WebApplicationServer:

224

def __init__(self, request_validator): ...

225

226

# Inherits all methods from RequestTokenEndpoint, AuthorizationEndpoint,

227

# AccessTokenEndpoint, and ResourceEndpoint

228

```

229

230

### Request Validator

231

232

OAuth 1.0 request validation interface that must be implemented to provide custom authentication and authorization logic. Handles client verification, token management, and security policies.

233

234

```python { .api }

235

class RequestValidator:

236

# Configuration properties

237

allowed_signature_methods: list[str]

238

safe_characters: set[str]

239

client_key_length: tuple[int, int]

240

request_token_length: tuple[int, int]

241

access_token_length: tuple[int, int]

242

timestamp_lifetime: int

243

nonce_length: tuple[int, int]

244

verifier_length: tuple[int, int]

245

realms: list[str]

246

enforce_ssl: bool

247

248

# Dummy values for timing attack protection

249

dummy_client: str

250

dummy_request_token: str

251

dummy_access_token: str

252

253

# Client validation

254

def validate_client_key(self, client_key: str, request) -> bool:

255

"""Validate client key exists and is valid."""

256

257

def check_client_key(self, client_key: str) -> bool:

258

"""Check client key format."""

259

260

def get_client_secret(self, client_key: str, request) -> str:

261

"""Get client secret for HMAC signatures."""

262

263

def get_rsa_key(self, client_key: str, request) -> str:

264

"""Get RSA public key for RSA signature verification."""

265

266

# Request token validation

267

def validate_request_token(self, client_key: str, token: str, request) -> bool:

268

"""Validate request token."""

269

270

def check_request_token(self, request_token: str) -> bool:

271

"""Check request token format."""

272

273

def get_request_token_secret(self, client_key: str, token: str, request) -> str:

274

"""Get request token secret."""

275

276

def save_request_token(self, token: dict, request) -> None:

277

"""Store request token."""

278

279

def invalidate_request_token(self, client_key: str, request_token: str, request) -> None:

280

"""Invalidate used request token."""

281

282

# Access token validation

283

def validate_access_token(self, client_key: str, token: str, request) -> bool:

284

"""Validate access token."""

285

286

def check_access_token(self, access_token: str) -> bool:

287

"""Check access token format."""

288

289

def get_access_token_secret(self, client_key: str, token: str, request) -> str:

290

"""Get access token secret."""

291

292

def save_access_token(self, token: dict, request) -> None:

293

"""Store access token."""

294

295

# Authorization validation

296

def validate_timestamp_and_nonce(

297

self,

298

client_key: str,

299

timestamp: str,

300

nonce: str,

301

request_token: str = None,

302

access_token: str = None,

303

) -> bool:

304

"""Validate timestamp and nonce to prevent replay attacks."""

305

306

def validate_redirect_uri(self, client_key: str, redirect_uri: str, request) -> bool:

307

"""Validate redirect URI."""

308

309

def validate_verifier(self, client_key: str, token: str, verifier: str, request) -> bool:

310

"""Validate authorization verifier."""

311

312

def save_verifier(self, token: str, verifier: str, request) -> None:

313

"""Store authorization verifier."""

314

315

def get_redirect_uri(self, token: str, request) -> str:

316

"""Get redirect URI for token."""

317

318

# Realm validation

319

def validate_requested_realms(self, client_key: str, realms: list[str], request) -> bool:

320

"""Validate requested authorization realms."""

321

322

def validate_realms(

323

self,

324

client_key: str,

325

token: str,

326

request,

327

uri: str = None,

328

realms: list[str] = None,

329

) -> bool:

330

"""Validate access to realms."""

331

332

def get_default_realms(self, client_key: str, request) -> list[str]:

333

"""Get default realms for client."""

334

335

def get_realms(self, token: str, request) -> list[str]:

336

"""Get realms associated with token."""

337

338

def check_realms(self, realms: list[str]) -> bool:

339

"""Check realm format."""

340

341

# Format checking

342

def check_nonce(self, nonce: str) -> bool:

343

"""Check nonce format."""

344

345

def check_verifier(self, verifier: str) -> bool:

346

"""Check verifier format."""

347

```

348

349

### Signature Methods

350

351

OAuth 1.0 signature method implementations for request authentication. Supports HMAC-based and RSA-based signatures with multiple hash algorithms.

352

353

```python { .api }

354

# Signature base string creation

355

def signature_base_string(

356

http_method: str,

357

base_str_uri: str,

358

normalized_encoded_request_parameters: str,

359

) -> str:

360

"""Create OAuth 1.0 signature base string."""

361

362

def base_string_uri(uri: str, host: str = None) -> str:

363

"""Normalize URI for signature base string."""

364

365

def collect_parameters(

366

uri_query: str = "",

367

body: str | None = None,

368

headers: dict[str, str] | None = None,

369

exclude_oauth_signature: bool = True,

370

with_realm: bool = False,

371

) -> list[tuple[str, str]]:

372

"""Collect OAuth parameters for signature."""

373

374

def normalize_parameters(params: list[tuple[str, str]]) -> str:

375

"""Normalize parameters for signature base string."""

376

377

# HMAC signature methods

378

def sign_hmac_sha1(base_string: str, client_secret: str, resource_owner_secret: str) -> str:

379

"""Sign with HMAC-SHA1."""

380

381

def verify_hmac_sha1(

382

request,

383

client_secret: str = None,

384

resource_owner_secret: str = None,

385

) -> bool:

386

"""Verify HMAC-SHA1 signature."""

387

388

def sign_hmac_sha256(base_string: str, client_secret: str, resource_owner_secret: str) -> str:

389

"""Sign with HMAC-SHA256."""

390

391

def verify_hmac_sha256(

392

request,

393

client_secret: str = None,

394

resource_owner_secret: str = None,

395

) -> bool:

396

"""Verify HMAC-SHA256 signature."""

397

398

def sign_hmac_sha512(base_string: str, client_secret: str, resource_owner_secret: str) -> str:

399

"""Sign with HMAC-SHA512."""

400

401

def verify_hmac_sha512(

402

request,

403

client_secret: str = None,

404

resource_owner_secret: str = None,

405

) -> bool:

406

"""Verify HMAC-SHA512 signature."""

407

408

# RSA signature methods

409

def sign_rsa_sha1(base_string: str, rsa_private_key: str) -> str:

410

"""Sign with RSA-SHA1."""

411

412

def verify_rsa_sha1(request, rsa_public_key: str) -> bool:

413

"""Verify RSA-SHA1 signature."""

414

415

def sign_rsa_sha256(base_string: str, rsa_private_key: str) -> str:

416

"""Sign with RSA-SHA256."""

417

418

def verify_rsa_sha256(request, rsa_public_key: str) -> bool:

419

"""Verify RSA-SHA256 signature."""

420

421

def sign_rsa_sha512(base_string: str, rsa_private_key: str) -> str:

422

"""Sign with RSA-SHA512."""

423

424

def verify_rsa_sha512(request, rsa_public_key: str) -> bool:

425

"""Verify RSA-SHA512 signature."""

426

427

# Plaintext signature method

428

def sign_plaintext(client_secret: str, resource_owner_secret: str) -> str:

429

"""Sign with PLAINTEXT method."""

430

431

def verify_plaintext(

432

request,

433

client_secret: str = None,

434

resource_owner_secret: str = None,

435

) -> bool:

436

"""Verify PLAINTEXT signature."""

437

```

438

439

### Parameter Utilities

440

441

OAuth 1.0 parameter formatting and preparation utilities for different signature placement methods.

442

443

```python { .api }

444

def prepare_headers(

445

params: list[tuple[str, str]],

446

headers: dict[str, str] | None = None,

447

realm: str | None = None,

448

) -> dict[str, str]:

449

"""Prepare OAuth parameters for Authorization header."""

450

451

def prepare_form_encoded_body(

452

oauth_params: list[tuple[str, str]],

453

body: str | list[tuple[str, str]],

454

) -> str:

455

"""Prepare OAuth parameters for form-encoded body."""

456

457

def prepare_request_uri_query(

458

oauth_params: list[tuple[str, str]],

459

uri: str,

460

) -> str:

461

"""Prepare OAuth parameters for URI query string."""

462

```

463

464

### Utility Functions

465

466

OAuth 1.0 utility functions for parameter handling, URL encoding, and header parsing.

467

468

```python { .api }

469

def filter_oauth_params(params: list[tuple[str, str]]) -> list[str]:

470

"""Filter OAuth-specific parameters."""

471

472

def escape(u: str) -> str:

473

"""URL escape string for OAuth."""

474

475

def unescape(u: str) -> str:

476

"""URL unescape string."""

477

478

def parse_authorization_header(authorization_header: str) -> list[tuple[str, str]]:

479

"""Parse OAuth Authorization header."""

480

481

def parse_http_list(u: str) -> list[str]:

482

"""Parse HTTP list format."""

483

484

def parse_keqv_list(l: list[str]) -> dict[str, str]:

485

"""Parse key=value list format."""

486

487

def filter_params(target: list[str]) -> callable:

488

"""Create parameter filter function."""

489

```

490

491

## Constants

492

493

```python { .api }

494

# Signature methods

495

SIGNATURE_HMAC_SHA1: str

496

SIGNATURE_HMAC_SHA256: str

497

SIGNATURE_HMAC_SHA512: str

498

SIGNATURE_HMAC: str

499

SIGNATURE_RSA_SHA1: str

500

SIGNATURE_RSA_SHA256: str

501

SIGNATURE_RSA_SHA512: str

502

SIGNATURE_RSA: str

503

SIGNATURE_PLAINTEXT: str

504

505

# Signature placement

506

SIGNATURE_TYPE_AUTH_HEADER: str

507

SIGNATURE_TYPE_QUERY: str

508

SIGNATURE_TYPE_BODY: str

509

510

# Content type

511

CONTENT_TYPE_FORM_URLENCODED: str

512

```

513

514

## Exceptions

515

516

```python { .api }

517

class OAuth1Error(Exception):

518

"""Base OAuth 1.0 exception."""

519

error: str

520

description: str

521

uri: str | None

522

status_code: int

523

524

def __init__(

525

self,

526

description: str | None = None,

527

uri: str | None = None,

528

status_code: int = 400,

529

request=None,

530

) -> None: ...

531

532

def in_uri(self, uri: str) -> str: ...

533

534

@property

535

def twotuples(self) -> list[tuple[str, str]]: ...

536

537

@property

538

def urlencoded(self) -> str: ...

539

540

class InsecureTransportError(OAuth1Error):

541

"""HTTPS transport required."""

542

error: str

543

description: str

544

545

class InvalidSignatureMethodError(OAuth1Error):

546

"""Invalid signature method."""

547

error: str

548

549

class InvalidRequestError(OAuth1Error):

550

"""Invalid OAuth request."""

551

error: str

552

553

class InvalidClientError(OAuth1Error):

554

"""Invalid client credentials."""

555

error: str

556

```