Skip to content

Commit 5185d20

Browse files
authored
Remove stuff that was deprecated for 2.5.0 (#1425)
* Remove stuff that was deprecated for 2.5.0 * add PR# * temporarily remove codespell which is incorrectly causing commit failures until we can better tune it.
1 parent 30afee8 commit 5185d20

File tree

7 files changed

+15
-315
lines changed

7 files changed

+15
-315
lines changed

.pre-commit-config.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ repos:
3030
hooks:
3131
- id: sphinx-lint
3232
# Configuration for codespell is in pyproject.toml
33-
- repo: https://github.com/codespell-project/codespell
34-
rev: v2.3.0
35-
hooks:
36-
- id: codespell
37-
exclude: (package-lock.json|/locale/)
38-
additional_dependencies:
39-
- tomli
33+
# - repo: https://github.com/codespell-project/codespell
34+
# rev: v2.3.0
35+
# hooks:
36+
# - id: codespell
37+
# exclude: (package-lock.json|/locale/)
38+
# additional_dependencies:
39+
# - tomli

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
### Changed
2020
### Deprecated
2121
### Removed
22+
* #1425 Remove deprecated `RedirectURIValidator`, `WildcardSet` per #1345; `validate_logout_request` per #1274
23+
2224
### Fixed
2325
### Security
2426

oauth2_provider/validators.py

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import re
2-
import warnings
32
from urllib.parse import urlsplit
43

54
from django.core.exceptions import ValidationError
@@ -19,20 +18,6 @@ class URIValidator(URLValidator):
1918
regex = re.compile(scheme_re + host_re + port_re + path_re, re.IGNORECASE)
2019

2120

22-
class RedirectURIValidator(URIValidator):
23-
def __init__(self, allowed_schemes, allow_fragments=False):
24-
warnings.warn("This class is deprecated and will be removed in version 2.5.0.", DeprecationWarning)
25-
super().__init__(schemes=allowed_schemes)
26-
self.allow_fragments = allow_fragments
27-
28-
def __call__(self, value):
29-
super().__call__(value)
30-
value = force_str(value)
31-
scheme, netloc, path, query, fragment = urlsplit(value)
32-
if fragment and not self.allow_fragments:
33-
raise ValidationError("Redirect URIs must not contain fragments")
34-
35-
3621
class AllowedURIValidator(URIValidator):
3722
# TODO: find a way to get these associated with their form fields in place of passing name
3823
# TODO: submit PR to get `cause` included in the parent class ValidationError params`
@@ -90,22 +75,3 @@ def __call__(self, value):
9075
"%(name)s URI validation error. %(cause)s: %(value)s",
9176
params={"name": self.name, "value": value, "cause": e},
9277
)
93-
94-
95-
##
96-
# WildcardSet is a special set that contains everything.
97-
# This is required in order to move validation of the scheme from
98-
# URLValidator (the base class of URIValidator), to OAuth2Application.clean().
99-
100-
101-
class WildcardSet(set):
102-
"""
103-
A set that always returns True on `in`.
104-
"""
105-
106-
def __init__(self, *args, **kwargs):
107-
warnings.warn("This class is deprecated and will be removed in version 2.5.0.", DeprecationWarning)
108-
super().__init__(*args, **kwargs)
109-
110-
def __contains__(self, item):
111-
return True

oauth2_provider/views/oidc.py

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import json
2-
import warnings
32
from urllib.parse import urlparse
43

54
from django.contrib.auth import logout
@@ -212,76 +211,6 @@ def _validate_claims(request, claims):
212211
return True
213212

214213

