Skip to content

Commit 5b83e97

Browse files
committed
enable microservice-based flow to replay AuthnRequest
(requires wsgi_app in registered callback)
1 parent d8ba645 commit 5b83e97

27 files changed

+130
-118
lines changed

Diff for: src/satosa/backends/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def __init__(self, auth_callback_func, internal_attributes, base_url, name):
3232
self.base_url = base_url
3333
self.name = name
3434

35-
def start_auth(self, context, internal_request):
35+
def start_auth(self, context, internal_request, **kwargs):
3636
"""
3737
This is the start up function of the backend authorization.
3838

Diff for: src/satosa/backends/github.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name):
4545
outgoing, internal_attributes, config, base_url, name, 'github',
4646
'id')
4747

48-
def start_auth(self, context, internal_request, get_state=stateID):
48+
def start_auth(self, context, internal_request, get_state=stateID, **kwargs):
4949
"""
5050
:param get_state: Generates a state to be used in authentication call
5151
@@ -75,7 +75,7 @@ def auth_info(self, requrest):
7575
UNSPECIFIED, None,
7676
self.config['server_info']['authorization_endpoint'])
7777

78-
def _authn_response(self, context):
78+
def _authn_response(self, context, **kwargs):
7979
state_data = context.state[self.name]
8080
aresp = self.consumer.parse_response(
8181
AuthorizationResponse, info=json.dumps(context.request))

Diff for: src/satosa/backends/linkedin.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name):
4646
outgoing, internal_attributes, config, base_url, name, 'linkedin',
4747
'id')
4848

49-
def start_auth(self, context, internal_request, get_state=stateID):
49+
def start_auth(self, context, internal_request, get_state=stateID, **kwargs):
5050
"""
5151
:param get_state: Generates a state to be used in authentication call
5252
@@ -76,7 +76,7 @@ def auth_info(self, requrest):
7676
UNSPECIFIED, None,
7777
self.config['server_info']['authorization_endpoint'])
7878

79-
def _authn_response(self, context):
79+
def _authn_response(self, context, **kwargs):
8080
state_data = context.state[self.name]
8181
aresp = self.consumer.parse_response(
8282
AuthorizationResponse, info=json.dumps(context.request))

Diff for: src/satosa/backends/oauth.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name, extern
6464
response_type=self.config["response_type"])
6565
self.consumer.client_secret = self.config["client_secret"]
6666

67-
def start_auth(self, context, internal_request, get_state=stateID):
67+
def start_auth(self, context, internal_request, get_state=stateID, **kwargs):
6868
"""
6969
See super class method satosa.backends.base#start_auth
7070
:param get_state: Generates a state to be used in the authentication call.
@@ -118,7 +118,7 @@ def _verify_state(self, resp, state_data, state):
118118
"Missing or invalid state [%s] in response!" %
119119
received_state)
120120

121-
def _authn_response(self, context):
121+
def _authn_response(self, context, **kwargs):
122122
"""
123123
Handles the authentication response from the AS.
124124

Diff for: src/satosa/backends/openid_connect.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def __init__(self, auth_callback_func, internal_attributes, config, base_url, na
6464
if "response_type" not in config["client"]["auth_req_params"]:
6565
config["auth_req_params"]["response_type"] = "code"
6666

67-
def start_auth(self, context, request_info):
67+
def start_auth(self, context, request_info, **kwargs):
6868
"""
6969
See super class method satosa.backends.base#start_auth
7070
:type context: satosa.context.Context
@@ -167,7 +167,7 @@ def _get_userinfo(self, state, context):
167167
self._check_error_response(userinfo_resp, context)
168168
return userinfo_resp.to_dict()
169169

170-
def response_endpoint(self, context, *args):
170+
def response_endpoint(self, context, *args, **kwargs):
171171
"""
172172
Handles the authentication response from the OP.
173173
:type context: satosa.context.Context

Diff for: src/satosa/backends/orcid.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def auth_info(self, requrest):
6060
UNSPECIFIED, None,
6161
self.config['server_info']['authorization_endpoint'])
6262

63-
def _authn_response(self, context):
63+
def _authn_response(self, context, **kwargs):
6464
state_data = context.state[self.name]
6565
aresp = self.consumer.parse_response(
6666
AuthorizationResponse, info=json.dumps(context.request))

Diff for: src/satosa/backends/saml2.py

+13-12
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name):
129129
with open(p) as key_file:
130130
self.encryption_keys.append(key_file.read())
131131

132-
def get_idp_entity_id(self, context):
132+
def get_idp_entity_id(self, context, **kwargs):
133133
"""
134134
:type context: satosa.context.Context
135135
:rtype: str | None
@@ -164,7 +164,7 @@ def get_idp_entity_id(self, context):
164164
)
165165
return entity_id
166166

