or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication-actions.mdauthentication-backends.mdexception-handling.mdindex.mdpipeline-system.mdstorage-models.mdstrategy-interface.mdutilities-helpers.md

strategy-interface.mddocs/

0

# Strategy Interface

1

2

The strategy interface provides a framework-agnostic layer that adapts social-auth-core to work with any Python web framework. By implementing the strategy pattern, the library can integrate with Django, Flask, Pyramid, FastAPI, or any other web framework while maintaining consistent authentication behavior.

3

4

## Capabilities

5

6

### Base Strategy Class

7

8

The foundational strategy class that defines the interface for framework integration and provides common functionality.

9

10

```python { .api }

11

class BaseStrategy:

12

"""

13

Base strategy class for framework integration.

14

15

The strategy pattern enables social-auth-core to work with any web framework

16

by abstracting request/response handling, session management, and storage operations.

17

"""

18

19

# Class constants

20

ALLOWED_CHARS: str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

21

DEFAULT_TEMPLATE_STRATEGY: type = None # Template strategy class

22

SESSION_SAVE_KEY: str = "psa_session_id" # Session key for saving state

23

24

def __init__(self, storage=None, tpl=None):

25

"""

26

Initialize strategy with storage and template handler.

27

28

Parameters:

29

- storage: Storage backend instance for data persistence

30

- tpl: Template strategy instance for rendering (optional)

31

"""

32

33

def setting(self, name: str, default=None, backend=None):

34

"""

35

Get configuration setting value.

36

37

Retrieves setting values with proper prefixing and backend-specific

38

overrides, following the SOCIAL_AUTH_<BACKEND>_<SETTING> pattern.

39

40

Parameters:

41

- name: Setting name without prefix

42

- default: Default value if setting not found

43

- backend: Backend instance for backend-specific settings

44

45

Returns:

46

Setting value or default

47

"""

48

49

def get_setting(self, name: str):

50

"""

51

Get raw setting value without defaults.

52

53

Parameters:

54

- name: Full setting name

55

56

Returns:

57

Setting value or None if not found

58

59

Raises:

60

NotImplementedError: Must be implemented by subclasses

61

"""

62

63

def request_data(self, merge=True):

64

"""

65

Get request data (GET and POST parameters).

66

67

Extracts data from the current HTTP request, typically combining

68

query parameters and form data into a single dictionary.

69

70

Parameters:

71

- merge: Whether to merge GET and POST data (default: True)

72

73

Returns:

74

Dictionary of request parameters

75

76

Raises:

77

NotImplementedError: Must be implemented by subclasses

78

"""

79

80

def request_host(self):

81

"""

82

Get current request host.

83

84

Returns:

85

Host string from current request

86

87

Raises:

88

NotImplementedError: Must be implemented by subclasses

89

"""

90

91

def redirect(self, url: str):

92

"""

93

Create redirect response.

94

95

Generates a framework-specific redirect response to the specified URL.

96

97

Parameters:

98

- url: URL to redirect to

99

100

Returns:

101

Framework-specific redirect response

102

103

Raises:

104

NotImplementedError: Must be implemented by subclasses

105

"""

106

107

def html(self, content: str):

108

"""

109

Create HTML response.

110

111

Generates a framework-specific HTML response with the provided content.

112

113

Parameters:

114

- content: HTML content string

115

116

Returns:

117

Framework-specific HTML response

118

119

Raises:

120

NotImplementedError: Must be implemented by subclasses

121

"""

122

123

def render_html(self, tpl=None, html=None, context=None):

124

"""

125

Render HTML using template system.

126

127

Parameters:

128

- tpl: Template name/path (optional)

129

- html: Raw HTML string (optional)

130

- context: Template context dictionary (optional)

131

132

Returns:

133

Rendered HTML string

134

"""

135

136

def build_absolute_uri(self, path=None):

137

"""

138

Build absolute URI from relative path.

139

140

Parameters:

141

- path: Relative path (optional)

142

143

Returns:

144

Absolute URI string

145

146

Raises:

147

NotImplementedError: Must be implemented by subclasses

148

"""

149

150

def absolute_uri(self, path=None):

151

"""

152

Alias for build_absolute_uri.

153

154

Parameters:

155

- path: Relative path (optional)

156

157

Returns:

158

Absolute URI string

159

"""

160

161

def get_pipeline(self, backend):

162

"""

163

Get authentication pipeline configuration.

164

165

Returns the list of pipeline functions to execute for authentication,

166

allowing per-backend customization of the authentication flow.

167

168

Parameters:

169

- backend: Authentication backend instance

170

171

Returns:

172

Tuple of pipeline function names

173

"""

174

175

def authenticate(self, *args, **kwargs):

176

"""

177

Authenticate user with backend.

178

179

Executes the authentication process using the specified backend,

180

handling the complete pipeline execution and user creation/retrieval.

181

182

Parameters:

183

- backend: Authentication backend instance

184

- Additional arguments for authentication pipeline

185

186

Returns:

187

Authenticated user instance or None

188

"""

189

190

def clean_authenticate_args(self, *args, **kwargs):

191

"""

192

Clean and validate authentication arguments.

193

194

Processes authentication arguments to ensure they are in the correct

195

format for the pipeline execution.

196

197

Parameters:

198

- Arguments and keyword arguments for authentication

199

200

Returns:

201

Tuple of (cleaned_args, cleaned_kwargs)

202

"""

203

204

def continue_pipeline(self, partial):

205

"""

206

Continue interrupted authentication pipeline.

207

208

Resumes authentication flow from a partial pipeline state,

209

typically after user input or email validation.

210

211

Parameters:

212

- partial: Partial pipeline data object

213

214

Returns:

215

Authentication result or further partial state

216

"""

217

218

def session_get(self, name, default=None):

219

"""

220

Get value from session.

221

222

Parameters:

223

- name: Session key name

224

- default: Default value if key not found

225

226

Returns:

227

Session value or default

228

229

Raises:

230

NotImplementedError: Must be implemented by subclasses

231

"""

232

233

def session_set(self, name, value):

234

"""

235

Set value in session.

236

237

Parameters:

238

- name: Session key name

239

- value: Value to store

240

241

Raises:

242

NotImplementedError: Must be implemented by subclasses

243

"""

244

245

def session_pop(self, name, default=None):

246

"""

247

Remove and return value from session.

248

249

Parameters:

250

- name: Session key name

251

- default: Default value if key not found

252

253

Returns:

254

Session value or default

255

256

Raises:

257

NotImplementedError: Must be implemented by subclasses

258

"""

259

260

def session_setdefault(self, name, value):

261

"""

262

Set session value if key doesn't exist.

263

264

Parameters:

265

- name: Session key name

266

- value: Default value to set

267

268

Returns:

269

Existing value or newly set value

270

"""

271

272

def clean_partial_pipeline(self, token):

273

"""

274

Clean partial pipeline data.

275

276

Removes stored partial pipeline data after completion or cancellation.

277

278

Parameters:

279

- token: Partial pipeline token to clean

280

"""

281

282

def random_string(self, length=12, allowed_chars=None):

283

"""

284

Generate random string.

285

286

Creates a random string for tokens, nonces, or other security purposes.

287

288

Parameters:

289

- length: String length (default: 12)

290

- allowed_chars: Characters to use (default: ALLOWED_CHARS)

291

292

Returns:

293

Random string of specified length

294

"""

295

296

def create_user(self, *args, **kwargs):

297

"""

298

Create new user account.

299

300

Delegates to storage backend to create a new user with provided details.

301

302

Parameters:

303

- User creation arguments

304

305

Returns:

306

New user instance

307

"""

308

309

def get_user(self, user_id):

310

"""

311

Get user by ID.

312

313

Parameters:

314

- user_id: User primary key

315

316

Returns:

317

User instance or None if not found

318

"""

319

```

