0002-idp_oidc-check-length-of-authorize-s-redirect_uri-44.patch
src/authentic2_idp_oidc/app_settings.py | ||
---|---|---|
61 | 61 |
def PASSWORD_GRANT_RATELIMIT(self): |
62 | 62 |
return self._setting('PASSWORD_GRANT_RATELIMIT', '100/m') |
63 | 63 | |
64 |
@property |
|
65 |
def REDIRECT_URI_MAX_LENGTH(self): |
|
66 |
return self._setting('REDIRECT_URI_MAX_LENGTH', 1024) |
|
67 | ||
64 | 68 |
app_settings = AppSettings('A2_IDP_OIDC_') |
65 | 69 |
app_settings.__name__ = __name__ |
66 | 70 |
sys.modules[__name__] = app_settings |
src/authentic2_idp_oidc/models.py | ||
---|---|---|
32 | 32 |
from authentic2.models import Service |
33 | 33 |
from authentic2.utils import to_iter |
34 | 34 | |
35 |
from . import utils, managers |
|
35 |
from . import utils, managers, app_settings
|
|
36 | 36 | |
37 | 37 | |
38 | 38 |
def generate_uuid(): |
... | ... | |
192 | 192 |
def get_wanted_attributes(self): |
193 | 193 |
return self.oidcclaim_set.filter(name__isnull=False).values_list('value', flat=True) |
194 | 194 | |
195 |
def is_valid_redirect_uri(self, redirect_uri): |
|
195 |
def validate_redirect_uri(self, redirect_uri): |
|
196 |
if len(redirect_uri) > app_settings.REDIRECT_URI_MAX_LENGTH: |
|
197 |
raise ValueError('redirect_uri length > %s' % app_settings.REDIRECT_URI_MAX_LENGTH) |
|
198 | ||
196 | 199 |
parsed_uri = urlparse.urlparse(redirect_uri) |
197 | 200 |
for valid_redirect_uri in self.redirect_uris.split(): |
198 | 201 |
parsed_valid_uri = urlparse.urlparse(valid_redirect_uri) |
... | ... | |
214 | 217 |
else: |
215 | 218 |
if parsed_uri.path.rstrip('/') != parsed_valid_uri.path.rstrip('/'): |
216 | 219 |
continue |
217 |
return True
|
|
218 |
return False
|
|
220 |
return |
|
221 |
raise ValueError('redirect_uri is not declared')
|
|
219 | 222 | |
220 | 223 |
def scope_set(self): |
221 | 224 |
return utils.scope_set(self.scope) |
src/authentic2_idp_oidc/views.py | ||
---|---|---|
141 | 141 |
error_description='authz endpoint is configured ' |
142 | 142 |
'for resource owner password credential grant type') |
143 | 143 | |
144 |
if not client.is_valid_redirect_uri(redirect_uri): |
|
145 |
messages.warning(request, _('Authorization request is invalid')) |
|
146 |
logger.warning(u'idp_oidc: authorization request error, unknown redirect_uri redirect_uri=%r client_id=%r', |
|
147 |
redirect_uri, client_id) |
|
144 |
try: |
|
145 |
client.validate_redirect_uri(redirect_uri) |
|
146 |
except ValueError as e: |
|
147 |
messages.warning(request, _('Authorization request is invalid: %s') % e) |
|
148 |
logger.warning(u'idp_oidc: authorization request error, invalid redirect_uri %r (client_id=%r): %s', |
|
149 |
redirect_uri, client_id, e) |
|
148 | 150 |
return redirect(request, 'auth_homepage') |
149 | 151 | |
150 | 152 |
fragment = client.authorization_flow == client.FLOW_IMPLICIT |
tests/test_idp_oidc.py | ||
---|---|---|
1236 | 1236 |
assert user_info['family_name'].endswith(simple_user.last_name) |
1237 | 1237 | |
1238 | 1238 | |
1239 |
def test_client_is_valid_redirect_uri():
|
|
1239 |
def test_client_validate_redirect_uri():
|
|
1240 | 1240 |
client = OIDCClient(redirect_uris='''http://example.com |
1241 | 1241 |
http://example2.com/ |
1242 | 1242 |
http://example3.com/toto |
1243 | 1243 |
http://*example4.com/ |
1244 | 1244 |
http://example5.com/toto* |
1245 | 1245 |
''') |
1246 |
assert client.is_valid_redirect_uri('http://example.com') |
|
1247 |
assert client.is_valid_redirect_uri('http://example.com/') |
|
1248 |
assert not client.is_valid_redirect_uri('http://coin.example.com/') |
|
1249 |
assert not client.is_valid_redirect_uri('http://example.com/toto/') |
|
1250 |
assert not client.is_valid_redirect_uri('http://coin.example.com') |
|
1251 |
assert client.is_valid_redirect_uri('http://example2.com') |
|
1252 |
assert client.is_valid_redirect_uri('http://example2.com/') |
|
1253 |
assert not client.is_valid_redirect_uri('http://example3.com/') |
|
1254 |
assert not client.is_valid_redirect_uri('http://example3.com') |
|
1255 |
assert client.is_valid_redirect_uri('http://example3.com/toto') |
|
1256 |
assert client.is_valid_redirect_uri('http://example3.com/toto/') |
|
1257 |
assert client.is_valid_redirect_uri('http://example4.com/') |
|
1258 |
assert client.is_valid_redirect_uri('http://example4.com') |
|
1259 |
assert client.is_valid_redirect_uri('http://coin.example4.com') |
|
1260 |
assert client.is_valid_redirect_uri('http://coin.example4.com/') |
|
1261 |
assert not client.is_valid_redirect_uri('http://coinexample4.com') |
|
1262 |
assert not client.is_valid_redirect_uri('http://coinexample4.com/') |
|
1263 |
assert client.is_valid_redirect_uri('http://example5.com/toto') |
|
1264 |
assert client.is_valid_redirect_uri('http://example5.com/toto/') |
|
1265 |
assert client.is_valid_redirect_uri('http://example5.com/toto/tata') |
|
1266 |
assert client.is_valid_redirect_uri('http://example5.com/toto/tata/') |
|
1267 |
assert not client.is_valid_redirect_uri('http://example5.com/tototata/') |
|
1268 |
assert not client.is_valid_redirect_uri('http://example5.com/tototata') |
|
1246 |
# ok |
|
1247 |
for uri in [ |
|
1248 |
'http://example.com', |
|
1249 |
'http://example.com/', |
|
1250 |
'http://example2.com', |
|
1251 |
'http://example2.com/', |
|
1252 |
'http://example3.com/toto', |
|
1253 |
'http://example3.com/toto/', |
|
1254 |
'http://example4.com/', |
|
1255 |
'http://example4.com', |
|
1256 |
'http://coin.example4.com', |
|
1257 |
'http://coin.example4.com/', |
|
1258 |
'http://example5.com/toto', |
|
1259 |
'http://example5.com/toto/', |
|
1260 |
'http://example5.com/toto/tata', |
|
1261 |
'http://example5.com/toto/tata/']: |
|
1262 |
client.validate_redirect_uri(uri) |
|
1263 |
# nok |
|
1264 |
for uri in [ |
|
1265 |
'http://coin.example.com/', |
|
1266 |
'http://example.com/toto/', |
|
1267 |
'http://coin.example.com', |
|
1268 |
'http://example3.com/', |
|
1269 |
'http://example3.com', |
|
1270 |
'http://coinexample4.com', |
|
1271 |
'http://coinexample4.com/', |
|
1272 |
'http://example5.com/tototata/', |
|
1273 |
'http://example5.com/tototata']: |
|
1274 |
with pytest.raises(ValueError, match=r'is not declared'): |
|
1275 |
client.validate_redirect_uri(uri) |
|
1276 |
client.validate_redirect_uri('http://example5.com/toto/' + 'a' * 500) |
|
1277 |
with pytest.raises(ValueError, match=r'redirect_uri length >'): |
|
1278 |
client.validate_redirect_uri('http://example5.com/toto/' + 'a' * 1024) |
|
1269 | 1279 | |
1270 | 1280 | |
1271 | 1281 |
def test_filter_api_users(app, oidc_client, admin, simple_user, role_random): |
1272 |
- |