167-
def start_auth(self, context, internal_req):
167+
def start_auth(self, context, internal_req, **kwargs):
168168
"""
169169
See super class method satosa.backends.base.BackendModule#start_auth
170170
@@ -184,7 +184,7 @@ def start_auth(self, context, internal_req):
184184

185185
return self.authn_request(context, entity_id)
186186

187-
def disco_query(self, context):
187+
def disco_query(self, context, **kwargs):
188188
"""
189189
Makes a request to the discovery server
190190
@@ -236,7 +236,7 @@ def construct_requested_authn_context(self, entity_id):
236236

237237
return authn_context
238238

239-
def authn_request(self, context, entity_id):
239+
def authn_request(self, context, entity_id, **kwargs):
240240
"""
241241
Do an authorization request on idp with given entity id.
242242
This is the start of the authorization.
@@ -294,7 +294,7 @@ def authn_request(self, context, entity_id):
294294
context.state[self.name] = {"relay_state": relay_state}
295295
return make_saml_response(binding, ht_args)
296296

297-
def authn_response(self, context, binding):
297+
def authn_response(self, context, binding, **kwargs):
298298
"""
299299
Endpoint for the idp response
300300
:type context: satosa.context,Context
@@ -326,11 +326,12 @@ def authn_response(self, context, binding):
326326
raise SATOSAAuthenticationError(context.state, errmsg)
327327
del self.outstanding_queries[req_id]
328328

329-
# check if the relay_state matches the cookie state
330-
if context.state[self.name]["relay_state"] != context.request["RelayState"]:
331-
satosa_logging(logger, logging.DEBUG,
332-
"State did not match relay state for state", context.state)
333-
raise SATOSAAuthenticationError(context.state, "State did not match relay state")
329+
# if the response relay_state exists it must match that from the request
330+
if self.name in context.state and "relay_state" in context.state[self.name]:
331+
if context.state[self.name]["relay_state"] != context.request["RelayState"]:
332+
logger.debug("State did not match relay state for state", extra={'state': context.state})
333+
raise SATOSAAuthenticationError(context.state, "State did not match relay state")
334+
del context.state[self.name]
334335

335336
context.decorate(Context.KEY_BACKEND_METADATA_STORE, self.sp.metadata)
336337
if self.config.get(SAMLBackend.KEY_MEMORIZE_IDP):
@@ -340,7 +341,7 @@ def authn_response(self, context, binding):
340341
context.state.pop(Context.KEY_FORCE_AUTHN, None)
341342
return self.auth_callback_func(context, self._translate_response(authn_response, context.state))
342343

343-
def disco_response(self, context):
344+
def disco_response(self, context, **kwargs):
344345
"""
345346
Endpoint for the discovery server response
346347
@@ -406,7 +407,7 @@ def _translate_response(self, response, state):
406407
json.dumps(response.ava, indent=4), state)
407408
return internal_resp
408409

409-
def _metadata_endpoint(self, context):
410+
def _metadata_endpoint(self, context, **kwargs):
410411
"""
411412
Endpoint for retrieving the backend metadata
412413
:type context: satosa.context.Context

Diff for: src/satosa/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ def _run_bound_endpoint(self, context, spec):
226226
:return: response
227227
"""
228228
try:
229-
return spec(context)
229+
return spec(context, wsgi_app=self)
230230
except SATOSAAuthenticationError as error:
231231
error.error_id = uuid.uuid4().urn
232232
state = json.dumps(error.state.state_dict, indent=4)

Diff for: src/satosa/frontends/base.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __init__(self, auth_req_callback_func, internal_attributes, base_url, name):
2626
self.base_url = base_url
2727
self.name = name
2828

29-
def handle_authn_response(self, context, internal_resp):
29+
def handle_authn_response(self, context, internal_resp, **kwargs):
3030
"""
3131
If an authorization has been successful in a backend, this function is called and is
3232
supposed to send an authorization response to the client.

Diff for: src/satosa/frontends/openid_connect.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _init_authorization_state(self):
117117
return AuthorizationState(HashBasedSubjectIdentifierFactory(sub_hash_salt), authz_code_db, access_token_db,
118118
refresh_token_db, sub_db, **token_lifetimes)
119119

