Skip to content

Commit 83e3f7f

Browse files
committed
config rework wik
1 parent db0b18c commit 83e3f7f

File tree

4 files changed

+183
-43
lines changed

4 files changed

+183
-43
lines changed

django_pyoidc/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
77

88
from django_pyoidc.session import OIDCCacheSessionBackendForDjango
9+
from django_pyoidc.settings import OIDCSettingsFactory
910
from django_pyoidc.utils import OIDCCacheBackendForDjango, get_setting_for_sso_op
1011

1112
logger = logging.getLogger(__name__)
@@ -14,6 +15,7 @@
1415
class OIDCClient:
1516
def __init__(self, op_name, session_id=None):
1617
self._op_name = op_name
18+
self.settings = OIDCSettingsFactory.get(self.op_name)
1719

1820
self.session_cache_backend = OIDCCacheSessionBackendForDjango(self._op_name)
1921
self.general_cache_backend = OIDCCacheBackendForDjango(self._op_name)

django_pyoidc/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ class InvalidSIDException(Exception):
44

55
class ClaimNotFoundError(Exception):
66
pass
7+
8+
9+
class InvalidOIDCConfigurationException(Exception):
10+
pass

django_pyoidc/providers/base.py

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from typing import Any, Dict, List
22

3-
from django.urls import path, reverse_lazy
3+
from django.urls import path
4+
5+
from django_pyoidc.settings import OIDCSettingsFactory
46

57

68
class Provider:
@@ -9,35 +11,45 @@ class Provider:
911
use this class directly. Instead, you should but subclass it to implement the configuration logic.
1012
"""
1113

12-
def __init__(
13-
self,
14-
op_name: str,
15-
provider_discovery_uri: str,
16-
logout_redirect: str,
17-
failure_redirect: str,
18-
success_redirect: str,
19-
redirect_requires_https: bool,
20-
client_secret: str,
21-
client_id: str,
22-
):
14+
def __init__(self, op_name: str, *args, **kwargs):
15+
# provider_discovery_uri: str,
16+
# logout_redirect: str,
17+
# failure_redirect: str,
18+
# success_redirect: str,
19+
# redirect_requires_https: bool,
20+
# client_secret: str,
21+
# client_id: str,
22+
# ):
2323
"""
24-
Parameters:
25-
op_name (str): the name of the sso provider that you are using
26-
logout_redirect (str): the URI where a user should be redirected to on logout success
27-
failure_redirect (str): the URI where a user should be redirected to on login failure
28-
success_redirect (str): the URI a user should be redirected to on login success if no redirection url where provided
29-
redirect_requires_https (bool): set to True to disallow redirecting user to non-https uri on login success
30-
client_secret (str): the OIDC client secret
31-
client_id (str): the OIDC client ID
24+
Parameters:
25+
op_name (str): the name of the sso provider that you are using
26+
FIXME logout_redirect (str): the URI where a user should be redirected to on logout success
27+
FIXME failure_redirect (str): the URI where a user should be redirected to on login failure
28+
FIXME success_redirect (str): the URI a user should be redirected to on login success if no redirection url where provided
29+
FIXME redirect_requires_https (bool): set to True to disallow redirecting user to non-https uri on login success
30+
FIXME client_secret (str): the OIDC client secret
31+
FIXME client_id (str): the OIDC client ID
3232
"""
33-
self.op_name = op_name
34-
self.provider_discovery_uri = provider_discovery_uri
35-
self.logout_redirect = logout_redirect
36-
self.failure_redirect = failure_redirect
37-
self.success_redirect = success_redirect
38-
self.redirect_requires_https = redirect_requires_https
39-
self.client_secret = client_secret
40-
self.client_id = client_id
33+
34+
self.settings = OIDCSettingsFactory.get(op_name=op_name, *args, **kwargs)
35+
36+
# provider_discovery_uri=provider_discovery_uri,
37+
# logout_redirect=logout_redirect,
38+
# failure_redirect=failure_redirect,
39+
# success_redirect=success_redirect,
40+
# redirect_requires_https=redirect_requires_https,
41+
# client_secret=client_secret,
42+
# client_id=client_id,
43+
# )
44+
45+
self.op_name = self.settings.get("op_name")
46+
# self.provider_discovery_uri = provider_discovery_uri
47+
# self.logout_redirect = logout_redirect
48+
# self.failure_redirect = failure_redirect
49+
# self.success_redirect = success_redirect
50+
# self.redirect_requires_https = redirect_requires_https
51+
# self.client_secret = client_secret
52+
# self.client_id = client_id
4153

4254
def get_config(
4355
self, allowed_hosts, cache_backend: str = "default"
@@ -52,21 +64,10 @@ def get_config(
5264
Returns:
5365
dict: A dictionary with all the settings that `django-pyoidc` expects to work properly
5466
"""
55-
return {
56-
self.op_name: {
57-
"POST_LOGIN_URI_FAILURE": self.failure_redirect,
58-
"POST_LOGIN_URI_SUCCESS": self.success_redirect,
59-
"POST_LOGOUT_REDIRECT_URI": self.logout_redirect,
60-
"OIDC_CALLBACK_PATH": reverse_lazy(self.callback_uri_name),
61-
"REDIRECT_REQUIRES_HTTPS": self.redirect_requires_https,
62-
"LOGIN_URIS_REDIRECT_ALLOWED_HOSTS": allowed_hosts,
63-
"OIDC_CLIENT_SECRET": self.client_secret,
64-
"OIDC_CLIENT_ID": self.client_id,
65-
"OIDC_PROVIDER_DISCOVERY_URI": self.provider_discovery_uri,
66-
"OIDC_LOGOUT_REDIRECT_PARAMETER_NAME": None,
67-
"CACHE_DJANGO_BACKEND": cache_backend,
68-
}
69-
}
67+
config = self.settings.get_op_config()
68+
config["LOGIN_URIS_REDIRECT_ALLOWED_HOSTS"] = allowed_hosts
69+
config["CACHE_DJANGO_BACKEND"] = cache_backend
70+
return config
7071

