Skip to content

Commit da3f4e7

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

27 files changed

+129
-116
lines changed

src/satosa/backends/base.py

Lines changed: 1 addition & 1 deletion
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

src/satosa/backends/github.py

Lines changed: 2 additions & 2 deletions
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))

src/satosa/backends/linkedin.py

Lines changed: 2 additions & 2 deletions
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))

src/satosa/backends/oauth.py

Lines changed: 2 additions & 2 deletions
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

src/satosa/backends/openid_connect.py

Lines changed: 2 additions & 2 deletions
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

src/satosa/backends/orcid.py

Lines changed: 1 addition & 1 deletion
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))

src/satosa/backends/saml2.py

Lines changed: 13 additions & 12 deletions
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

src/satosa/base.py

Lines changed: 1 addition & 1 deletion
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)

src/satosa/frontends/base.py

Lines changed: 1 addition & 1 deletion
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.

src/satosa/frontends/openid_connect.py

Lines changed: 8 additions & 8 deletions
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:

0 commit comments

Comments
 (0)