120-
def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None):
120+
def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None, **kwargs):
121121
"""
122122
See super class method satosa.frontends.base.FrontendModule#handle_authn_response
123123
:type context: satosa.context.Context
@@ -232,7 +232,7 @@ def _get_authn_request_from_state(self, state):
232232
"""
233233
return AuthorizationRequest().deserialize(state[self.name]["oidc_request"])
234234

235-
def client_registration(self, context):
235+
def client_registration(self, context, **kwargs):
236236
"""
237237
Handle the OIDC dynamic client registration.
238238
:type context: satosa.context.Context
@@ -247,7 +247,7 @@ def client_registration(self, context):
247247
except InvalidClientRegistrationRequest as e:
248248
return BadRequest(e.to_json(), content="application/json")
249249

250-
def provider_config(self, context):
250+
def provider_config(self, context, **kwargs):
251251
"""
252252
Construct the provider configuration information (served at /.well-known/openid-configuration).
253253
:type context: satosa.context.Context
@@ -270,7 +270,7 @@ def _get_approved_attributes(self, provider_supported_claims, authn_req):
270270
requested_claims.extend(authn_req["claims"][k].keys())
271271
return set(provider_supported_claims).intersection(set(requested_claims))
272272

273-
def _handle_authn_request(self, context):
273+
def _handle_authn_request(self, context, **kwargs):
274274
"""
275275
Parse and verify the authentication request into an internal request.
276276
:type context: satosa.context.Context
@@ -315,7 +315,7 @@ def _handle_authn_request(self, context):
315315
authn_req))
316316
return internal_req
317317

318-
def handle_authn_request(self, context):
318+
def handle_authn_request(self, context, **kwargs):
319319
"""
320320
Handle an authentication request and pass it on to the backend.
321321
:type context: satosa.context.Context
@@ -329,7 +329,7 @@ def handle_authn_request(self, context):
329329
return internal_req
330330
return self.auth_req_callback_func(context, internal_req)
331331

332-
def jwks(self, context):
332+
def jwks(self, context, **kwargs):
333333
"""
334334
Construct the JWKS document (served at /jwks).
335335
:type context: satosa.context.Context
@@ -340,7 +340,7 @@ def jwks(self, context):
340340
"""
341341
return Response(json.dumps(self.provider.jwks), content="application/json")
342342

343-
def token_endpoint(self, context):
343+
def token_endpoint(self, context, **kwargs):
344344
"""
345345
Handle token requests (served at /token).
346346
:type context: satosa.context.Context
@@ -364,7 +364,7 @@ def token_endpoint(self, context):
364364
error_resp = TokenErrorResponse(error=e.oauth_error, error_description=str(e))
365365
return BadRequest(error_resp.to_json(), content="application/json")
366366

367-
def userinfo_endpoint(self, context):
367+
def userinfo_endpoint(self, context, **kwargs):
368368
headers = {"Authorization": context.request_authorization}
369369

370370
try:

Diff for: src/satosa/frontends/ping.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, auth_req_callback_func, internal_attributes, config, base_url
1919

2020
self.config = config
2121

22-
def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None):
22+
def handle_authn_response(self, context, internal_resp, extra_id_token_claims=None, **kwargs):
2323
"""
2424
See super class method satosa.frontends.base.FrontendModule#handle_authn_response
2525
:type context: satosa.context.Context
@@ -47,7 +47,7 @@ def register_endpoints(self, backend_names):
4747

4848
return url_map
4949

50-
def ping_endpoint(self, context):
50+
def ping_endpoint(self, context, **kwargs):
5151
"""
5252
"""
5353
logprefix = PingFrontend.logprefix

Diff for: src/satosa/frontends/saml2.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def __init__(self, auth_req_callback_func, internal_attributes, config, base_url
7878
self.KEY_CUSTOM_ATTR_RELEASE)
7979
self.idp = None
8080

81-
def handle_authn_response(self, context, internal_response):
81+
def handle_authn_response(self, context, internal_response, **kwargs):
8282
"""
8383
See super class method satosa.frontends.base.FrontendModule#handle_authn_response
8484
:type context: satosa.context.Context
@@ -87,7 +87,7 @@ def handle_authn_response(self, context, internal_response):
8787
"""
8888
return self._handle_authn_response(context, internal_response, self.idp)
8989

