diff --git a/doc/developer/webservices.rst b/doc/developer/webservices.rst index 00b3cf7add..dfbdec4b36 100644 --- a/doc/developer/webservices.rst +++ b/doc/developer/webservices.rst @@ -20,7 +20,6 @@ Parameters * ``background``: parent group of background layers to get. * ``group``: the group to get. * ``min_levels``: minimum number of group levels that is required, default is ``1``. -* ``role``: role name, not used by the server but it is required for the cache management. Requests examples: diff --git a/geoportal/c2cgeoportal_geoportal/lib/common_headers.py b/geoportal/c2cgeoportal_geoportal/lib/common_headers.py index 9388be3571..3730babe73 100644 --- a/geoportal/c2cgeoportal_geoportal/lib/common_headers.py +++ b/geoportal/c2cgeoportal_geoportal/lib/common_headers.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2024, Camptocamp SA +# Copyright (c) 2012-2025, Camptocamp SA # All rights reserved. # Redistribution and use in source and binary forms, with or without @@ -126,7 +126,7 @@ def _set_common_headers( response.headers.update(service_headers_settings.get("headers", {})) if cache in (Cache.PRIVATE, Cache.PRIVATE_NO): - response.vary = (response.vary or ()) + ("Cookie",) + response.vary = (response.vary or ()) + ("Cookie", "Authorization") maxage = ( service_headers_settings.get("cache_control_max_age", 3600) diff --git a/geoportal/c2cgeoportal_geoportal/lib/lingva_extractor.py b/geoportal/c2cgeoportal_geoportal/lib/lingva_extractor.py index 59a72a6210..ca57dd3ebf 100644 --- a/geoportal/c2cgeoportal_geoportal/lib/lingva_extractor.py +++ b/geoportal/c2cgeoportal_geoportal/lib/lingva_extractor.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2024, Camptocamp SA +# Copyright (c) 2011-2025, Camptocamp SA # All rights reserved. # Redistribution and use in source and binary forms, with or without @@ -799,7 +799,7 @@ def _layer_attributes(self, url: str, layer: str) -> tuple[list[str], list[str]] try: rendered_headers = " ".join( [ - f"{h}={v if h not in ('Authorization', 'Cookies') else '***'}" + f"{h}={v if h not in ('Authorization', 'Cookie') else '***'}" for h, v in headers.items() ] ) @@ -836,7 +836,7 @@ def _layer_attributes(self, url: str, layer: str) -> tuple[list[str], list[str]] print(colorize(str(e), Color.RED)) rendered_headers = " ".join( [ - f"{h}={v if h not in ('Authorization', 'Cookies') else '***'}" + f"{h}={v if h not in ('Authorization', 'Cookie') else '***'}" for h, v in headers.items() ] ) diff --git a/geoportal/c2cgeoportal_geoportal/views/proxy.py b/geoportal/c2cgeoportal_geoportal/views/proxy.py index 427308ebcf..bdf92203e6 100644 --- a/geoportal/c2cgeoportal_geoportal/views/proxy.py +++ b/geoportal/c2cgeoportal_geoportal/views/proxy.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2024, Camptocamp SA +# Copyright (c) 2011-2025, Camptocamp SA # All rights reserved. # Redistribution and use in source and binary forms, with or without @@ -124,7 +124,7 @@ def _proxy( method, "\n".join( [ - f"{h}: {v if h not in ('Authorization', 'Cookies') else '***'}" + f"{h}: {v if h not in ('Authorization', 'Cookie') else '***'}" for h, v in list(headers.items()) ] ), @@ -154,7 +154,7 @@ def _proxy( method, "\n".join( [ - f"{h}: {v if h not in ('Authorization', 'Cookies') else '***'}" + f"{h}: {v if h not in ('Authorization', 'Cookie') else '***'}" for h, v in list(headers.items()) ] ), @@ -256,4 +256,6 @@ def get_headers(self) -> dict[str, str]: headers: dict[str, str] = self.request.headers if "Cookie" in headers: headers.pop("Cookie") + if "Authorization" in headers: + headers.pop("Authorization") return headers diff --git a/geoportal/tests/functional/test_login.py b/geoportal/tests/functional/test_login.py index 4a1b2297e8..0afd9a7e67 100644 --- a/geoportal/tests/functional/test_login.py +++ b/geoportal/tests/functional/test_login.py @@ -1,4 +1,4 @@ -# Copyright (c) 2013-2024, Camptocamp SA +# Copyright (c) 2013-2025, Camptocamp SA # All rights reserved. # Redistribution and use in source and binary forms, with or without @@ -358,7 +358,10 @@ class F: "functionalities": {"func": ["value"]}, } assert login.loginuser() == expected - assert request.response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie" + assert ( + request.response.headers["Vary"] + == "Origin, Access-Control-Request-Headers, Cookie, Authorization" + ) def test_intranet(self): from c2cgeoportal_geoportal.views.login import Login diff --git a/geoportal/tests/functional/test_oauth2.py b/geoportal/tests/functional/test_oauth2.py index 1a3516e15f..f9fccee72c 100644 --- a/geoportal/tests/functional/test_oauth2.py +++ b/geoportal/tests/functional/test_oauth2.py @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2024, Camptocamp SA +# Copyright (c) 2021-2025, Camptocamp SA # All rights reserved. # Redistribution and use in source and binary forms, with or without @@ -153,7 +153,7 @@ def test_oauth2_protocol_test_login_get_token_is_login(self) -> None: response = Login(request).oauth2token() assert response.headers["Content-Type"] == "application/json" assert response.headers["Pragma"] == "no-cache" - assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie" + assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie, Authorization" assert response.headers["Cache-Control"] == "max-age=10, no-store, private" data = json.loads(response.body) assert set(data.keys()) == {"access_token", "expires_in", "token_type", "refresh_token"} @@ -272,7 +272,7 @@ def test_oauth2_protocol_test_login_get_token_refresh_token_is_login(self) -> No response = Login(request).oauth2token() assert response.headers["Content-Type"] == "application/json" assert response.headers["Pragma"] == "no-cache" - assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie" + assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie, Authorization" assert response.headers["Cache-Control"] == "max-age=10, no-store, private" data = json.loads(response.body) assert set(data.keys()) == {"access_token", "expires_in", "token_type", "refresh_token"} @@ -356,7 +356,7 @@ def test_state_oauth2_protocol_test_login_get_token_refresh_token_is_login(self) response = Login(request).oauth2token() assert response.headers["Content-Type"] == "application/json" assert response.headers["Pragma"] == "no-cache" - assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie" + assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie, Authorization" assert response.headers["Cache-Control"] == "max-age=10, no-store, private" data = json.loads(response.body) assert set(data.keys()) == {"access_token", "expires_in", "token_type", "refresh_token"} @@ -479,7 +479,7 @@ def test_oauth2_protocol_test_login_get_token_refresh_token_wrong_code(self) -> response = Login(request).oauth2token() assert response.headers["Content-Type"] == "application/json" assert response.headers["Pragma"] == "no-cache" - assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie" + assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie, Authorization" assert response.headers["Cache-Control"] == "max-age=10, no-store, private" data = json.loads(response.body) assert set(data.keys()) == {"access_token", "expires_in", "token_type", "refresh_token"} @@ -612,7 +612,7 @@ def test_pkce_oauth2_protocol_test_login_get_token_refresh_token_is_login(self) response = Login(request).oauth2token() assert response.headers["Content-Type"] == "application/json" assert response.headers["Pragma"] == "no-cache" - assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie" + assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie, Authorization" assert response.headers["Cache-Control"] == "max-age=10, no-store, private" data = json.loads(response.body) assert set(data.keys()) == {"access_token", "expires_in", "token_type", "refresh_token"} @@ -709,7 +709,7 @@ def test_pkce_state_oauth2_protocol_test_login_get_token_refresh_token_is_login( response = Login(request).oauth2token() assert response.headers["Content-Type"] == "application/json" assert response.headers["Pragma"] == "no-cache" - assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie" + assert response.headers["Vary"] == "Origin, Access-Control-Request-Headers, Cookie, Authorization" assert response.headers["Cache-Control"] == "max-age=10, no-store, private" data = json.loads(response.body) assert set(data.keys()) == {"access_token", "expires_in", "token_type", "refresh_token"} diff --git a/geoportal/tests/test_caching.py b/geoportal/tests/test_caching.py index 0737a0dd0a..147ff51c08 100644 --- a/geoportal/tests/test_caching.py +++ b/geoportal/tests/test_caching.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2024, Camptocamp SA +# Copyright (c) 2015-2025, Camptocamp SA # All rights reserved. # Redistribution and use in source and binary forms, with or without @@ -66,7 +66,7 @@ def test_simple(self): "Cache-Control": "max-age=10, private", "Content-Length": "0", "Content-Type": "text/html; charset=UTF-8", - "Vary": "Origin, Access-Control-Request-Headers, Cookie", + "Vary": "Origin, Access-Control-Request-Headers, Cookie, Authorization", } # 2. If the value of the Origin header is not a case-sensitive match for @@ -76,7 +76,7 @@ def test_simple(self): "Cache-Control": "max-age=10, private", "Content-Length": "0", "Content-Type": "text/html; charset=UTF-8", - "Vary": "Origin, Access-Control-Request-Headers, Cookie", + "Vary": "Origin, Access-Control-Request-Headers, Cookie, Authorization", } # 3. If the resource supports credentials add a single @@ -87,7 +87,7 @@ def test_simple(self): "Cache-Control": "max-age=10, private", "Content-Length": "0", "Content-Type": "text/html; charset=UTF-8", - "Vary": "Origin, Access-Control-Request-Headers, Cookie", + "Vary": "Origin, Access-Control-Request-Headers, Cookie, Authorization", "Access-Control-Max-Age": self.MAX_AGE, "Access-Control-Allow-Origin": self.ORIGIN2, "Access-Control-Allow-Methods": CORS_METHODS, @@ -205,7 +205,7 @@ def test_not_configured(self): "Cache-Control": "max-age=10, private", "Content-Length": "0", "Content-Type": "text/html; charset=UTF-8", - "Vary": "Origin, Access-Control-Request-Headers, Cookie", + "Vary": "Origin, Access-Control-Request-Headers, Cookie, Authorization", } def test_match_all(self): @@ -220,7 +220,7 @@ def test_match_all(self): "Cache-Control": "max-age=10, private", "Content-Length": "0", "Content-Type": "text/html; charset=UTF-8", - "Vary": "Origin, Access-Control-Request-Headers, Cookie", + "Vary": "Origin, Access-Control-Request-Headers, Cookie, Authorization", "Access-Control-Max-Age": self.MAX_AGE, "Access-Control-Allow-Origin": self.ORIGIN1, "Access-Control-Allow-Methods": CORS_METHODS, @@ -233,7 +233,7 @@ def test_match_all(self): "Cache-Control": "max-age=10, private", "Content-Length": "0", "Content-Type": "text/html; charset=UTF-8", - "Vary": "Origin, Access-Control-Request-Headers, Cookie", + "Vary": "Origin, Access-Control-Request-Headers, Cookie, Authorization", "Access-Control-Max-Age": self.MAX_AGE, "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": CORS_METHODS,