1+ """The service that talks to the OAuth2 provider info discovery endpoint."""
12import logging
23
34from cryptojwt .key_jar import KeyJar
910from oidcservice .exception import OidcServiceError
1011from oidcservice .service import Service
1112
12- logger = logging .getLogger (__name__ )
13+ LOGGER = logging .getLogger (__name__ )
1314
1415
1516class ProviderInfoDiscovery (Service ):
17+ """The service that talks to the OAuth2 provider info discovery endpoint."""
1618 msg_type = oauth2 .Message
1719 response_cls = oauth2 .ASConfigurationResponse
1820 error_msg = ResponseMessage
@@ -38,8 +40,8 @@ def get_endpoint(self):
3840
3941 if _iss .endswith ('/' ):
4042 return OIDCONF_PATTERN .format (_iss [:- 1 ])
41- else :
42- return OIDCONF_PATTERN .format (_iss )
43+
44+ return OIDCONF_PATTERN .format (_iss )
4345
4446 def get_request_parameters (self , method = "GET" , ** kwargs ):
4547 """
@@ -51,82 +53,92 @@ def get_request_parameters(self, method="GET", **kwargs):
5153 """
5254 return {'url' : self .get_endpoint (), 'method' : method }
5355
54- def _update_service_context (self , resp , ** kwargs ):
56+ def _verify_issuer (self , resp , issuer ):
57+ _pcr_issuer = resp ["issuer" ]
58+ if resp ["issuer" ].endswith ("/" ):
59+ if issuer .endswith ("/" ):
60+ _issuer = issuer
61+ else :
62+ _issuer = issuer + "/"
63+ else :
64+ if issuer .endswith ("/" ):
65+ _issuer = issuer [:- 1 ]
66+ else :
67+ _issuer = issuer
68+
69+ # In some cases we can live with the two URLs not being
70+ # the same. But this is an excepted that has to be explicit
71+ try :
72+ self .service_context .allow ['issuer_mismatch' ]
73+ except KeyError :
74+ if _issuer != _pcr_issuer :
75+ raise OidcServiceError (
76+ "provider info issuer mismatch '%s' != '%s'" % (
77+ _issuer , _pcr_issuer ))
78+ return _issuer
79+
80+ @staticmethod
81+ def _store_endpoint (srvs , key , val ):
82+ for _srv in srvs .values ():
83+ # Every service has an endpoint_name assigned
84+ # when initiated. This name *MUST* match the
85+ # endpoint names used in the provider info
86+ if _srv .endpoint_name == key :
87+ _srv .endpoint = val
88+
89+ def _set_endpoints (self , resp ):
90+ """
91+ If there are services defined set the service endpoint to be
92+ the URLs specified in the provider information."""
93+ try :
94+ _srvs = self .service_context .service
95+ except AttributeError :
96+ pass
97+ else :
98+ if _srvs :
99+ for key , val in resp .items ():
100+ # All service endpoint parameters in the provider info has
101+ # a name ending in '_endpoint' so I can look specifically
102+ # for those
103+ if key .endswith ("_endpoint" ):
104+ self ._store_endpoint (_srvs , key , val )
105+
106+ def _update_service_context (self , resp ):
55107 """
56108 Deal with Provider Config Response. Based on the provider info
57109 response a set of parameters in different places needs to be set.
58110
59111 :param resp: The provider info response
60112 :param service_context: Information collected/used by services
61113 """
62- issuer = self .service_context .issuer
63114
64115 # Verify that the issuer value received is the same as the
65116 # url that was used as service endpoint (without the .well-known part)
66117 if "issuer" in resp :
67- _pcr_issuer = resp ["issuer" ]
68- if resp ["issuer" ].endswith ("/" ):
69- if issuer .endswith ("/" ):
70- _issuer = issuer
71- else :
72- _issuer = issuer + "/"
73- else :
74- if issuer .endswith ("/" ):
75- _issuer = issuer [:- 1 ]
76- else :
77- _issuer = issuer
78-
79- # In some cases we can live with the two URLs not being
80- # the same. But this is an excepted that has to be explicit
81- try :
82- self .service_context .allow ['issuer_mismatch' ]
83- except KeyError :
84- if _issuer != _pcr_issuer :
85- raise OidcServiceError (
86- "provider info issuer mismatch '%s' != '%s'" % (
87- _issuer , _pcr_issuer ))
88-
118+ _pcr_issuer = self ._verify_issuer (resp , self .service_context .issuer )
89119 else : # No prior knowledge
90- _pcr_issuer = issuer
120+ _pcr_issuer = self . service_context . issuer
91121
92122 self .service_context .issuer = _pcr_issuer
93123 self .service_context .provider_info = resp
94124
95- # If there are services defined set the service endpoint to be
96- # the URLs specified in the provider information.
97- try :
98- _srvs = self .service_context .service
99- except AttributeError :
100- pass
101- else :
102- if self .service_context .service :
103- for key , val in resp .items ():
104- # All service endpoint parameters in the provider info has
105- # a name ending in '_endpoint' so I can look specifically
106- # for those
107- if key .endswith ("_endpoint" ):
108- for _srv in self .service_context .service .values ():
109- # Every service has an endpoint_name assigned
110- # when initiated. This name *MUST* match the
111- # endpoint names used in the provider info
112- if _srv .endpoint_name == key :
113- _srv .endpoint = val
125+ self ._set_endpoints (resp )
114126
115127 # If I already have a Key Jar then I'll add then provider keys to
116128 # that. Otherwise a new Key Jar is minted
117129 try :
118- kj = self .service_context .keyjar
130+ _keyjar = self .service_context .keyjar
119131 except KeyError :
120- kj = KeyJar ()
132+ _keyjar = KeyJar ()
121133
122134 # Load the keys. Note that this only means that the key specification
123135 # is loaded not necessarily that any keys are fetched.
124136 if 'jwks_uri' in resp :
125- kj .load_keys (_pcr_issuer , jwks_uri = resp ['jwks_uri' ])
137+ _keyjar .load_keys (_pcr_issuer , jwks_uri = resp ['jwks_uri' ])
126138 elif 'jwks' in resp :
127- kj .load_keys (_pcr_issuer , jwks = resp ['jwks' ])
139+ _keyjar .load_keys (_pcr_issuer , jwks = resp ['jwks' ])
128140
129- self .service_context .keyjar = kj
141+ self .service_context .keyjar = _keyjar
130142
131143 def update_service_context (self , resp , ** kwargs ):
132- return self ._update_service_context (resp , ** kwargs )
144+ return self ._update_service_context (resp )
0 commit comments