90-
def handle_authn_request(self, context, binding_in):
90+
def handle_authn_request(self, context, binding_in, **kwargs):
9191
"""
9292
This method is bound to the starting endpoint of the authentication.
9393
@@ -174,7 +174,7 @@ def _validate_config(self, config):
174174
except KeyError as e:
175175
raise ValueError("Missing configuration key: %s" % key) from e
176176

177-
def _handle_authn_request(self, context, binding_in, idp):
177+
def _handle_authn_request(self, context, binding_in, idp, **kwargs):
178178
"""
179179
See doc for handle_authn_request method.
180180
@@ -286,7 +286,7 @@ def _filter_attributes(self, idp, internal_response, context,):
286286

287287
return attributes
288288

289-
def _handle_authn_response(self, context, internal_response, idp):
289+
def _handle_authn_response(self, context, internal_response, idp, **kwargs):
290290
"""
291291
See super class satosa.frontends.base.FrontendModule
292292
@@ -425,7 +425,7 @@ def _handle_backend_error(self, exception, idp):
425425
satosa_logging(logger, logging.DEBUG, "HTTPargs: %s" % http_args, exception.state)
426426
return make_saml_response(resp_args["binding"], http_args)
427427

428-
def _metadata_endpoint(self, context):
428+
def _metadata_endpoint(self, context, **kwargs):
429429
"""
430430
Endpoint for retrieving the backend metadata
431431
:type context: satosa.context.Context
@@ -589,7 +589,7 @@ def _load_endpoints_to_config(self, provider, target_entity_id, config=None):
589589
idp_conf["service"]["idp"]["endpoints"][service] = idp_endpoints
590590
return idp_conf
591591

592-
def _load_idp_dynamic_endpoints(self, context):
592+
def _load_idp_dynamic_endpoints(self, context, **kwargs):
593593
"""
594594
Loads an idp server that accepts the target backend name in the endpoint url
595595
ex: /<backend_name>/sso/redirect
@@ -621,7 +621,7 @@ def _load_idp_dynamic_entity_id(self, state):
621621
idp_config = IdPConfig().load(idp_config_file, metadata_construction=False)
622622
return Server(config=idp_config)
623623

624-
def handle_authn_request(self, context, binding_in):
624+
def handle_authn_request(self, context, binding_in, **kwargs):
625625
"""
626626
Loads approved endpoints dynamically
627627
See super class satosa.frontends.saml2.SAMLFrontend#handle_authn_request
@@ -637,7 +637,7 @@ def handle_authn_request(self, context, binding_in):
637637
idp = self._load_idp_dynamic_endpoints(context)
638638
return self._handle_authn_request(context, binding_in, idp)
639639

640-
def _create_state_data(self, context, resp_args, relay_state):
640+
def _create_state_data(self, context, resp_args, relay_state, **kwargs):
641641
"""
642642
Adds the frontend idp entity id to state
643643
See super class satosa.frontends.saml2.SAMLFrontend#save_state
@@ -661,7 +661,7 @@ def handle_backend_error(self, exception):
661661
idp = self._load_idp_dynamic_entity_id(exception.state)
662662
return self._handle_backend_error(exception, idp)
663663

664-
def handle_authn_response(self, context, internal_response):
664+
def handle_authn_response(self, context, internal_response, **kwargs):
665665
"""
666666
See super class satosa.frontends.base.FrontendModule#handle_authn_response
667667
:param context:
@@ -708,7 +708,7 @@ class SAMLVirtualCoFrontend(SAMLFrontend):
708708
KEY_ORGANIZATION = 'organization'
709709
KEY_ORGANIZATION_KEYS = ['display_name', 'name', 'url']
710710

711-
def handle_authn_request(self, context, binding_in):
711+
def handle_authn_request(self, context, binding_in, **kwargs):
712712
"""
713713
See super class
714714
satosa.frontends.saml2.SAMLFrontend#handle_authn_request
@@ -723,7 +723,7 @@ def handle_authn_request(self, context, binding_in):
723723
idp = self._create_co_virtual_idp(context)
724724
return self._handle_authn_request(context, binding_in, idp)
725725

726-
def handle_authn_response(self, context, internal_response):
726+
def handle_authn_response(self, context, internal_response, **kwargs):
727727
"""
728728
See super class satosa.frontends.base.
729729
FrontendModule#handle_authn_response
@@ -734,7 +734,7 @@ def handle_authn_response(self, context, internal_response):
734734

735735
return self._handle_authn_response(context, internal_response)
736736

737-
def _handle_authn_response(self, context, internal_response):
737+
def _handle_authn_response(self, context, internal_response, **kwargs):
738738
"""
739739
"""
740740
# Using the context of the current request and saved state from the

0 commit comments

Comments
 (0)