7172
@property
7273
def login_uri_name(self):

django_pyoidc/settings.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
from functools import lru_cache
2+
from typing import Any, Dict
3+
4+
from django.conf import settings
5+
from django.urls import reverse_lazy
6+
7+
from django_pyoidc.exceptions import InvalidOIDCConfigurationException
8+
9+
10+
class OIDCSettingsFactory:
11+
@lru_cache
12+
def get(op_name, *args, **kwargs):
13+
"""
14+
lru_cache will return a singleton for each argument value.
15+
So this is a memoized function
16+
"""
17+
18+
# FIXME: Not good, too much args, needs to memoize only on op_name
19+
20+
return OIDCSettings(op_name, *args, **kwargs)
21+
22+
23+
class OIDCSettings:
24+
25+
GLOBAL_SETTINGS = {
26+
"CACHE_PROVIDER_TTL": 60,
27+
"DRF_CLIENT_ID": None,
28+
"DRF_USE_INTROSPECTION": True,
29+
}
30+
OP_SETTINGS = {
31+
"POST_LOGIN_URI_FAILURE": "/",
32+
"POST_LOGIN_URI_SUCCESS": "/",
33+
"POST_LOGOUT_REDIRECT_URI": "/",
34+
"OIDC_CALLBACK_PATH": "/oidc",
35+
"REDIRECT_REQUIRES_HTTPS": True,
36+
"LOGIN_URIS_REDIRECT_ALLOWED_HOSTS": [],
37+
"OIDC_CLIENT_SECRET": None,
38+
"OIDC_CLIENT_ID": None,
39+
"OIDC_PROVIDER_DISCOVERY_URI": None,
40+
"OIDC_LOGOUT_REDIRECT_PARAMETER_NAME": "post_logut_redirect",
41+
"CACHE_DJANGO_BACKEND": None,
42+
}
43+
44+
def init(self, op_name: str, *args, **kwargs):
45+
# provider_discovery_uri: str,
46+
# logout_redirect: str,
47+
# failure_redirect: str,
48+
# success_redirect: str,
49+
# redirect_requires_https: bool,
50+
# client_secret: str,
51+
# client_id: str,
52+
# ):
53+
54+
# provider_discovery_uri = kwargs["provider_discovery_uri"]
55+
logout_redirect = kwargs["logout_redirect"]
56+
failure_redirect = kwargs["failure_redirect"]
57+
success_redirect = kwargs["success_redirect"]
58+
redirect_requires_https = kwargs["redirect_requires_https"]
59+
client_secret = kwargs["client_secret"]
60+
client_id = kwargs["client_id"]
61+
if op_name == "__default":
62+
raise InvalidOIDCConfigurationException(
63+
"'__default' is a reserved word that you cannot use for the provide name"
64+
)
65+
self.op_name = op_name
66+
# self.attrs =
67+
# NEW !!
68+
# if 'provider_name' in kwargs:
69+
# FIXME: load provider by name, to get all defaults from that
70+
if "provider_discovery_uri" in kwargs:
71+
self.provider_discovery_uri = kwargs["provider_discovery_uri"]
72+
else:
73+
self.provider_discovery_uri = kwargs["provider_discovery_uri"]
74+
self.init("POST_LOGOUT_REDIRECT_URI", logout_redirect)
75+
# if settings.DJANGO_PYOIDC[op_name]
76+
self.OP_SETTINGS["POST_LOGOUT_REDIRECT_URI"] = logout_redirect
77+
self.OP_SETTINGS["POST_LOGIN_URI_FAILURE"] = failure_redirect
78+
self.success_redirect = success_redirect
79+
self.redirect_requires_https = redirect_requires_https
80+
self.client_secret = client_secret
81+
self.client_id = client_id
82+
83+
def get(self, name, default=None):
84+
return self.get_op_setting(self.op_name, name, default)
85+
86+
def set(self, key: str, value=None):
87+
self.OP_SETTINGS[key] = value
88+
89+
def _get_attr(self, key):
90+
if key in self.OP_SETTINGS and self.OP_SETTINGS[key] is not None:
91+
return self.OP_SETTINGS[key]
92+
else:
93+
if key in self.GLOBAL_SETTINGS:
94+
return self.GLOBAL_SETTINGS[key]
95+
else:
96+
raise InvalidOIDCConfigurationException(
97+
f"{key} is not a valid setting."
98+
)
99+
100+
def get_op_setting(self, key: str, default=None):
101+
res = self._get_attr(key)
102+
if res is None:
103+
return default
104+
105+
def get_op_settings(op_name: str):
106+
# FALSE
107+
return settings.DJANGO_PYOIDC[op_name]
108+
109+
def get_op_config(self) -> Dict[str, Dict[str, Any]]:
110+
"""
111+
Parameters:
112+
allowed_hosts(:obj:`list`) : A list of allowed domains that can be redirected to. A good idea is to this to
113+
:setting:`ALLOWED_HOSTS <django:ALLOWED_HOSTS>`. See :ref:`Redirect the user after login` for more details.
114+
cache_backend(:obj:`str`, optional): Defaults to 'default'. The cache backend that should be used to store
115+
this provider sessions. Take a look at :ref:`Cache Management`
116+
117+
Returns:
118+
dict: A dictionary with all the settings that `django-pyoidc` expects to work properly
119+
"""
120+
return {
121+
self.op_name: {
122+
"POST_LOGIN_URI_FAILURE": self.failure_redirect,
123+
"POST_LOGIN_URI_SUCCESS": self.success_redirect,
124+
"POST_LOGOUT_REDIRECT_URI": self.logout_redirect,
125+
"OIDC_CALLBACK_PATH": reverse_lazy(self.callback_uri_name),
126+
"REDIRECT_REQUIRES_HTTPS": self.redirect_requires_https,
127+
"OIDC_CLIENT_SECRET": self.attrs["client_secret"],
128+
"OIDC_CLIENT_ID": self.attrs["client_id"],
129+
"OIDC_PROVIDER_DISCOVERY_URI": self.provider_discovery_uri,
130+
"OIDC_LOGOUT_REDIRECT_PARAMETER_NAME": None,
131+
"CACHE_PROVIDER_TTL": self.GLOBAL_SETTINGS["CACHE_PROVIDER_TTL"],
132+
}
133+
}

0 commit comments

Comments
 (0)