215-
def validate_logout_request(request, id_token_hint, client_id, post_logout_redirect_uri):
216-
"""
217-
Validate an OIDC RP-Initiated Logout Request.
218-
`(prompt_logout, (post_logout_redirect_uri, application), token_user)` is returned.
219-
220-
`prompt_logout` indicates whether the logout has to be confirmed by the user. This happens if the
221-
specifications force a confirmation, or it is enabled by `OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPT`.
222-
`post_logout_redirect_uri` is the validated URI where the User should be redirected to after the
223-
logout. Can be None. None will redirect to "/" of this app. If it is set `application` will also
224-
be set to the Application that is requesting the logout. `token_user` is the id_token user, which will
225-
used to revoke the tokens if found.
226-
227-
The `id_token_hint` will be validated if given. If both `client_id` and `id_token_hint` are given they
228-
will be validated against each other.
229-
"""
230-
231-
warnings.warn("This method is deprecated and will be removed in version 2.5.0.", DeprecationWarning)
232-
233-
id_token = None
234-
must_prompt_logout = True
235-
token_user = None
236-
if id_token_hint:
237-
# Only basic validation has been done on the IDToken at this point.
238-
id_token, claims = _load_id_token(id_token_hint)
239-
240-
if not id_token or not _validate_claims(request, claims):
241-
raise InvalidIDTokenError()
242-
243-
token_user = id_token.user
244-
245-
if id_token.user == request.user:
246-
# A logout without user interaction (i.e. no prompt) is only allowed
247-
# if an ID Token is provided that matches the current user.
248-
must_prompt_logout = False
249-
250-
# If both id_token_hint and client_id are given it must be verified that they match.
251-
if client_id:
252-
if id_token.application.client_id != client_id:
253-
raise ClientIdMissmatch()
254-
255-
# The standard states that a prompt should always be shown.
256-
# This behaviour can be configured with OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPT.
257-
prompt_logout = must_prompt_logout or oauth2_settings.OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPT
258-
259-
application = None
260-
# Determine the application that is requesting the logout.
261-
if client_id:
262-
application = get_application_model().objects.get(client_id=client_id)
263-
elif id_token:
264-
application = id_token.application
265-
266-
# Validate `post_logout_redirect_uri`
267-
if post_logout_redirect_uri:
268-
if not application:
269-
raise InvalidOIDCClientError()
270-
scheme = urlparse(post_logout_redirect_uri)[0]
271-
if not scheme:
272-
raise InvalidOIDCRedirectURIError("A Scheme is required for the redirect URI.")
273-
if oauth2_settings.OIDC_RP_INITIATED_LOGOUT_STRICT_REDIRECT_URIS and (
274-
scheme == "http" and application.client_type != "confidential"
275-
):
276-
raise InvalidOIDCRedirectURIError("http is only allowed with confidential clients.")
277-
if scheme not in application.get_allowed_schemes():
278-
raise InvalidOIDCRedirectURIError(f'Redirect to scheme "{scheme}" is not permitted.')
279-
if not application.post_logout_redirect_uri_allowed(post_logout_redirect_uri):
280-
raise InvalidOIDCRedirectURIError("This client does not have this redirect uri registered.")
281-
282-
return prompt_logout, (post_logout_redirect_uri, application), token_user
283-
284-
285214
class RPInitiatedLogoutView(OIDCLogoutOnlyMixin, FormView):
286215
template_name = "oauth2_provider/logout_confirm.html"
287216
form_class = ConfirmLogoutForm

pyproject.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ exclude = '''
1010
'''
1111

1212
# Ref: https://github.com/codespell-project/codespell#using-a-config-file
13-
[tool.codespell]
14-
skip = '.git,package-lock.json,locale'
15-
check-hidden = true
16-
ignore-regex = '.*pragma: codespell-ignore.*'
13+
# [tool.codespell]
14+
# skip = '.git,package-lock.json,locale'
15+
# check-hidden = true
16+
# ignore-regex = '.*pragma: codespell-ignore.*'
1717
# ignore-words-list = ''

tests/test_oidc_views.py

Lines changed: 1 addition & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,7 @@
1515
from oauth2_provider.models import get_access_token_model, get_id_token_model, get_refresh_token_model
1616
from oauth2_provider.oauth2_validators import OAuth2Validator
1717
from oauth2_provider.settings import oauth2_settings
18-
from oauth2_provider.views.oidc import (
19-
RPInitiatedLogoutView,
20-
_load_id_token,
21-
_validate_claims,
22-
validate_logout_request,
23-
)
18+
from oauth2_provider.views.oidc import RPInitiatedLogoutView, _load_id_token, _validate_claims
2419

2520
from . import presets
2621

@@ -225,104 +220,6 @@ def mock_request_for(user):
225220
return request
226221

227222