320

321

### Template Strategy Base Class

322

323

Base class for template rendering strategies that handle HTML output generation.

324

325

```python { .api }

326

class BaseTemplateStrategy:

327

"""

328

Base template strategy for rendering HTML content.

329

330

Provides abstraction for template rendering that can be adapted

331

to different template engines like Jinja2, Django templates, etc.

332

"""

333

334

def __init__(self, strategy):

335

"""

336

Initialize template strategy.

337

338

Parameters:

339

- strategy: Parent strategy instance

340

"""

341

342

def render(self, tpl=None, html=None, context=None):

343

"""

344

Render template or HTML string.

345

346

Parameters:

347

- tpl: Template name/path (optional)

348

- html: Raw HTML string (optional)

349

- context: Template context dictionary (optional)

350

351

Returns:

352

Rendered HTML string

353

354

Raises:

355

ValueError: If neither tpl nor html provided

356

"""

357

358

def render_template(self, tpl: str, context: dict | None):

359

"""

360

Render template file.

361

362

Parameters:

363

- tpl: Template name/path

364

- context: Template context dictionary

365

366

Returns:

367

Rendered HTML string

368

369

Raises:

370

NotImplementedError: Must be implemented by subclasses

371

"""

372

373

def render_string(self, html: str, context: dict | None):

374

"""

375

Render HTML string with context.

376

377

Parameters:

378

- html: Raw HTML string with template syntax

379

- context: Template context dictionary

380

381

Returns:

382

Rendered HTML string

383

384

Raises:

385

NotImplementedError: Must be implemented by subclasses

386

"""

387

```

388

389

## Framework Implementation Examples

390

391

### Django Strategy Implementation

392

393

