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

oauth1.mddocs/

0

# OAuth 1.0 Implementation

1

2

Complete OAuth 1.0 implementation following RFC 5849 with support for all signature methods (HMAC-SHA1, RSA-SHA1, PLAINTEXT) and signature types (header, query, body). Provides both client and server implementations with comprehensive support for temporary credentials and token credentials.

3

4

## Capabilities

5

6

### OAuth 1.0 Client

7

8

High-level OAuth 1.0 client implementation for performing the complete authorization flow with automatic signature generation and request signing.

9

10

```python { .api }

11

class OAuth1Client:

12

"""OAuth 1.0 client implementation."""

13

14

def __init__(self, client_key: str, client_secret: str = None, token: str = None, token_secret: str = None, redirect_uri: str = None, rsa_key=None, verifier: str = None, signature_method: str = 'HMAC-SHA1', signature_type: str = 'AUTH_HEADER', force_include_body: bool = False, **kwargs) -> None:

15

"""

16

Initialize OAuth 1.0 client.

17

18

Args:

19

client_key: Client identifier

20

client_secret: Client secret (not needed for RSA-SHA1)

21

token: OAuth token

22

token_secret: OAuth token secret

23

redirect_uri: Callback URI for authorization

24

rsa_key: RSA private key for RSA-SHA1 signature method

25

verifier: OAuth verifier from authorization callback

26

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

27

signature_type: Where to include signature (AUTH_HEADER, QUERY, BODY)

28

force_include_body: Whether to always include body in signature

29

"""

30

31

def fetch_request_token(self, uri: str, realm: str = None) -> dict:

32

"""

33

Fetch temporary credentials (request token).

34

35

Args:

36

uri: Request token endpoint URI

37

realm: Optional authorization realm

38

39

Returns:

40

Dictionary containing oauth_token and oauth_token_secret

41

"""

42

43

def create_authorization_url(self, uri: str, **request_kwargs) -> str:

44

"""

45

Create authorization URL for user to visit.

46

47

Args:

48

uri: Authorization endpoint URI

49

**request_kwargs: Additional parameters for authorization

50

51

Returns:

52

Authorization URL with embedded token

53

"""

54

55

def fetch_access_token(self, uri: str, verifier: str = None) -> dict:

56

"""

57

Exchange authorization verifier for access token.

58

59

Args:

60

uri: Access token endpoint URI

61

verifier: OAuth verifier from authorization callback

62

63

Returns:

64

Dictionary containing oauth_token and oauth_token_secret

65

"""

66

67

def get_request_token_authorization_url(self, url: str, **request_kwargs) -> str:

68

"""Get authorization URL (alias for create_authorization_url)."""

69

70

def parse_authorization_response(self, url: str) -> dict:

71

"""

72

Parse authorization callback response.

73

74

Args:

75

url: Callback URL with parameters

76

77

Returns:

78

Dictionary with parsed parameters

79

"""

80

```

81

82

### OAuth 1.0 Server Components

83

84

Server-side components for implementing OAuth 1.0 authorization and resource servers.

85

86

```python { .api }

87

class AuthorizationServer:

88

"""OAuth 1.0 authorization server."""

89

90

def __init__(self, query_client: callable, query_token: callable, save_request_token: callable, save_verifier: callable, save_access_token: callable) -> None:

91

"""

92

Initialize authorization server.

93

94

Args:

95

query_client: Function to query client by client_key

96

query_token: Function to query token by token value

97

save_request_token: Function to save temporary credentials

98

save_verifier: Function to save authorization verifier

99

save_access_token: Function to save access token

100

"""

101

102

def create_request_token_response(self, uri: str, http_method: str = 'POST', body: str = None, headers: dict = None) -> tuple:

103

"""

104

Create response for request token endpoint.

105

106

Args:

107

uri: Request URI

108

http_method: HTTP method

109

body: Request body

110

headers: Request headers

111

112

Returns:

113

Tuple of (headers, body, status_code)

114

"""

115

116

def create_authorization_response(self, uri: str, http_method: str = 'GET', body: str = None, headers: dict = None, credentials: dict = None) -> tuple:

117

"""

118

Create response for authorization endpoint.

119

120

Args:

121

uri: Request URI

122

http_method: HTTP method

123

body: Request body

124

headers: Request headers

125

credentials: User credentials dictionary

126

127

Returns:

128

Tuple of (headers, body, status_code)

129

"""

130

131

def create_access_token_response(self, uri: str, http_method: str = 'POST', body: str = None, headers: dict = None, credentials: dict = None) -> tuple:

132

"""

133

Create response for access token endpoint.

134

135

Args:

136

uri: Request URI

137

http_method: HTTP method

138

body: Request body

139

headers: Request headers

140

credentials: Optional user credentials

141

142

Returns:

143

Tuple of (headers, body, status_code)

144

"""

145

146

def validate_request_token_request(self, request: OAuth1Request) -> None:

147

"""Validate request token request."""

148

149

def validate_authorization_request(self, request: OAuth1Request) -> None:

150

"""Validate authorization request."""

151

152

def validate_access_token_request(self, request: OAuth1Request) -> None:

153

"""Validate access token request."""

154

155

class ResourceProtector:

156

"""OAuth 1.0 resource server protection."""

157

158

def __init__(self, query_client: callable, query_token: callable) -> None:

159

"""

160

Initialize resource protector.

161

162

Args:

163

query_client: Function to query client by client_key

164

query_token: Function to query token by token value

165

"""

166

167

def validate_request(self, uri: str, http_method: str, body: str = None, headers: dict = None) -> OAuth1Request:

168

"""

169

Validate OAuth 1.0 signed request.

170

171

Args:

172

uri: Request URI

173

http_method: HTTP method

174

body: Request body

175

headers: Request headers

176

177

Returns:

178

Validated OAuth1Request object

179

"""

180

```

