Skip to content

Commit d2ef983

Browse files
committed
Refactored handling of client authentication methods.
1 parent 3c193ae commit d2ef983

28 files changed

+157
-147
lines changed

example/flask_rp/conf.json

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -61,27 +61,27 @@
6161
},
6262
"services": {
6363
"discovery": {
64-
"class": "oidcrp.oidc.provider_info_discovery.ProviderInfoDiscovery",
64+
"class": "idpyoidc.client.oidc.provider_info_discovery.ProviderInfoDiscovery",
6565
"kwargs": {}
6666
},
6767
"registration": {
68-
"class": "oidcrp.oidc.registration.Registration",
68+
"class": "idpyoidc.client.oidc.registration.Registration",
6969
"kwargs": {}
7070
},
7171
"authorization": {
72-
"class": "oidcrp.oidc.authorization.Authorization",
72+
"class": "idpyoidc.client.oidc.authorization.Authorization",
7373
"kwargs": {}
7474
},
7575
"accesstoken": {
76-
"class": "oidcrp.oidc.access_token.AccessToken",
76+
"class": "idpyoidc.client.oidc.access_token.AccessToken",
7777
"kwargs": {}
7878
},
7979
"userinfo": {
80-
"class": "oidcrp.oidc.userinfo.UserInfo",
80+
"class": "idpyoidc.client.oidc.userinfo.UserInfo",
8181
"kwargs": {}
8282
},
8383
"end_session": {
84-
"class": "oidcrp.oidc.end_session.EndSession",
84+
"class": "idpyoidc.client.oidc.end_session.EndSession",
8585
"kwargs": {}
8686
}
8787
},
@@ -111,27 +111,27 @@
111111
"redirect_uris": [],
112112
"services": {
113113
"discovery": {
114-
"class": "oidcrp.oidc.provider_info_discovery.ProviderInfoDiscovery",
114+
"class": "idpyoidc.client.oidc.provider_info_discovery.ProviderInfoDiscovery",
115115
"kwargs": {}
116116
},
117117
"registration": {
118-
"class": "oidcrp.oidc.registration.Registration",
118+
"class": "idpyoidc.client.oidc.registration.Registration",
119119
"kwargs": {}
120120
},
121121
"authorization": {
122-
"class": "oidcrp.oidc.authorization.Authorization",
122+
"class": "idpyoidc.client.oidc.authorization.Authorization",
123123
"kwargs": {}
124124
},
125125
"accesstoken": {
126-
"class": "oidcrp.oidc.access_token.AccessToken",
126+
"class": "idpyoidc.client.oidc.access_token.AccessToken",
127127
"kwargs": {}
128128
},
129129
"userinfo": {
130-
"class": "oidcrp.oidc.userinfo.UserInfo",
130+
"class": "idpyoidc.client.oidc.userinfo.UserInfo",
131131
"kwargs": {}
132132
},
133133
"end_session": {
134-
"class": "oidcrp.oidc.end_session.EndSession",
134+
"class": "idpyoidc.client.oidc.end_session.EndSession",
135135
"kwargs": {}
136136
}
137137
}
@@ -169,33 +169,33 @@
169169
"backchannel_logout_session_required": true,
170170
"services": {
171171
"discovery": {
172-
"class": "oidcrp.oidc.provider_info_discovery.ProviderInfoDiscovery",
172+
"class": "idpyoidc.client.oidc.provider_info_discovery.ProviderInfoDiscovery",
173173
"kwargs": {}
174174
},
175175
"registration": {
176-
"class": "oidcrp.oidc.registration.Registration",
176+
"class": "idpyoidc.client.oidc.registration.Registration",
177177
"kwargs": {}
178178
},
179179
"authorization": {
180-
"class": "oidcrp.oidc.authorization.Authorization",
180+
"class": "idpyoidc.client.oidc.authorization.Authorization",
181181
"kwargs": {}
182182
},
183183
"accesstoken": {
184-
"class": "oidcrp.oidc.access_token.AccessToken",
184+
"class": "idpyoidc.client.oidc.access_token.AccessToken",
185185
"kwargs": {}
186186
},
187187
"userinfo": {
188-
"class": "oidcrp.oidc.userinfo.UserInfo",
188+
"class": "idpyoidc.client.oidc.userinfo.UserInfo",
189189
"kwargs": {}
190190
},
191191
"end_session": {
192-
"class": "oidcrp.oidc.end_session.EndSession",
192+
"class": "idpyoidc.client.oidc.end_session.EndSession",
193193
"kwargs": {}
194194
}
195195
},
196196
"add_ons": {
197197
"pkce": {
198-
"function": "oidcrp.oauth2.add_on.pkce.add_support",
198+
"function": "idpyoidc.client.oauth2.add_on.pkce.add_support",
199199
"kwargs": {
200200
"code_challenge_length": 64,
201201
"code_challenge_method": "S256"
@@ -236,39 +236,71 @@
236236
"backchannel_logout_session_required": true,
237237
"services": {
238238
"discovery": {
239-
"class": "oidcrp.oidc.provider_info_discovery.ProviderInfoDiscovery",
239+
"class": "idpyoidc.client.oidc.provider_info_discovery.ProviderInfoDiscovery",
240240
"kwargs": {}
241241
},
242242
"registration": {
243-
"class": "oidcrp.oidc.registration.Registration",
243+
"class": "idpyoidc.client.oidc.registration.Registration",
244244
"kwargs": {}
245245
},
246246
"authorization": {
247-
"class": "oidcrp.oidc.authorization.Authorization",
247+
"class": "idpyoidc.client.oidc.authorization.Authorization",
248248
"kwargs": {}
249249
},
250250
"accesstoken": {
251-
"class": "oidcrp.oidc.access_token.AccessToken",
251+
"class": "idpyoidc.client.oidc.access_token.AccessToken",
252252
"kwargs": {}
253253
},
254254
"userinfo": {
255-
"class": "oidcrp.oidc.userinfo.UserInfo",
255+
"class": "idpyoidc.client.oidc.userinfo.UserInfo",
256256
"kwargs": {}
257257
},
258258
"end_session": {
259-
"class": "oidcrp.oidc.end_session.EndSession",
259+
"class": "idpyoidc.client.oidc.end_session.EndSession",
260260
"kwargs": {}
261261
}
262262
},
263263
"add_ons": {
264264
"pkce": {
265-
"function": "oidcrp.oauth2.add_on.pkce.add_support",
265+
"function": "idpyoidc.client.oauth2.add_on.pkce.add_support",
266266
"kwargs": {
267267
"code_challenge_length": 64,
268268
"code_challenge_method": "S256"
269269
}
270270
}
271271
}
272+
},
273+
"bobcat": {
274+
"client_id": "client3",
275+
"client_secret": "abcdefghijklmnop",
276+
"issuer": "http://127.0.0.1:8080/",
277+
"behaviour": {
278+
"application_name": "rphandler",
279+
"application_type": "web",
280+
"contacts": [
281+
282+
],
283+
"response_types": [
284+
"code"
285+
],
286+
"scope": [
287+
"openid",
288+
"profile",
289+
"email",
290+
"address",
291+
"phone"
292+
],
293+
"token_endpoint_auth_method": [
294+
"client_secret_basic",
295+
"client_secret_post"
296+
]
297+
},
298+
"redirect_uris": [
299+
"https://{domain}:{port}/authz_cb/bobcat"
300+
],
301+
"post_logout_redirect_uri": "https://{domain}:{port}/session_logout/bobcat",
302+
"frontchannel_logout_uri": "https://{domain}:{port}/fc_logout/bobcat",
303+
"frontchannel_logout_session_required": true
272304
}
273305
},
274306
"webserver": {

example/flask_rp/views.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
from flask import session
1111
from flask.helpers import make_response
1212
from flask.helpers import send_from_directory
13-
import werkzeug
14-
1513
from idpyoidc.client import rp_handler
1614
from idpyoidc.client.exception import OidcServiceError
15+
import werkzeug
1716

1817
logger = logging.getLogger(__name__)
1918

@@ -53,12 +52,12 @@ def rp():
5352
uid = ''
5453

5554
if iss or uid:
56-
args = {
57-
'req_args': {
58-
"claims": {"id_token": {"acr": {"value": "https://refeds.org/profile/mfa"}}}
59-
}
60-
}
61-
55+
# args = {
56+
# 'req_args': {
57+
# "claims": {"id_token": {"acr": {"value": "https://refeds.org/profile/mfa"}}}
58+
# }
59+
# }
60+
args = {}
6261
if uid:
6362
args['user_id'] = uid
6463

src/idpyoidc/client/client_auth.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from cryptojwt.exception import UnsupportedAlgorithm
88
from cryptojwt.jws.jws import SIGNER_ALGS
99
from cryptojwt.jws.utils import alg2keytype
10+
from cryptojwt.utils import importer
1011

1112
from idpyoidc.defaults import DEF_SIGN_ALG
1213
from idpyoidc.defaults import JWT_BEARER
@@ -612,13 +613,15 @@ def valid_service_context(service_context, when=0):
612613
return True
613614

614615

615-
def factory(auth_method):
616-
"""Return an instance of a client authentication class.
616+
def client_auth_setup(auth_set=None):
617+
if auth_set is None:
618+
auth_set = CLIENT_AUTHN_METHOD
619+
else:
620+
auth_set.update(CLIENT_AUTHN_METHOD)
621+
res = {}
617622

618-
:param auth_method: The name of the client authentication method
619-
"""
620-
try:
621-
return CLIENT_AUTHN_METHOD[auth_method]()
622-
except KeyError:
623-
LOGGER.error('Unknown client authentication method: %s', auth_method)
624-
raise ValueError(auth_method)
623+
for name, cls in auth_set.items():
624+
if isinstance(cls, str):
625+
cls = importer(cls)
626+
res[name] = cls()
627+
return res

src/idpyoidc/client/entity.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
from typing import Union
44

55
from cryptojwt import KeyJar
6-
7-
from idpyoidc.client.client_auth import factory
6+
from idpyoidc.client.client_auth import client_auth_setup
87
from idpyoidc.client.configure import Configuration
98
from idpyoidc.client.defaults import DEFAULT_OAUTH2_SERVICES
109
from idpyoidc.client.service import init_services
@@ -13,7 +12,6 @@
1312

1413
class Entity(object):
1514
def __init__(self,
16-
client_authn_factory: Optional[Callable] = None,
1715
keyjar: Optional[KeyJar] = None,
1816
config: Optional[Union[dict, Configuration]] = None,
1917
services: Optional[dict] = None,
@@ -28,8 +26,6 @@ def __init__(self,
2826
self._service_context = ServiceContext(keyjar=keyjar, config=config,
2927
jwks_uri=jwks_uri, httpc_params=self.httpc_params)
3028

31-
_cam = client_authn_factory or factory
32-
3329
if config:
3430
_srvs = config.get("services")
3531
else:
@@ -39,8 +35,10 @@ def __init__(self,
3935
_srvs = services or DEFAULT_OAUTH2_SERVICES
4036

4137
self._service = init_services(service_definitions=_srvs,
42-
client_get=self.client_get,
43-
client_authn_factory=_cam)
38+
client_get=self.client_get)
39+
40+
self.setup_client_authn_methods(config)
41+
4442

4543
def client_get(self, what, *arg):
4644
_func = getattr(self, "get_{}".format(what), None)
@@ -72,3 +70,7 @@ def get_entity(self):
7270

7371
def get_client_id(self):
7472
return self._service_context.client_id
73+
74+
def setup_client_authn_methods(self, config):
75+
self._service_context.client_authn_method = client_auth_setup(
76+
config.get("client_authn_methods"))

src/idpyoidc/client/oauth2/__init__.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,10 @@ class ExpiredToken(Exception):
3131

3232

3333
class Client(Entity):
34-
def __init__(self, client_authn_factory=None, keyjar=None, verify_ssl=True, config=None,
34+
def __init__(self, keyjar=None, verify_ssl=True, config=None,
3535
httplib=None, services=None, jwks_uri='', httpc_params=None):
3636
"""
3737
38-
:param client_authn_factory: Factory that this client can use to
39-
initiate a client authentication class.
4038
:param keyjar: A py:class:`idpyoidc.key_jar.KeyJar` instance
4139
:param config: Configuration information passed on to the
4240
:py:class:`idpyoidc.client.service_context.ServiceContext`
@@ -48,7 +46,7 @@ def __init__(self, client_authn_factory=None, keyjar=None, verify_ssl=True, conf
4846
:return: Client instance
4947
"""
5048

51-
Entity.__init__(self, client_authn_factory=client_authn_factory, keyjar=keyjar,
49+
Entity.__init__(self, keyjar=keyjar,
5250
config=config, services=services, jwks_uri=jwks_uri,
5351
httpc_params=httpc_params)
5452

src/idpyoidc/client/oauth2/access_token.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ class AccessToken(Service):
2323
request_body_type = 'urlencoded'
2424
response_body_type = 'json'
2525

26-
def __init__(self, client_get, client_authn_factory=None, conf=None):
27-
Service.__init__(self, client_get,
28-
client_authn_factory=client_authn_factory, conf=conf)
26+
def __init__(self, client_get, conf=None):
27+
Service.__init__(self, client_get, conf=conf)
2928
self.pre_construct.append(self.oauth_pre_construct)
3029

3130
def update_service_context(self, resp, key='', **kwargs):

src/idpyoidc/client/oauth2/authorization.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ class Authorization(Service):
2828
# "endpoint": ""
2929
# })
3030

31-
def __init__(self, client_get, client_authn_factory=None, conf=None):
32-
Service.__init__(self, client_get,
33-
client_authn_factory=client_authn_factory, conf=conf)
31+
def __init__(self, client_get, conf=None):
32+
Service.__init__(self, client_get, conf=conf)
3433
self.pre_construct.extend([pre_construct_pick_redirect_uri, set_state_parameter])
3534
self.post_construct.append(self.store_auth_request)
3635

src/idpyoidc/client/oauth2/client_credentials/cc_access_token.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ class CCAccessToken(Service):
1616
request_body_type = 'urlencoded'
1717
response_body_type = 'json'
1818

19-
def __init__(self, client_get, client_authn_factory=None, conf=None):
20-
Service.__init__(self, client_get,
21-
client_authn_factory=client_authn_factory, conf=conf)
19+
def __init__(self, client_get, conf=None):
20+
Service.__init__(self, client_get, conf=conf)
2221

2322
def update_service_context(self, resp, key='cc', **kwargs):
2423
if 'expires_in' in resp:

src/idpyoidc/client/oauth2/client_credentials/cc_refresh_access_token.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ class CCRefreshAccessToken(Service):
1414
default_authn_method = 'bearer_header'
1515
http_method = 'POST'
1616

17-
def __init__(self, client_get, client_authn_factory=None, conf=None):
18-
Service.__init__(self, client_get,
19-
client_authn_factory=client_authn_factory, conf=conf)
17+
def __init__(self, client_get, conf=None):
18+
Service.__init__(self, client_get, conf=conf)
2019
self.pre_construct.append(self.cc_pre_construct)
2120
self.post_construct.append(self.cc_post_construct)
2221

src/idpyoidc/client/oauth2/provider_info_discovery.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ class ProviderInfoDiscovery(Service):
2121
service_name = 'provider_info'
2222
http_method = 'GET'
2323

24-
def __init__(self, client_get, client_authn_factory=None, conf=None):
25-
Service.__init__(self, client_get,
26-
client_authn_factory=client_authn_factory, conf=conf)
24+
def __init__(self, client_get, conf=None):
25+
Service.__init__(self, client_get, conf=conf)
2726

2827
def get_endpoint(self):
2928
"""

0 commit comments

Comments
 (0)