0
# OAuth2 Endpoints
1
2
Django OAuth Toolkit provides complete OAuth2 server endpoints implementing RFC 6749 and related specifications. These views handle authorization, token issuance, revocation, and introspection with support for all standard OAuth2 flows.
3
4
## Capabilities
5
6
### Authorization Endpoint
7
8
OAuth2 authorization endpoint that handles authorization requests and user consent.
9
10
```python { .api }
11
class AuthorizationView(BaseAuthorizationView):
12
"""
13
OAuth2 authorization endpoint (/o/authorize/).
14
15
Handles authorization requests for all grant types:
16
- Authorization Code Grant
17
- Implicit Grant
18
- OpenID Connect Hybrid Flow
19
20
Methods:
21
GET: Display authorization form to user
22
POST: Process user authorization decision
23
24
Query Parameters:
25
response_type: 'code', 'token', or 'id_token' combinations
26
client_id: OAuth2 client identifier
27
redirect_uri: Where to redirect after authorization
28
scope: Requested OAuth2 scopes
29
state: Client state parameter
30
nonce: OIDC nonce for ID token
31
code_challenge: PKCE code challenge
32
code_challenge_method: PKCE challenge method ('plain' or 'S256')
33
claims: OIDC claims parameter
34
35
Returns:
36
Authorization form or redirect to client with code/token
37
"""
38
39
template_name = "oauth2_provider/authorize.html"
40
form_class = AllowForm
41
42
def get(self, request, *args, **kwargs):
43
"""Display authorization form"""
44
45
def post(self, request, *args, **kwargs):
46
"""Process authorization decision"""
47
```
48
49
### Token Endpoint
50
51
OAuth2 token endpoint for issuing and refreshing access tokens.
52
53
```python { .api }
54
class TokenView(BaseTokenView):
55
"""
56
OAuth2 token endpoint (/o/token/).
57
58
Handles token requests for all grant types:
59
- Authorization Code Grant
60
- Resource Owner Password Credentials Grant
61
- Client Credentials Grant
62
- Refresh Token Grant
63
64
Methods:
65
POST: Issue or refresh access tokens
66
67
Form Parameters:
68
grant_type: Type of grant being used
69
code: Authorization code (authorization_code grant)
70
redirect_uri: Redirect URI used in authorization
71
username: Resource owner username (password grant)
72
password: Resource owner password (password grant)
73
refresh_token: Refresh token (refresh_token grant)
74
scope: Requested scopes
75
client_id: OAuth2 client identifier
76
client_secret: OAuth2 client secret
77
code_verifier: PKCE code verifier
78
79
Returns:
80
JSON response with access_token, token_type, expires_in, refresh_token, scope
81
"""
82
83
def post(self, request, *args, **kwargs):
84
"""Process token request and return JSON response"""
85
```
86
87
### Token Revocation Endpoint
88
89
OAuth2 token revocation endpoint implementing RFC 7009.
90
91
```python { .api }
92
class RevokeTokenView(BaseRevokeTokenView):
93
"""
94
OAuth2 token revocation endpoint (/o/revoke_token/).
95
96
Revokes access tokens and refresh tokens as per RFC 7009.
97
98
Methods:
99
POST: Revoke specified token
100
101
Form Parameters:
102
token: The token to revoke (access or refresh token)
103
token_type_hint: Hint about token type ('access_token' or 'refresh_token')
104
client_id: OAuth2 client identifier
105
client_secret: OAuth2 client secret (for confidential clients)
106
107
Returns:
108
HTTP 200 on successful revocation
109
HTTP 400 for invalid requests
110
"""
111
112
def post(self, request, *args, **kwargs):
113
"""Revoke the specified token"""
114
```
115
116
### Token Introspection Endpoint
117
118
OAuth2 token introspection endpoint implementing RFC 7662.
119
120
```python { .api }
121
class IntrospectTokenView(BaseIntrospectTokenView):
122
"""
123
OAuth2 token introspection endpoint (/o/introspect/).
124
125
Provides metadata about OAuth2 tokens as per RFC 7662.
126
127
Methods:
128
POST: Return token metadata
129
130
Form Parameters:
131
token: The token to introspect
132
token_type_hint: Hint about token type
133
client_id: OAuth2 client identifier
134
client_secret: OAuth2 client secret
135
136
Returns:
137
JSON response with token metadata:
138
- active: Boolean indicating if token is active
139
- scope: Space-separated list of scopes
140
- client_id: Client identifier
141
- username: Resource owner username
142
- token_type: Type of token
143
- exp: Expiration timestamp
144
- iat: Issued at timestamp
145
- sub: Subject identifier
146
- aud: Audience
147
- iss: Issuer
148
"""
149
150
def post(self, request, *args, **kwargs):
151
"""Return token introspection data"""
152
```
153
154
## URL Patterns
155
156
### Base OAuth2 URLs
157
158
Core OAuth2 endpoint URL patterns that should be included in your Django URL configuration.
159
160
```python { .api }
161
base_urlpatterns = [
162
path("authorize/", views.AuthorizationView.as_view(), name="authorize"),
163
path("token/", views.TokenView.as_view(), name="token"),
164
path("revoke_token/", views.RevokeTokenView.as_view(), name="revoke-token"),
165
path("introspect/", views.IntrospectTokenView.as_view(), name="introspect"),
166
]
167
```
168
169
## Usage Examples
170
171
### URL Configuration
172
173
```python
174
# urls.py
175
from django.urls import path, include
176
177
urlpatterns = [
178
# Include OAuth2 URLs
179
path('o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
180
# Your app URLs
181
path('api/', include('myapp.urls')),
182
]
183
```
184
185
### Authorization Code Flow
186
187
```python
188
# Client initiates authorization request
189
# GET /o/authorize/?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=read+write&state=STATE
190
191
# After user authorization, client receives:
192
# HTTP/1.1 302 Found
193
# Location: REDIRECT_URI?code=AUTHORIZATION_CODE&state=STATE
194
195
# Client exchanges code for token
196
# POST /o/token/
197
# Content-Type: application/x-www-form-urlencoded
198
#
199
# grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
200
201
# Response:
202
# {
203
# "access_token": "ACCESS_TOKEN",
204
# "token_type": "Bearer",
205
# "expires_in": 3600,
206
# "refresh_token": "REFRESH_TOKEN",
207
# "scope": "read write"
208
# }
209
```
210
211
### Client Credentials Flow
212
213
```python
214
# Server-to-server authentication
215
# POST /o/token/
216
# Content-Type: application/x-www-form-urlencoded
217
# Authorization: Basic BASE64(CLIENT_ID:CLIENT_SECRET)
218
#
219
# grant_type=client_credentials&scope=api
220
221
# Response:
222
# {
223
# "access_token": "ACCESS_TOKEN",
224
# "token_type": "Bearer",
225
# "expires_in": 3600,
226
# "scope": "api"
227
# }
228
```
229
230
### Resource Owner Password Credentials Flow
231
232
```python
233
# Direct username/password authentication (use carefully)
234
# POST /o/token/
235
# Content-Type: application/x-www-form-urlencoded
236
#
237
# grant_type=password&username=USERNAME&password=PASSWORD&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&scope=read+write
238
239
# Response:
240
# {
241
# "access_token": "ACCESS_TOKEN",
242
# "token_type": "Bearer",
243
# "expires_in": 3600,
244
# "refresh_token": "REFRESH_TOKEN",
245
# "scope": "read write"
246
# }
247
```
248
249
### Refresh Token Flow
250
251
```python
252
# Refresh expired access token
253
# POST /o/token/
254
# Content-Type: application/x-www-form-urlencoded
255
#
256
# grant_type=refresh_token&refresh_token=REFRESH_TOKEN&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
257
258
# Response:
259
# {
260
# "access_token": "NEW_ACCESS_TOKEN",
261
# "token_type": "Bearer",
262
# "expires_in": 3600,
263
# "refresh_token": "NEW_REFRESH_TOKEN",
264
# "scope": "read write"
265
# }
266
```
267
268
### Token Revocation
269
270
```python
271
# Revoke access token
272
# POST /o/revoke_token/
273
# Content-Type: application/x-www-form-urlencoded
274
# Authorization: Basic BASE64(CLIENT_ID:CLIENT_SECRET)
275
#
276
# token=ACCESS_TOKEN&token_type_hint=access_token
277
278
# Response: HTTP 200 OK (empty body)
279
280
# Revoke refresh token (also revokes associated access tokens)
281
# POST /o/revoke_token/
282
# Content-Type: application/x-www-form-urlencoded
283
#
284
# token=REFRESH_TOKEN&token_type_hint=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET
285
```
286
287
### Token Introspection
288
289
```python
290
# Introspect token for metadata
291
# POST /o/introspect/
292
# Content-Type: application/x-www-form-urlencoded
293
# Authorization: Basic BASE64(CLIENT_ID:CLIENT_SECRET)
294
#
295
# token=ACCESS_TOKEN
296
297
# Active token response:
298
# {
299
# "active": true,
300
# "scope": "read write",
301
# "client_id": "client123",
302
# "username": "user@example.com",
303
# "token_type": "Bearer",
304
# "exp": 1640995200,
305
# "iat": 1640991600,
306
# "sub": "user@example.com",
307
# "aud": "client123"
308
# }
309
310
# Inactive token response:
311
# {
312
# "active": false
313
# }
314
```
315
316
### PKCE (Proof Key for Code Exchange)
317
318
```python
319
# Authorization request with PKCE
320
# GET /o/authorize/?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=read&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
321
322
# Token exchange with code verifier
323
# POST /o/token/
324
# Content-Type: application/x-www-form-urlencoded
325
#
326
# grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI&client_id=CLIENT_ID&code_verifier=CODE_VERIFIER
327
```
328
329
### Custom Views
330
331
```python
332
from oauth2_provider.views.base import BaseAuthorizationView
333
from django.shortcuts import render
334
335
class CustomAuthorizationView(BaseAuthorizationView):
336
"""Custom authorization view with custom template"""
337
338
template_name = "myapp/custom_authorize.html"
339
340
def get_context_data(self, **kwargs):
341
context = super().get_context_data(**kwargs)
342
# Add custom context
343
context['custom_data'] = 'Custom authorization page'
344
return context
345
346
# Use in URL configuration
347
# path('custom/authorize/', CustomAuthorizationView.as_view(), name='custom_authorize')
348
```
349
350
### Error Handling
351
352
OAuth2 endpoints return standard error responses following RFC 6749:
353
354
```python
355
# Authorization endpoint errors (redirect to client):
356
# error=invalid_request&error_description=Missing+client_id+parameter
357
# error=unauthorized_client&error_description=Client+not+authorized
358
# error=access_denied&error_description=User+denied+authorization
359
# error=unsupported_response_type&error_description=Response+type+not+supported
360
# error=invalid_scope&error_description=Requested+scope+invalid
361
# error=server_error&error_description=Server+encountered+error
362
363
# Token endpoint errors (JSON response):
364
# {
365
# "error": "invalid_request",
366
# "error_description": "Missing grant_type parameter"
367
# }
368
#
369
# {
370
# "error": "invalid_client",
371
# "error_description": "Client authentication failed"
372
# }
373
#
374
# {
375
# "error": "invalid_grant",
376
# "error_description": "Authorization code has expired"
377
# }
378
#
379
# {
380
# "error": "unsupported_grant_type",
381
# "error_description": "Grant type not supported"
382
# }
383
```