Skip to content

Commit 64faa9e

Browse files
bull500n2ygk
andauthored
Allow Authorization Code flow without a client_secret - Initial commit with Patch & testcases (#1276)
* Initial commit with Patch & testcases * reference the RFC where empty client secret is allowed --------- Co-authored-by: Alan Crosswell <[email protected]>
1 parent 016c6c3 commit 64faa9e

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Contributors
99

1010
Abhishek Patel
1111
Adam Johnson
12+
Adheeth P Praveen
1213
Alan Crosswell
1314
Alejandro Mantecon Guillen
1415
Aleksander Vaskevich

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2525
* #1218 Confim support for Python 3.11.
2626
* #1222 Remove expired ID tokens alongside access tokens in `cleartokens` management command
2727
* #1270 Fix RP-initiated Logout with no available Django session
28+
* #1092 Allow Authorization Code flow without a client_secret per [RFC 6749 2.3.1](https://www.rfc-editor.org/rfc/rfc6749.html#section-2.3.1)
2829

2930
## [2.2.0] 2022-10-18
3031

oauth2_provider/oauth2_validators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def _authenticate_request_body(self, request):
170170
# TODO: check if oauthlib has already unquoted client_id and client_secret
171171
try:
172172
client_id = request.client_id
173-
client_secret = request.client_secret
173+
client_secret = getattr(request, "client_secret", "")
174174
except AttributeError:
175175
return False
176176

tests/test_oauth2_validators.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
RefreshToken = get_refresh_token_model()
3131

3232
CLEARTEXT_SECRET = "1234567890abcdefghijklmnopqrstuvwxyz"
33+
CLEARTEXT_BLANK_SECRET = ""
3334

3435

3536
@contextlib.contextmanager
@@ -61,11 +62,25 @@ def setUp(self):
6162
)
6263
self.request.client = self.application
6364

65+
self.blank_secret_request = mock.MagicMock(wraps=Request)
66+
self.blank_secret_request.user = self.user
67+
self.blank_secret_request.grant_type = "not client"
68+
self.blank_secret_application = Application.objects.create(
69+
client_id="blank_secret_client_id",
70+
client_secret=CLEARTEXT_BLANK_SECRET,
71+
user=self.user,
72+
client_type=Application.CLIENT_PUBLIC,
73+
authorization_grant_type=Application.GRANT_PASSWORD,
74+
)
75+
self.blank_secret_request.client = self.blank_secret_application
76+
6477
def tearDown(self):
6578
self.application.delete()
6679

6780
def test_authenticate_request_body(self):
6881
self.request.client_id = "client_id"
82+
self.assertFalse(self.validator._authenticate_request_body(self.request))
83+
6984
self.request.client_secret = ""
7085
self.assertFalse(self.validator._authenticate_request_body(self.request))
7186

@@ -75,6 +90,15 @@ def test_authenticate_request_body(self):
7590
self.request.client_secret = CLEARTEXT_SECRET
7691
self.assertTrue(self.validator._authenticate_request_body(self.request))
7792

93+
self.blank_secret_request.client_id = "blank_secret_client_id"
94+
self.assertTrue(self.validator._authenticate_request_body(self.blank_secret_request))
95+
96+
self.blank_secret_request.client_secret = CLEARTEXT_BLANK_SECRET
97+
self.assertTrue(self.validator._authenticate_request_body(self.blank_secret_request))
98+
99+
self.blank_secret_request.client_secret = "wrong_client_secret"
100+
self.assertFalse(self.validator._authenticate_request_body(self.blank_secret_request))
101+
78102
def test_extract_basic_auth(self):
79103
self.request.headers = {"HTTP_AUTHORIZATION": "Basic 123456"}
80104
self.assertEqual(self.validator._extract_basic_auth(self.request), "123456")

0 commit comments

Comments
 (0)