228-
@pytest.mark.django_db
229-
@pytest.mark.parametrize("ALWAYS_PROMPT", [True, False])
230-
def test_deprecated_validate_logout_request(
231-
oidc_tokens, public_application, other_user, rp_settings, ALWAYS_PROMPT
232-
):
233-
rp_settings.OIDC_RP_INITIATED_LOGOUT_ALWAYS_PROMPT = ALWAYS_PROMPT
234-
oidc_tokens = oidc_tokens
235-
application = oidc_tokens.application
236-
client_id = application.client_id
237-
id_token = oidc_tokens.id_token
238-
assert validate_logout_request(
239-
request=mock_request_for(oidc_tokens.user),
240-
id_token_hint=None,
241-
client_id=None,
242-
post_logout_redirect_uri=None,
243-
) == (True, (None, None), None)
244-
assert validate_logout_request(
245-
request=mock_request_for(oidc_tokens.user),
246-
id_token_hint=None,
247-
client_id=client_id,
248-
post_logout_redirect_uri=None,
249-
) == (True, (None, application), None)
250-
assert validate_logout_request(
251-
request=mock_request_for(oidc_tokens.user),
252-
id_token_hint=None,
253-
client_id=client_id,
254-
post_logout_redirect_uri="http://example.org",
255-
) == (True, ("http://example.org", application), None)
256-
assert validate_logout_request(
257-
request=mock_request_for(oidc_tokens.user),
258-
id_token_hint=id_token,
259-
client_id=None,
260-
post_logout_redirect_uri="http://example.org",
261-
) == (ALWAYS_PROMPT, ("http://example.org", application), oidc_tokens.user)
262-
assert validate_logout_request(
263-
request=mock_request_for(other_user),
264-
id_token_hint=id_token,
265-
client_id=None,
266-
post_logout_redirect_uri="http://example.org",
267-
) == (True, ("http://example.org", application), oidc_tokens.user)
268-
assert validate_logout_request(
269-
request=mock_request_for(oidc_tokens.user),
270-
id_token_hint=id_token,
271-
client_id=client_id,
272-
post_logout_redirect_uri="http://example.org",
273-
) == (ALWAYS_PROMPT, ("http://example.org", application), oidc_tokens.user)
274-
with pytest.raises(InvalidIDTokenError):
275-
validate_logout_request(
276-
request=mock_request_for(oidc_tokens.user),
277-
id_token_hint="111",
278-
client_id=public_application.client_id,
279-
post_logout_redirect_uri="http://other.org",
280-
)
281-
with pytest.raises(ClientIdMissmatch):
282-
validate_logout_request(
283-
request=mock_request_for(oidc_tokens.user),
284-
id_token_hint=id_token,
285-
client_id=public_application.client_id,
286-
post_logout_redirect_uri="http://other.org",
287-
)
288-
with pytest.raises(InvalidOIDCClientError):
289-
validate_logout_request(
290-
request=mock_request_for(oidc_tokens.user),
291-
id_token_hint=None,
292-
client_id=None,
293-
post_logout_redirect_uri="http://example.org",
294-
)
295-
with pytest.raises(InvalidOIDCRedirectURIError):
296-
validate_logout_request(
297-
request=mock_request_for(oidc_tokens.user),
298-
id_token_hint=None,
299-
client_id=client_id,
300-
post_logout_redirect_uri="example.org",
301-
)
302-
with pytest.raises(InvalidOIDCRedirectURIError):
303-
validate_logout_request(
304-
request=mock_request_for(oidc_tokens.user),
305-
id_token_hint=None,
306-
client_id=client_id,
307-
post_logout_redirect_uri="imap://example.org",
308-
)
309-
with pytest.raises(InvalidOIDCRedirectURIError):
310-
validate_logout_request(
311-
request=mock_request_for(oidc_tokens.user),
312-
id_token_hint=None,
313-
client_id=client_id,
314-
post_logout_redirect_uri="http://other.org",
315-
)
316-
with pytest.raises(InvalidOIDCRedirectURIError):
317-
rp_settings.OIDC_RP_INITIATED_LOGOUT_STRICT_REDIRECT_URIS = True
318-
validate_logout_request(
319-
request=mock_request_for(oidc_tokens.user),
320-
id_token_hint=None,
321-
client_id=public_application.client_id,
322-
post_logout_redirect_uri="http://other.org",
323-
)
324-
325-
326223
@pytest.mark.django_db
327224
def test_validate_logout_request(oidc_tokens, public_application, rp_settings):
328225
oidc_tokens = oidc_tokens