181

182

### Request Wrapper

183

184

OAuth 1.0 request representation with signature validation capabilities.

185

186

```python { .api }

187

class OAuth1Request:

188

"""OAuth 1.0 request wrapper."""

189

190

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

191

"""

192

Initialize OAuth 1.0 request.

193

194

Args:

195

uri: Request URI

196

http_method: HTTP method

197

body: Request body

198

headers: Request headers

199

"""

200

201

@property

202

def client_key(self) -> str:

203

"""Get client key from request."""

204

205

@property

206

def signature(self) -> str:

207

"""Get signature from request."""

208

209

@property

210

def signature_method(self) -> str:

211

"""Get signature method from request."""

212

213

@property

214

def token(self) -> str:

215

"""Get token from request."""

216

217

def validate_timestamp_and_nonce(self, timestamp_lifetime: int = 600) -> None:

218

"""

219

Validate timestamp and nonce.

220

221

Args:

222

timestamp_lifetime: Maximum age of timestamp in seconds

223

"""

224

225

def validate_signature(self, client_secret: str, token_secret: str = '', rsa_key=None) -> None:

226

"""

227

Validate request signature.

228

229

Args:

230

client_secret: Client secret

231

token_secret: Token secret

232

rsa_key: RSA public key for RSA-SHA1 verification

233

"""

234

```

235

236

### Client Authentication

237

238

OAuth 1.0 client authentication for use with HTTP libraries.

239

240

```python { .api }

241

class ClientAuth:

242

"""OAuth 1.0 client authentication."""

243

244

def __init__(self, client_key: str, client_secret: str = None, token: str = None, token_secret: str = None, signature_method: str = 'HMAC-SHA1', signature_type: str = 'AUTH_HEADER', rsa_key=None, verifier: str = None, **kwargs) -> None:

245

"""

246

Initialize client authentication.

247

248

Args:

249

client_key: Client identifier

250

client_secret: Client secret

251

token: OAuth token

252

token_secret: OAuth token secret

253

signature_method: Signature method

254

signature_type: Signature type

255

rsa_key: RSA private key

256

verifier: OAuth verifier

257

"""

258

259

def __call__(self, request) -> object:

260

"""

261

Apply OAuth 1.0 signature to request.

262

263

Args:

264

request: HTTP request object

265

266

Returns:

267

Modified request with OAuth signature

268

"""

269

```

270

271

### Model Mixins

272

273

Mixins for database models to store OAuth 1.0 credentials.

274

275

```python { .api }

276

class ClientMixin:

277

"""Mixin for OAuth 1.0 client model."""

278

279

client_key: str # Client identifier

280

client_secret: str # Client secret (may be None for RSA-SHA1)

281

default_redirect_uri: str # Default callback URI

282

default_realms: list # Default authorization realms

283

284

def get_default_redirect_uri(self) -> str:

285

"""Get default redirect URI for this client."""

286

287

def get_default_realms(self) -> list:

288

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

289

290

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

291

"""Validate if redirect URI is allowed for this client."""

292

293

class TemporaryCredentialMixin:

294

"""Mixin for temporary credential (request token) model."""

295

296

client_key: str # Client identifier

297

oauth_token: str # Temporary token

298

oauth_token_secret: str # Temporary token secret

299

oauth_callback: str # Callback URI

300

oauth_verifier: str # Authorization verifier

301

302

def get_redirect_uri(self) -> str:

303

"""Get callback URI for this temporary credential."""

304

305

def get_oauth_verifier(self) -> str:

306

"""Get OAuth verifier for this temporary credential."""

307

308

class TokenCredentialMixin:

309

"""Mixin for token credential (access token) model."""

310

311

client_key: str # Client identifier

312

oauth_token: str # Access token

313

oauth_token_secret: str # Access token secret

314

user_id: str # User identifier

315

316

def get_user_id(self) -> str:

317

"""Get user ID associated with this token."""

318

319

class TemporaryCredential:

320

"""Temporary credential representation."""

321

322

def __init__(self, client_key: str, oauth_token: str, oauth_token_secret: str, oauth_callback: str = None) -> None:

323

"""

324

Initialize temporary credential.

325

326

Args:

327

client_key: Client identifier

328

oauth_token: Temporary token

329

oauth_token_secret: Temporary token secret

330

oauth_callback: Callback URI

331

"""

332

```

