0
# Headless API
1
2
REST API endpoints for mobile and single-page applications. Provides JSON-based authentication flows without traditional Django templates and forms, enabling modern frontend frameworks to integrate with django-allauth authentication system.
3
4
## Capabilities
5
6
### Constants and Enums
7
8
Core constants defining client types and authentication flows.
9
10
```python { .api }
11
from enum import Enum
12
13
class Client(str, Enum):
14
"""
15
Client type enumeration for headless authentication.
16
"""
17
APP = "app"
18
BROWSER = "browser"
19
20
class Flow(str, Enum):
21
"""
22
Authentication flow enumeration.
23
"""
24
VERIFY_EMAIL = "verify_email"
25
LOGIN = "login"
26
LOGIN_BY_CODE = "login_by_code"
27
SIGNUP = "signup"
28
PASSWORD_RESET_BY_CODE = "password_reset_by_code"
29
PROVIDER_REDIRECT = "provider_redirect"
30
PROVIDER_SIGNUP = "provider_signup"
31
PROVIDER_TOKEN = "provider_token"
32
REAUTHENTICATE = "reauthenticate"
33
MFA_REAUTHENTICATE = "mfa_reauthenticate"
34
MFA_AUTHENTICATE = "mfa_authenticate"
35
MFA_LOGIN_WEBAUTHN = "mfa_login_webauthn"
36
MFA_SIGNUP_WEBAUTHN = "mfa_signup_webauthn"
37
MFA_TRUST = "mfa_trust"
38
```
39
40
### Base REST Framework
41
42
Core REST API components providing input validation, response formatting, and view base classes.
43
44
```python { .api }
45
class Input:
46
"""
47
Base class for API input validation.
48
"""
49
50
def __init__(self, data: Dict[str, Any]): ...
51
def is_valid(self) -> bool: ...
52
def get_errors(self) -> Dict[str, List[str]]: ...
53
54
class Response:
55
"""
56
Base class for API response formatting.
57
"""
58
59
def __init__(self, request: HttpRequest, **kwargs): ...
60
def to_dict(self) -> Dict[str, Any]: ...
61
62
class APIView(View):
63
"""
64
Base API view class with input validation and response formatting.
65
"""
66
input_class: Optional[type] = None
67
68
def dispatch(self, request: HttpRequest, *args, **kwargs) -> JsonResponse: ...
69
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
70
def get_input_kwargs(self, request: HttpRequest, *args, **kwargs) -> Dict[str, Any]: ...
71
```
72
73
### Account API Views
74
75
REST API endpoints for account management operations.
76
77
```python { .api }
78
class LoginView(APIView):
79
"""
80
User login via REST API.
81
"""
82
input_class: type = LoginInput
83
84
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
85
86
class SignupView(APIView):
87
"""
88
User registration via REST API.
89
"""
90
input_class: type = SignupInput
91
92
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
93
94
class LogoutView(APIView):
95
"""
96
User logout via REST API.
97
"""
98
99
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
100
101
class PasswordResetView(APIView):
102
"""
103
Password reset request via REST API.
104
"""
105
input_class: type = PasswordResetInput
106
107
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
108
109
class ConfirmPasswordResetView(APIView):
110
"""
111
Password reset confirmation via REST API.
112
"""
113
input_class: type = ConfirmPasswordResetInput
114
115
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
116
117
class PasswordChangeView(APIView):
118
"""
119
Password change via REST API.
120
"""
121
input_class: type = PasswordChangeInput
122
123
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
124
125
class EmailVerificationView(APIView):
126
"""
127
Email verification via REST API.
128
"""
129
input_class: type = EmailVerificationInput
130
131
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
132
133
class RequestEmailVerificationView(APIView):
134
"""
135
Request email verification via REST API.
136
"""
137
input_class: type = RequestEmailVerificationInput
138
139
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
140
```
141
142
### Input Classes
143
144
Input validation classes for API requests.
145
146
```python { .api }
147
class LoginInput(Input):
148
"""
149
Input validation for login requests.
150
"""
151
email: str
152
password: str
153
154
def clean_email(self) -> str: ...
155
def clean_password(self) -> str: ...
156
157
class SignupInput(Input):
158
"""
159
Input validation for signup requests.
160
"""
161
email: str
162
password: str
163
username: Optional[str] = None
164
165
def clean_email(self) -> str: ...
166
def clean_password(self) -> str: ...
167
def clean_username(self) -> Optional[str]: ...
168
169
class PasswordResetInput(Input):
170
"""
171
Input validation for password reset requests.
172
"""
173
email: str
174
175
def clean_email(self) -> str: ...
176
177
class ConfirmPasswordResetInput(Input):
178
"""
179
Input validation for password reset confirmation.
180
"""
181
key: str
182
password: str
183
184
def clean_key(self) -> str: ...
185
def clean_password(self) -> str: ...
186
187
class PasswordChangeInput(Input):
188
"""
189
Input validation for password change requests.
190
"""
191
current_password: str
192
new_password: str
193
194
def clean_current_password(self) -> str: ...
195
def clean_new_password(self) -> str: ...
196
197
class EmailVerificationInput(Input):
198
"""
199
Input validation for email verification.
200
"""
201
key: str
202
203
def clean_key(self) -> str: ...
204
205
class RequestEmailVerificationInput(Input):
206
"""
207
Input validation for email verification requests.
208
"""
209
email: str
210
211
def clean_email(self) -> str: ...
212
```
213
214
### Response Classes
215
216
Response formatting classes for API responses.
217
218
```python { .api }
219
class AuthenticationResponse(Response):
220
"""
221
Response for authentication operations.
222
"""
223
224
def __init__(self, request: HttpRequest, user: User = None, access_token: str = None, **kwargs): ...
225
def to_dict(self) -> Dict[str, Any]: ...
226
227
class UserResponse(Response):
228
"""
229
Response containing user information.
230
"""
231
232
def __init__(self, request: HttpRequest, user: User, **kwargs): ...
233
def to_dict(self) -> Dict[str, Any]: ...
234
235
class FlowResponse(Response):
236
"""
237
Response for multi-step authentication flows.
238
"""
239
240
def __init__(self, request: HttpRequest, flow: str, pending: bool = False, **kwargs): ...
241
def to_dict(self) -> Dict[str, Any]: ...
242
243
class ErrorResponse(Response):
244
"""
245
Response for API errors.
246
"""
247
248
def __init__(self, request: HttpRequest, errors: Dict[str, List[str]], **kwargs): ...
249
def to_dict(self) -> Dict[str, Any]: ...
250
```
251
252
### Social Account API
253
254
REST API endpoints for social authentication.
255
256
```python { .api }
257
class ProviderRedirectView(APIView):
258
"""
259
Initiate social provider authentication.
260
"""
261
262
def handle(self, request: HttpRequest, provider: str, *args, **kwargs) -> Response: ...
263
264
class ProviderCallbackView(APIView):
265
"""
266
Handle social provider authentication callback.
267
"""
268
269
def handle(self, request: HttpRequest, provider: str, *args, **kwargs) -> Response: ...
270
271
class ProviderTokenView(APIView):
272
"""
273
Authenticate using social provider access token.
274
"""
275
input_class: type = ProviderTokenInput
276
277
def handle(self, request: HttpRequest, provider: str, *args, **kwargs) -> Response: ...
278
279
class ProvidersView(APIView):
280
"""
281
List available social authentication providers.
282
"""
283
284
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
285
```
286
287
### MFA API
288
289
REST API endpoints for multi-factor authentication.
290
291
```python { .api }
292
class MFAAuthenticateView(APIView):
293
"""
294
MFA authentication via REST API.
295
"""
296
input_class: type = MFAAuthenticateInput
297
298
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
299
300
class TOTPAddView(APIView):
301
"""
302
Add TOTP authenticator via REST API.
303
"""
304
input_class: type = TOTPAddInput
305
306
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
307
308
class WebAuthnAddView(APIView):
309
"""
310
Add WebAuthn authenticator via REST API.
311
"""
312
input_class: type = WebAuthnAddInput
313
314
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
315
316
class AuthenticatorsView(APIView):
317
"""
318
List user's MFA authenticators via REST API.
319
"""
320
321
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
322
323
class RecoveryCodesView(APIView):
324
"""
325
Manage recovery codes via REST API.
326
"""
327
328
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
329
```
330
331
### Session Management
332
333
Session and authentication token management for headless clients.
334
335
```python { .api }
336
class SessionView(APIView):
337
"""
338
Get current session information.
339
"""
340
341
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
342
343
class ConfigView(APIView):
344
"""
345
Get authentication configuration for client.
346
"""
347
348
def handle(self, request: HttpRequest, *args, **kwargs) -> Response: ...
349
350
def create_session_token(user: User, client: Client = Client.BROWSER) -> str:
351
"""
352
Create session token for headless authentication.
353
354
Parameters:
355
- user: User instance
356
- client: Client type
357
358
Returns:
359
Session token string
360
"""
361
362
def validate_session_token(token: str) -> Optional[User]:
363
"""
364
Validate session token and return user.
365
366
Parameters:
367
- token: Session token
368
369
Returns:
370
User instance if valid, None otherwise
371
"""
372
```
373
374
## Usage Examples
375
376
### Basic Authentication Flow
377
378
```python
379
import requests
380
381
# Login via API
382
login_data = {
383
'email': 'user@example.com',
384
'password': 'password123'
385
}
386
387
response = requests.post('/auth/login/', json=login_data)
388
if response.status_code == 200:
389
data = response.json()
390
access_token = data['access_token']
391
user_id = data['user']['id']
392
print(f"Logged in as user {user_id}")
393
394
# Use authentication token for subsequent requests
395
headers = {'Authorization': f'Bearer {access_token}'}
396
profile_response = requests.get('/auth/user/', headers=headers)
397
```
398
399
### Registration Flow
400
401
```python
402
# Signup via API
403
signup_data = {
404
'email': 'newuser@example.com',
405
'password': 'securepassword123',
406
'username': 'newuser'
407
}
408
409
response = requests.post('/auth/signup/', json=signup_data)
410
if response.status_code == 200:
411
data = response.json()
412
if data.get('verification_sent'):
413
print("Verification email sent")
414
415
# Verify email
416
verify_data = {
417
'key': 'verification_key_from_email'
418
}
419
verify_response = requests.post('/auth/email/verify/', json=verify_data)
420
```
421
422
### Social Authentication
423
424
```python
425
# Get social providers
426
providers_response = requests.get('/auth/providers/')
427
providers = providers_response.json()['providers']
428
429
# Initiate Google OAuth flow
430
google_response = requests.post('/auth/providers/google/redirect/')
431
redirect_url = google_response.json()['redirect_url']
432
433
# After user completes OAuth, handle callback
434
callback_data = {
435
'code': 'oauth_code_from_callback',
436
'state': 'oauth_state_from_callback'
437
}
438
auth_response = requests.post('/auth/providers/google/callback/', json=callback_data)
439
440
# Or authenticate with existing access token
441
token_data = {
442
'access_token': 'google_access_token'
443
}
444
token_response = requests.post('/auth/providers/google/token/', json=token_data)
445
```
446
447
### MFA Flow
448
449
```python
450
# Login triggers MFA if enabled
451
login_response = requests.post('/auth/login/', json=login_data)
452
if login_response.json().get('flow') == 'mfa_authenticate':
453
mfa_token = login_response.json()['mfa_token']
454
455
# Complete MFA authentication
456
mfa_data = {
457
'token': mfa_token,
458
'code': '123456' # TOTP code
459
}
460
mfa_response = requests.post('/auth/mfa/authenticate/', json=mfa_data)
461
462
if mfa_response.status_code == 200:
463
access_token = mfa_response.json()['access_token']
464
465
# Add TOTP authenticator
466
totp_setup_response = requests.post('/auth/mfa/totp/add/')
467
secret = totp_setup_response.json()['secret']
468
qr_code = totp_setup_response.json()['qr_code']
469
470
# Confirm TOTP setup
471
confirm_data = {
472
'secret': secret,
473
'code': '123456' # Code from authenticator app
474
}
475
confirm_response = requests.post('/auth/mfa/totp/confirm/', json=confirm_data)
476
```
477
478
### Password Management
479
480
```python
481
# Request password reset
482
reset_data = {
483
'email': 'user@example.com'
484
}
485
reset_response = requests.post('/auth/password/reset/', json=reset_data)
486
487
# Confirm password reset with key from email
488
confirm_data = {
489
'key': 'reset_key_from_email',
490
'password': 'newpassword123'
491
}
492
confirm_response = requests.post('/auth/password/reset/confirm/', json=confirm_data)
493
494
# Change password (authenticated user)
495
change_data = {
496
'current_password': 'oldpassword123',
497
'new_password': 'newpassword123'
498
}
499
headers = {'Authorization': f'Bearer {access_token}'}
500
change_response = requests.post('/auth/password/change/', json=change_data, headers=headers)
501
```
502
503
### Frontend Integration (JavaScript)
504
505
```javascript
506
class AuthAPI {
507
constructor(baseURL = '/auth') {
508
this.baseURL = baseURL;
509
this.token = localStorage.getItem('auth_token');
510
}
511
512
async login(email, password) {
513
const response = await fetch(`${this.baseURL}/login/`, {
514
method: 'POST',
515
headers: {'Content-Type': 'application/json'},
516
body: JSON.stringify({email, password})
517
});
518
519
const data = await response.json();
520
if (data.access_token) {
521
this.token = data.access_token;
522
localStorage.setItem('auth_token', this.token);
523
}
524
return data;
525
}
526
527
async getUser() {
528
const response = await fetch(`${this.baseURL}/user/`, {
529
headers: {'Authorization': `Bearer ${this.token}`}
530
});
531
return response.json();
532
}
533
534
async logout() {
535
await fetch(`${this.baseURL}/logout/`, {
536
method: 'POST',
537
headers: {'Authorization': `Bearer ${this.token}`}
538
});
539
this.token = null;
540
localStorage.removeItem('auth_token');
541
}
542
}
543
544
// Usage
545
const auth = new AuthAPI();
546
547
// Login
548
auth.login('user@example.com', 'password123')
549
.then(data => {
550
if (data.user) {
551
console.log('Logged in:', data.user);
552
} else if (data.flow === 'mfa_authenticate') {
553
// Handle MFA flow
554
showMFAPrompt(data.mfa_token);
555
}
556
});
557
```
558
559
### Configuration
560
561
```python
562
# In Django settings.py
563
564
# Enable headless mode
565
INSTALLED_APPS = [
566
# ...
567
'allauth.headless',
568
]
569
570
# Headless-specific settings
571
HEADLESS_ENABLED = True
572
HEADLESS_ONLY = False # Set to True to disable traditional views
573
574
# Token authentication settings
575
HEADLESS_TOKEN_STRATEGY = 'allauth.headless.tokens.SessionTokenStrategy'
576
HEADLESS_TOKEN_LIFETIME = 3600 # 1 hour
577
578
# CORS settings for API access
579
CORS_ALLOWED_ORIGINS = [
580
"http://localhost:3000", # React dev server
581
"https://myapp.com",
582
]
583
584
# URL configuration
585
urlpatterns = [
586
path('auth/', include('allauth.headless.urls')),
587
]
588
```