tests/test_validators.py

Lines changed: 1 addition & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -2,101 +2,7 @@
22
from django.core.validators import ValidationError
33
from django.test import TestCase
44

5-
from oauth2_provider.validators import AllowedURIValidator, RedirectURIValidator, WildcardSet
6-
7-
8-
@pytest.mark.usefixtures("oauth2_settings")
9-
class TestValidators(TestCase):
10-
def test_validate_good_uris(self):
11-
validator = RedirectURIValidator(allowed_schemes=["https"])
12-
good_uris = [
13-
"https://example.com/",
14-
"https://example.org/?key=val",
15-
"https://example",
16-
"https://localhost",
17-
"https://1.1.1.1",
18-
"https://127.0.0.1",
19-
"https://255.255.255.255",
20-
]
21-
for uri in good_uris:
22-
# Check ValidationError not thrown
23-
validator(uri)
24-
25-
def test_validate_custom_uri_scheme(self):
26-
validator = RedirectURIValidator(allowed_schemes=["my-scheme", "https", "git+ssh"])
27-
good_uris = [
28-
"my-scheme://example.com",
29-
"my-scheme://example",
30-
"my-scheme://localhost",
31-
"https://example.com",
32-
"HTTPS://example.com",
33-
"git+ssh://example.com",
34-
]
35-
for uri in good_uris:
36-
# Check ValidationError not thrown
37-
validator(uri)
38-
39-
def test_validate_bad_uris(self):
40-
validator = RedirectURIValidator(allowed_schemes=["https"])
41-
self.oauth2_settings.ALLOWED_REDIRECT_URI_SCHEMES = ["https", "good"]
42-
bad_uris = [
43-
"http:/example.com",
44-
"HTTP://localhost",
45-
"HTTP://example.com",
46-
"HTTP://example.com.",
47-
"http://example.com/#fragment",
48-
"123://example.com",
49-
"http://fe80::1",
50-
"git+ssh://example.com",
51-
"my-scheme://example.com",
52-
"uri-without-a-scheme",
53-
"https://example.com/#fragment",
54-
"good://example.com/#fragment",
55-
" ",
56-
"",
57-
# Bad IPv6 URL, urlparse behaves differently for these
58-
'https://["><script>alert()</script>',
59-
]
60-
61-
for uri in bad_uris:
62-
with self.assertRaises(ValidationError):
63-
validator(uri)
64-
65-
def test_validate_wildcard_scheme__bad_uris(self):
66-
validator = RedirectURIValidator(allowed_schemes=WildcardSet())
67-
bad_uris = [
68-
"http:/example.com#fragment",
69-
"HTTP://localhost#fragment",
70-
"http://example.com/#fragment",
71-
"good://example.com/#fragment",
72-
" ",
73-
"",
74-
# Bad IPv6 URL, urlparse behaves differently for these
75-
'https://["><script>alert()</script>',
76-
]
77-
78-
for uri in bad_uris:
79-
with self.assertRaises(ValidationError, msg=uri):
80-
validator(uri)
81-
82-
def test_validate_wildcard_scheme_good_uris(self):
83-
validator = RedirectURIValidator(allowed_schemes=WildcardSet())
84-
good_uris = [
85-
"my-scheme://example.com",
86-
"my-scheme://example",
87-
"my-scheme://localhost",
88-
"https://example.com",
89-
"HTTPS://example.com",
90-
"HTTPS://example.com.",
91-
"git+ssh://example.com",
92-
"ANY://localhost",
93-
"scheme://example.com",
94-
"at://example.com",
95-
"all://example.com",
96-
]
97-
for uri in good_uris:
98-
# Check ValidationError not thrown
99-
validator(uri)
5+
from oauth2_provider.validators import AllowedURIValidator
1006

1017

1028
@pytest.mark.usefixtures("oauth2_settings")

0 commit comments

Comments
 (0)