plain.oauth 0.24.1__py3-none-any.whl → 0.24.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plain/oauth/CHANGELOG.md +12 -0
- plain/oauth/README.md +54 -22
- plain/oauth/models.py +2 -2
- {plain_oauth-0.24.1.dist-info → plain_oauth-0.24.2.dist-info}/METADATA +56 -24
- {plain_oauth-0.24.1.dist-info → plain_oauth-0.24.2.dist-info}/RECORD +7 -7
- {plain_oauth-0.24.1.dist-info → plain_oauth-0.24.2.dist-info}/WHEEL +0 -0
- {plain_oauth-0.24.1.dist-info → plain_oauth-0.24.2.dist-info}/licenses/LICENSE +0 -0
plain/oauth/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# plain-oauth changelog
|
2
2
|
|
3
|
+
## [0.24.2](https://github.com/dropseed/plain/releases/plain-oauth@0.24.2) (2025-08-05)
|
4
|
+
|
5
|
+
### What's changed
|
6
|
+
|
7
|
+
- Updated documentation to use `plain` commands instead of `python manage.py` references ([8071854](https://github.com/dropseed/plain/commit/8071854d61))
|
8
|
+
- Improved README with better structure, table of contents, and more comprehensive examples ([4ebecd1](https://github.com/dropseed/plain/commit/4ebecd1856))
|
9
|
+
- Fixed router setup documentation in URLs section ([48caf10](https://github.com/dropseed/plain/commit/48caf105da))
|
10
|
+
|
11
|
+
### Upgrade instructions
|
12
|
+
|
13
|
+
- No changes required
|
14
|
+
|
3
15
|
## [0.24.1](https://github.com/dropseed/plain/releases/plain-oauth@0.24.1) (2025-07-23)
|
4
16
|
|
5
17
|
### What's changed
|
plain/oauth/README.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
# plain.oauth
|
2
2
|
|
3
|
-
Let users log in with OAuth providers
|
3
|
+
**Let users log in with OAuth providers.**
|
4
|
+
|
5
|
+
- [Overview](#overview)
|
6
|
+
- [Usage](#usage)
|
7
|
+
- [Basic setup example](#basic-setup-example)
|
8
|
+
- [Handling OAuth errors](#handling-oauth-errors)
|
9
|
+
- [Connecting and disconnecting OAuth accounts](#connecting-and-disconnecting-oauth-accounts)
|
10
|
+
- [Using a saved access token](#using-a-saved-access-token)
|
11
|
+
- [Using the Django system check](#using-the-django-system-check)
|
12
|
+
- [FAQs](#faqs)
|
13
|
+
- [Installation](#installation)
|
14
|
+
|
15
|
+
## Overview
|
4
16
|
|
5
17
|
[Watch on YouTube (3 mins) →](https://www.youtube.com/watch?v=UxbxBa6AFsU)
|
6
18
|
|
@@ -17,11 +29,9 @@ There are three OAuth flows that it makes possible:
|
|
17
29
|
|
18
30
|
## Usage
|
19
31
|
|
20
|
-
|
32
|
+
### Basic setup example
|
21
33
|
|
22
|
-
|
23
|
-
pip install plain-oauth
|
24
|
-
```
|
34
|
+
Here's a complete example showing how to set up OAuth login with GitHub:
|
25
35
|
|
26
36
|
Add `plain.oauth` to your `INSTALLED_PACKAGES` in `settings.py`:
|
27
37
|
|
@@ -32,19 +42,24 @@ INSTALLED_PACKAGES = [
|
|
32
42
|
]
|
33
43
|
```
|
34
44
|
|
35
|
-
In your `urls.py`, include `
|
45
|
+
In your `urls.py`, include the [`OAuthRouter`](./urls.py#OAuthRouter):
|
36
46
|
|
37
47
|
```python
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
48
|
+
from plain.oauth.urls import OAuthRouter
|
49
|
+
from plain.urls import Router, include
|
50
|
+
|
51
|
+
class AppRouter(Router):
|
52
|
+
namespace = ""
|
53
|
+
urls = [
|
54
|
+
include("oauth/", OAuthRouter),
|
55
|
+
# ...
|
56
|
+
]
|
42
57
|
```
|
43
58
|
|
44
59
|
Then run migrations:
|
45
60
|
|
46
61
|
```sh
|
47
|
-
|
62
|
+
plain migrate plain.oauth
|
48
63
|
```
|
49
64
|
|
50
65
|
Create a new OAuth provider ([or copy one from our examples](https://github.com/forgepackages/plain-oauth/tree/master/provider_examples)):
|
@@ -56,12 +71,12 @@ import requests
|
|
56
71
|
from plain.oauth.providers import OAuthProvider, OAuthToken, OAuthUser
|
57
72
|
|
58
73
|
|
59
|
-
class
|
60
|
-
authorization_url = "https://
|
74
|
+
class GitHubOAuthProvider(OAuthProvider):
|
75
|
+
authorization_url = "https://github.com/login/oauth/authorize"
|
61
76
|
|
62
77
|
def get_oauth_token(self, *, code, request):
|
63
78
|
response = requests.post(
|
64
|
-
"https://
|
79
|
+
"https://github.com/login/oauth/access_token",
|
65
80
|
headers={
|
66
81
|
"Accept": "application/json",
|
67
82
|
},
|
@@ -79,7 +94,7 @@ class ExampleOAuthProvider(OAuthProvider):
|
|
79
94
|
|
80
95
|
def get_oauth_user(self, *, oauth_token):
|
81
96
|
response = requests.get(
|
82
|
-
"https://
|
97
|
+
"https://api.github.com/user",
|
83
98
|
headers={
|
84
99
|
"Accept": "application/json",
|
85
100
|
"Authorization": f"token {oauth_token.access_token}",
|
@@ -136,8 +151,6 @@ your OAuth callback will be something like `https://example.com/oauth/{provider}
|
|
136
151
|
|
137
152
|
That's pretty much it!
|
138
153
|
|
139
|
-
## Advanced usage
|
140
|
-
|
141
154
|
### Handling OAuth errors
|
142
155
|
|
143
156
|
The most common error you'll run into is if an existing user clicks a login button,
|
@@ -202,7 +215,7 @@ Hello {{ request.user }}!
|
|
202
215
|
{% endblock %}
|
203
216
|
```
|
204
217
|
|
205
|
-
The `get_provider_keys` function can help populate the list of options:
|
218
|
+
The [`get_provider_keys`](./providers.py#get_provider_keys) function can help populate the list of options:
|
206
219
|
|
207
220
|
```python
|
208
221
|
from plain.oauth.providers import get_provider_keys
|
@@ -241,12 +254,12 @@ This library comes with a Django system check to ensure you don't _remove_ a pro
|
|
241
254
|
You do need to specify the `--database` for this to run when using the check command by itself:
|
242
255
|
|
243
256
|
```sh
|
244
|
-
|
257
|
+
plain check --database default
|
245
258
|
```
|
246
259
|
|
247
260
|
## FAQs
|
248
261
|
|
249
|
-
|
262
|
+
#### How is this different from [Django OAuth libraries](https://djangopackages.org/grids/g/oauth/)?
|
250
263
|
|
251
264
|
The short answer is that _it does less_.
|
252
265
|
|
@@ -265,7 +278,7 @@ and the implications for doing it one way or another.
|
|
265
278
|
The other popular OAuth libraries have similar issues,
|
266
279
|
and I think their _weight_ outweighs their usefulness for 80% of the use cases.
|
267
280
|
|
268
|
-
|
281
|
+
#### Why aren't providers included in the library itself?
|
269
282
|
|
270
283
|
One thing you'll notice is that we don't have a long list of pre-configured providers in this library.
|
271
284
|
Instead, we have some examples (which you can usually just copy, paste, and use) and otherwise encourage you to wire up the provider yourself.
|
@@ -288,7 +301,7 @@ You don't need to try to run changes through us or wait for an upstream update.
|
|
288
301
|
You're welcome to contribute an example to this repo,
|
289
302
|
and there won't be an expectation that it "works perfectly for every use case until the end of time".
|
290
303
|
|
291
|
-
|
304
|
+
#### Redirect/callback URL mismatch in local development?
|
292
305
|
|
293
306
|
If you're doing local development through a proxy/tunnel like [ngrok](https://ngrok.com/),
|
294
307
|
then the callback URL might be automatically built as `http` instead of `https`.
|
@@ -298,3 +311,22 @@ This is the Django setting you're probably looking for:
|
|
298
311
|
```python
|
299
312
|
HTTPS_PROXY_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
300
313
|
```
|
314
|
+
|
315
|
+
## Installation
|
316
|
+
|
317
|
+
Install the `plain.oauth` package from [PyPI](https://pypi.org/project/plain.oauth/):
|
318
|
+
|
319
|
+
```bash
|
320
|
+
uv add plain.oauth
|
321
|
+
```
|
322
|
+
|
323
|
+
After installation, follow the basic setup example in the [Usage](#usage) section above to:
|
324
|
+
|
325
|
+
1. Add `plain.oauth` to your `INSTALLED_PACKAGES`
|
326
|
+
2. Include the OAuth router in your URLs
|
327
|
+
3. Run migrations
|
328
|
+
4. Create an OAuth provider class
|
329
|
+
5. Configure OAuth settings
|
330
|
+
6. Add login buttons to your templates
|
331
|
+
|
332
|
+
For a complete working example, see the [Basic setup example](#basic-setup-example) which shows how to set up GitHub OAuth login.
|
plain/oauth/models.py
CHANGED
@@ -160,7 +160,7 @@ class OAuthConnection(models.Model):
|
|
160
160
|
A system check for ensuring that provider_keys in the database are also present in settings.
|
161
161
|
|
162
162
|
Note that the --database flag is required for this to work:
|
163
|
-
|
163
|
+
plain check --database default
|
164
164
|
"""
|
165
165
|
errors = super().check(**kwargs)
|
166
166
|
|
@@ -175,7 +175,7 @@ class OAuthConnection(models.Model):
|
|
175
175
|
cls.objects.values_list("provider_key", flat=True).distinct()
|
176
176
|
)
|
177
177
|
except (OperationalError, ProgrammingError):
|
178
|
-
# Check runs on
|
178
|
+
# Check runs on plain migrate, and the table may not exist yet
|
179
179
|
# or it may not be installed on the particular database intentionally
|
180
180
|
return errors
|
181
181
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: plain.oauth
|
3
|
-
Version: 0.24.
|
4
|
-
Summary:
|
3
|
+
Version: 0.24.2
|
4
|
+
Summary: Let users log in with OAuth providers.
|
5
5
|
Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
|
6
6
|
License-Expression: BSD-3-Clause
|
7
7
|
License-File: LICENSE
|
@@ -14,7 +14,19 @@ Description-Content-Type: text/markdown
|
|
14
14
|
|
15
15
|
# plain.oauth
|
16
16
|
|
17
|
-
Let users log in with OAuth providers
|
17
|
+
**Let users log in with OAuth providers.**
|
18
|
+
|
19
|
+
- [Overview](#overview)
|
20
|
+
- [Usage](#usage)
|
21
|
+
- [Basic setup example](#basic-setup-example)
|
22
|
+
- [Handling OAuth errors](#handling-oauth-errors)
|
23
|
+
- [Connecting and disconnecting OAuth accounts](#connecting-and-disconnecting-oauth-accounts)
|
24
|
+
- [Using a saved access token](#using-a-saved-access-token)
|
25
|
+
- [Using the Django system check](#using-the-django-system-check)
|
26
|
+
- [FAQs](#faqs)
|
27
|
+
- [Installation](#installation)
|
28
|
+
|
29
|
+
## Overview
|
18
30
|
|
19
31
|
[Watch on YouTube (3 mins) →](https://www.youtube.com/watch?v=UxbxBa6AFsU)
|
20
32
|
|
@@ -31,11 +43,9 @@ There are three OAuth flows that it makes possible:
|
|
31
43
|
|
32
44
|
## Usage
|
33
45
|
|
34
|
-
|
46
|
+
### Basic setup example
|
35
47
|
|
36
|
-
|
37
|
-
pip install plain-oauth
|
38
|
-
```
|
48
|
+
Here's a complete example showing how to set up OAuth login with GitHub:
|
39
49
|
|
40
50
|
Add `plain.oauth` to your `INSTALLED_PACKAGES` in `settings.py`:
|
41
51
|
|
@@ -46,19 +56,24 @@ INSTALLED_PACKAGES = [
|
|
46
56
|
]
|
47
57
|
```
|
48
58
|
|
49
|
-
In your `urls.py`, include `
|
59
|
+
In your `urls.py`, include the [`OAuthRouter`](./urls.py#OAuthRouter):
|
50
60
|
|
51
61
|
```python
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
62
|
+
from plain.oauth.urls import OAuthRouter
|
63
|
+
from plain.urls import Router, include
|
64
|
+
|
65
|
+
class AppRouter(Router):
|
66
|
+
namespace = ""
|
67
|
+
urls = [
|
68
|
+
include("oauth/", OAuthRouter),
|
69
|
+
# ...
|
70
|
+
]
|
56
71
|
```
|
57
72
|
|
58
73
|
Then run migrations:
|
59
74
|
|
60
75
|
```sh
|
61
|
-
|
76
|
+
plain migrate plain.oauth
|
62
77
|
```
|
63
78
|
|
64
79
|
Create a new OAuth provider ([or copy one from our examples](https://github.com/forgepackages/plain-oauth/tree/master/provider_examples)):
|
@@ -70,12 +85,12 @@ import requests
|
|
70
85
|
from plain.oauth.providers import OAuthProvider, OAuthToken, OAuthUser
|
71
86
|
|
72
87
|
|
73
|
-
class
|
74
|
-
authorization_url = "https://
|
88
|
+
class GitHubOAuthProvider(OAuthProvider):
|
89
|
+
authorization_url = "https://github.com/login/oauth/authorize"
|
75
90
|
|
76
91
|
def get_oauth_token(self, *, code, request):
|
77
92
|
response = requests.post(
|
78
|
-
"https://
|
93
|
+
"https://github.com/login/oauth/access_token",
|
79
94
|
headers={
|
80
95
|
"Accept": "application/json",
|
81
96
|
},
|
@@ -93,7 +108,7 @@ class ExampleOAuthProvider(OAuthProvider):
|
|
93
108
|
|
94
109
|
def get_oauth_user(self, *, oauth_token):
|
95
110
|
response = requests.get(
|
96
|
-
"https://
|
111
|
+
"https://api.github.com/user",
|
97
112
|
headers={
|
98
113
|
"Accept": "application/json",
|
99
114
|
"Authorization": f"token {oauth_token.access_token}",
|
@@ -150,8 +165,6 @@ your OAuth callback will be something like `https://example.com/oauth/{provider}
|
|
150
165
|
|
151
166
|
That's pretty much it!
|
152
167
|
|
153
|
-
## Advanced usage
|
154
|
-
|
155
168
|
### Handling OAuth errors
|
156
169
|
|
157
170
|
The most common error you'll run into is if an existing user clicks a login button,
|
@@ -216,7 +229,7 @@ Hello {{ request.user }}!
|
|
216
229
|
{% endblock %}
|
217
230
|
```
|
218
231
|
|
219
|
-
The `get_provider_keys` function can help populate the list of options:
|
232
|
+
The [`get_provider_keys`](./providers.py#get_provider_keys) function can help populate the list of options:
|
220
233
|
|
221
234
|
```python
|
222
235
|
from plain.oauth.providers import get_provider_keys
|
@@ -255,12 +268,12 @@ This library comes with a Django system check to ensure you don't _remove_ a pro
|
|
255
268
|
You do need to specify the `--database` for this to run when using the check command by itself:
|
256
269
|
|
257
270
|
```sh
|
258
|
-
|
271
|
+
plain check --database default
|
259
272
|
```
|
260
273
|
|
261
274
|
## FAQs
|
262
275
|
|
263
|
-
|
276
|
+
#### How is this different from [Django OAuth libraries](https://djangopackages.org/grids/g/oauth/)?
|
264
277
|
|
265
278
|
The short answer is that _it does less_.
|
266
279
|
|
@@ -279,7 +292,7 @@ and the implications for doing it one way or another.
|
|
279
292
|
The other popular OAuth libraries have similar issues,
|
280
293
|
and I think their _weight_ outweighs their usefulness for 80% of the use cases.
|
281
294
|
|
282
|
-
|
295
|
+
#### Why aren't providers included in the library itself?
|
283
296
|
|
284
297
|
One thing you'll notice is that we don't have a long list of pre-configured providers in this library.
|
285
298
|
Instead, we have some examples (which you can usually just copy, paste, and use) and otherwise encourage you to wire up the provider yourself.
|
@@ -302,7 +315,7 @@ You don't need to try to run changes through us or wait for an upstream update.
|
|
302
315
|
You're welcome to contribute an example to this repo,
|
303
316
|
and there won't be an expectation that it "works perfectly for every use case until the end of time".
|
304
317
|
|
305
|
-
|
318
|
+
#### Redirect/callback URL mismatch in local development?
|
306
319
|
|
307
320
|
If you're doing local development through a proxy/tunnel like [ngrok](https://ngrok.com/),
|
308
321
|
then the callback URL might be automatically built as `http` instead of `https`.
|
@@ -312,3 +325,22 @@ This is the Django setting you're probably looking for:
|
|
312
325
|
```python
|
313
326
|
HTTPS_PROXY_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
314
327
|
```
|
328
|
+
|
329
|
+
## Installation
|
330
|
+
|
331
|
+
Install the `plain.oauth` package from [PyPI](https://pypi.org/project/plain.oauth/):
|
332
|
+
|
333
|
+
```bash
|
334
|
+
uv add plain.oauth
|
335
|
+
```
|
336
|
+
|
337
|
+
After installation, follow the basic setup example in the [Usage](#usage) section above to:
|
338
|
+
|
339
|
+
1. Add `plain.oauth` to your `INSTALLED_PACKAGES`
|
340
|
+
2. Include the OAuth router in your URLs
|
341
|
+
3. Run migrations
|
342
|
+
4. Create an OAuth provider class
|
343
|
+
5. Configure OAuth settings
|
344
|
+
6. Add login buttons to your templates
|
345
|
+
|
346
|
+
For a complete working example, see the [Basic setup example](#basic-setup-example) which shows how to set up GitHub OAuth login.
|
@@ -1,18 +1,18 @@
|
|
1
|
-
plain/oauth/CHANGELOG.md,sha256=
|
2
|
-
plain/oauth/README.md,sha256=
|
1
|
+
plain/oauth/CHANGELOG.md,sha256=t9_ijwUrVBdQq1kwWZflh-91sqJccWrcc8e-Ovg8Oec,1986
|
2
|
+
plain/oauth/README.md,sha256=SUIbWnuka9mAJFOPTkrtW2KmKLAOYn5vMpT1VesPWPk,11156
|
3
3
|
plain/oauth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
plain/oauth/admin.py,sha256=9DAku8ubV6a_ByFer6UBS0G1cC_gGGHiI_iRP0b78nE,1310
|
5
5
|
plain/oauth/config.py,sha256=0Q4IILBKQbIaxqeL9WRTH5Cka-BO3c3SOj1AdQIAJgc,167
|
6
6
|
plain/oauth/default_settings.py,sha256=dlN1J9vSOjjxPNLp-0qe-cLTqwM4E69ZAx_8lpxMhaM,28
|
7
7
|
plain/oauth/exceptions.py,sha256=yoZsq8XgzstuwbE2ihoet0nzpw_sVZgDrwUauh6hhUs,546
|
8
|
-
plain/oauth/models.py,sha256=
|
8
|
+
plain/oauth/models.py,sha256=iCh_cyi2ajBN2IO8xBIHLyAyjk4OMgB4ziwDQymvwJo,6739
|
9
9
|
plain/oauth/providers.py,sha256=YDftJUMyyfXgsDCkyTNxGwrbwXAowL0Hg6KrwrAN5S0,7793
|
10
10
|
plain/oauth/urls.py,sha256=FYzpQwhvZdcat8n3f7RyA-1Q21finKb8JEyakSOjXXg,696
|
11
11
|
plain/oauth/views.py,sha256=J2NCa37YediBTi82CfRlmsb45hFT6gWN6zMaFHhsDMM,2410
|
12
12
|
plain/oauth/migrations/0001_initial.py,sha256=0NjfF7F3szhUXkpK3JvN10Xkat1QR-VvnX6Oed9iFmo,1940
|
13
13
|
plain/oauth/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
14
|
plain/oauth/templates/oauth/callback.html,sha256=4CJG0oAN0xYjw2IPkjaL7B4hwlf9um9LI4CTu50E-yE,173
|
15
|
-
plain_oauth-0.24.
|
16
|
-
plain_oauth-0.24.
|
17
|
-
plain_oauth-0.24.
|
18
|
-
plain_oauth-0.24.
|
15
|
+
plain_oauth-0.24.2.dist-info/METADATA,sha256=4wEMvZsEaJXj9V8-FnSVQt7dGhLExWZFKjhw0O1ObII,11561
|
16
|
+
plain_oauth-0.24.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
17
|
+
plain_oauth-0.24.2.dist-info/licenses/LICENSE,sha256=cvKM3OlqHx3ijD6e34zsSUkPvzl-ya3Dd63A6EHL94U,1500
|
18
|
+
plain_oauth-0.24.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|