```python

394

from django.conf import settings

395

from django.shortcuts import redirect

396

from django.http import HttpResponse

397

from social_core.strategy import BaseStrategy

398

399

class DjangoStrategy(BaseStrategy):

400

"""Django framework strategy implementation."""

401

402

def __init__(self, storage, request=None, tpl=None):

403

self.request = request

404

super().__init__(storage, tpl)

405

406

def get_setting(self, name):

407

return getattr(settings, name, None)

408

409

def request_data(self, merge=True):

410

if not self.request:

411

return {}

412

if merge:

413

data = self.request.GET.copy()

414

data.update(self.request.POST)

415

return data

416

return self.request.GET if self.request.method == 'GET' else self.request.POST

417

418

def request_host(self):

419

return self.request.get_host() if self.request else ''

420

421

def redirect(self, url):

422

return redirect(url)

423

424

def html(self, content):

425

return HttpResponse(content, content_type='text/html')

426

427

def build_absolute_uri(self, path=None):

428

return self.request.build_absolute_uri(path) if self.request else path

429

430

def session_get(self, name, default=None):

431

return self.request.session.get(name, default) if self.request else default

432

433

def session_set(self, name, value):

434

if self.request:

435

self.request.session[name] = value

436

437

def session_pop(self, name, default=None):

438

return self.request.session.pop(name, default) if self.request else default

439

```

440

441

### Flask Strategy Implementation

442

443

```python

444

from flask import request, session, redirect as flask_redirect, g

445

from social_core.strategy import BaseStrategy

446

447

class FlaskStrategy(BaseStrategy):

448

"""Flask framework strategy implementation."""

449

450

def __init__(self, storage, tpl=None):

451

super().__init__(storage, tpl)

452

453

def get_setting(self, name):

454

from flask import current_app

455

return current_app.config.get(name)

456

457

def request_data(self, merge=True):

458

if merge:

459

data = request.args.to_dict()

460

data.update(request.form.to_dict())

461

return data

462

return request.args if request.method == 'GET' else request.form

463

464

def request_host(self):

465

return request.host

466

467

def redirect(self, url):

468

return flask_redirect(url)

469

470

def html(self, content):

471

from flask import Response

472

return Response(content, content_type='text/html')

473

474

def build_absolute_uri(self, path=None):

475

return request.url_root.rstrip('/') + (path or '')

476

477

def session_get(self, name, default=None):

478

return session.get(name, default)

479

480

def session_set(self, name, value):

481

session[name] = value

482

483

def session_pop(self, name, default=None):

484

return session.pop(name, default)

485

```

486

487

### FastAPI Strategy Implementation

488

489

```python

490

from fastapi import Request

491

from fastapi.responses import RedirectResponse, HTMLResponse

492

from social_core.strategy import BaseStrategy

493

494

class FastAPIStrategy(BaseStrategy):

495

"""FastAPI framework strategy implementation."""

496

497

def __init__(self, storage, request: Request = None, tpl=None):

498

self.request = request

499

super().__init__(storage, tpl)

500

501

def get_setting(self, name):

502

# Implement settings retrieval for FastAPI

503

return getattr(settings, name, None)

504

505

def request_data(self, merge=True):

506

if not self.request:

507

return {}

508

# FastAPI request data handling

509

return dict(self.request.query_params)

510

511

def request_host(self):

512

return self.request.client.host if self.request else ''

513

514

def redirect(self, url):

515

return RedirectResponse(url=url)

516

517

def html(self, content):

518

return HTMLResponse(content=content)

519

520

def build_absolute_uri(self, path=None):

521

if not self.request:

522

return path

523

base_url = f"{self.request.url.scheme}://{self.request.url.netloc}"

524

return base_url + (path or '')

525

526

def session_get(self, name, default=None):

527

# Implement session handling for FastAPI

528

return getattr(self.request.session, 'get', lambda k, d: d)(name, default)

529

530

def session_set(self, name, value):

531

# Implement session handling for FastAPI

532

if hasattr(self.request, 'session'):

533

self.request.session[name] = value

534

535

def session_pop(self, name, default=None):

536

# Implement session handling for FastAPI

537

if hasattr(self.request, 'session'):

538

return self.request.session.pop(name, default)

539

return default

540

```

541

542

## Configuration Integration

543

544

The strategy interface integrates with framework-specific configuration systems:

545

546

```python

547

# Django settings.py

548

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'your-client-id'

549

SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'your-client-secret'

550

SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'

551

SOCIAL_AUTH_PIPELINE = (

552

'social_core.pipeline.social_auth.social_details',

553

# ... additional pipeline steps

554

)

555

556

# Flask config

557

class Config:

558

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = 'your-client-id'

559

SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'your-client-secret'

560

SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'

561

562

# FastAPI settings

563

from pydantic import BaseSettings

564

565

class Settings(BaseSettings):

566

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY: str

567

SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET: str

568

SOCIAL_AUTH_LOGIN_REDIRECT_URL: str = '/'

569

```

570

571

The strategy interface enables social-auth-core to maintain consistent behavior across different web frameworks while adapting to each framework's specific patterns for request handling, response generation, session management, and configuration.