333

334

### Constants

335

336

OAuth 1.0 signature methods and types.

337

338

```python { .api }

339

# Signature Methods

340

SIGNATURE_HMAC_SHA1: str = 'HMAC-SHA1'

341

SIGNATURE_RSA_SHA1: str = 'RSA-SHA1'

342

SIGNATURE_PLAINTEXT: str = 'PLAINTEXT'

343

344

# Signature Types

345

SIGNATURE_TYPE_HEADER: str = 'AUTH_HEADER'

346

SIGNATURE_TYPE_QUERY: str = 'QUERY'

347

SIGNATURE_TYPE_BODY: str = 'BODY'

348

```

349

350

## Usage Examples

351

352

### Client Flow

353

354

```python

355

from authlib.oauth1 import OAuth1Client

356

357

# Step 1: Initialize client

358

client = OAuth1Client(

359

client_key='your-client-key',

360

client_secret='your-client-secret',

361

signature_method='HMAC-SHA1'

362

)

363

364

# Step 2: Get request token

365

request_token = client.fetch_request_token('https://provider.com/oauth/request_token')

366

print(f"Request token: {request_token['oauth_token']}")

367

368

# Step 3: Get authorization URL

369

client.token = request_token['oauth_token']

370

client.token_secret = request_token['oauth_token_secret']

371

auth_url = client.create_authorization_url('https://provider.com/oauth/authorize')

372

print(f"Visit: {auth_url}")

373

374

# Step 4: After user authorization, exchange for access token

375

client.verifier = 'verifier-from-callback'

376

access_token = client.fetch_access_token('https://provider.com/oauth/access_token')

377

print(f"Access token: {access_token['oauth_token']}")

378

379

# Step 5: Make authenticated requests

380

client.token = access_token['oauth_token']

381

client.token_secret = access_token['oauth_token_secret']

382

# Use client with requests library or make manual signed requests

383

```

384

385

### Server Implementation

386

387

```python

388

from authlib.oauth1 import AuthorizationServer, ResourceProtector

389

390

# Define callback functions

391

def query_client(client_key):

392

# Return client object or None

393

return get_client_by_key(client_key)

394

395

def query_token(token):

396

# Return token object or None

397

return get_token_by_value(token)

398

399

def save_request_token(token, request):

400

# Save temporary credential

401

store_request_token(token)

402

403

def save_verifier(token, verifier, request):

404

# Save authorization verifier

405

update_token_verifier(token, verifier)

406

407

def save_access_token(token, request):

408

# Save access token

409

store_access_token(token)

410

411

# Create authorization server

412

authorization_server = AuthorizationServer(

413

query_client=query_client,

414

query_token=query_token,

415

save_request_token=save_request_token,

416

save_verifier=save_verifier,

417

save_access_token=save_access_token

418

)

419

420

# Handle request token endpoint

421

headers, body, status = authorization_server.create_request_token_response(

422

uri='/oauth/request_token',

423

http_method='POST',

424

headers=request.headers

425

)

426

427

# Handle authorization endpoint

428

headers, body, status = authorization_server.create_authorization_response(

429

uri='/oauth/authorize',

430

http_method='GET',

431

credentials={'user_id': current_user.id}

432

)

433

434

# Handle access token endpoint

435

headers, body, status = authorization_server.create_access_token_response(

436

uri='/oauth/access_token',

437

http_method='POST',

438

headers=request.headers

439

)

440

```

441

442

### Resource Protection

443

444

```python

445

from authlib.oauth1 import ResourceProtector

446

447

# Create resource protector

448

resource_protector = ResourceProtector(

449

query_client=query_client,

450

query_token=query_token

451

)

452

453

# Protect API endpoints

454

def protected_resource():

455

try:

456

# Validate OAuth 1.0 request

457

oauth_request = resource_protector.validate_request(

458

uri=request.url,

459

http_method=request.method,

460

body=request.get_data(),

461

headers=request.headers

462

)

463

464

# Access token is valid, process request

465

token = oauth_request.token

466

return f"Hello, token: {token}"

467

468

except OAuth1Error as error:

469

return {'error': error.error}, 401

470

```