Skip to content

Commit 8067f39

Browse files
author
ivan
committed
Add requested authn context for backend requests
Use acr_mapping from the backend config to generate a RequestedAuthnContext node in an AuthnRequest. acr_mapping configuration is extended so that each entry is a dictionary with two possible keys: - class_ref: defines the content of the AuthnContextClassRef node - comparison: defines the Comparison attribute
1 parent 3be975e commit 8067f39

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

src/satosa/backends/saml2.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
from saml2.config import SPConfig
1313
from saml2.extension.ui import NAMESPACE as UI_NAMESPACE
1414
from saml2.metadata import create_metadata_string
15+
from saml2.authn_context import requested_authn_context
1516

17+
import satosa.util as util
1618
from satosa.base import SAMLBaseModule
1719
from .base import BackendModule
1820
from ..exception import SATOSAAuthenticationError
@@ -23,7 +25,6 @@
2325
ContactPersonDesc, UIInfoDesc)
2426
from ..response import SeeOther, Response
2527
from ..saml_util import make_saml_response
26-
from ..util import rndstr
2728

2829
logger = logging.getLogger(__name__)
2930

@@ -32,6 +33,8 @@ class SAMLBackend(BackendModule, SAMLBaseModule):
3233
"""
3334
A saml2 backend module (acting as a SP).
3435
"""
36+
VALUE_ACR_CLASS_REF_DEFAULT = 'http://eidas.europa.eu/LoA/low'
37+
VALUE_ACR_COMPARISON_DEFAULT = 'minimum'
3538

3639
def __init__(self, outgoing, internal_attributes, config, base_url, name):
3740
"""
@@ -56,6 +59,7 @@ def __init__(self, outgoing, internal_attributes, config, base_url, name):
5659
self.config = config
5760
self.attribute_profile = config.get("attribute_profile", "saml")
5861
self.discosrv = config.get("disco_srv")
62+
self.acr_mapping = config.get("acr_mapping")
5963
self.encryption_keys = []
6064
self.outstanding_queries = {}
6165

@@ -109,6 +113,27 @@ def disco_query(self):
109113
loc = self.sp.create_discovery_service_request(self.discosrv, self.sp.config.entityid, **{"return": return_url})
110114
return SeeOther(loc)
111115

116+
def construct_requested_authn_context(self, entity_id):
117+
if not self.acr_mapping:
118+
return None
119+
120+
acr_entry = util.get_dict_defaults(self.acr_mapping, entity_id)
121+
if not acr_entry:
122+
return None
123+
124+
if type(acr_entry) is not dict:
125+
acr_entry = {
126+
"class_ref": acr_entry,
127+
"comparison": self.VALUE_ACR_COMPARISON_DEFAULT,
128+
}
129+
130+
authn_context = requested_authn_context(
131+
acr_entry.get('class_ref', self.VALUE_ACR_CLASS_REF_DEFAULT),
132+
comparison=acr_entry.get(
133+
'comparison', self.VALUE_ACR_COMPARISON_DEFAULT))
134+
135+
return authn_context
136+
112137
def authn_request(self, context, entity_id):
113138
"""
114139
Do an authorization request on idp with given entity id.
@@ -122,14 +147,20 @@ def authn_request(self, context, entity_id):
122147
:param entity_id: Target IDP entity id
123148
:return: response to the user agent
124149
"""
150+
kwargs = {}
151+
authn_context = self.construct_requested_authn_context(entity_id)
152+
if authn_context:
153+
kwargs['requested_authn_context'] = authn_context
154+
125155
try:
126156
binding, destination = self.sp.pick_binding(
127157
"single_sign_on_service", None, "idpsso", entity_id=entity_id)
128158
satosa_logging(logger, logging.DEBUG, "binding: %s, destination: %s" % (binding, destination),
129159
context.state)
130160
acs_endp, response_binding = self.sp.config.getattr("endpoints", "sp")["assertion_consumer_service"][0]
131-
req_id, req = self.sp.create_authn_request(destination, binding=response_binding)
132-
relay_state = rndstr()
161+
req_id, req = self.sp.create_authn_request(
162+
destination, binding=response_binding, **kwargs)
163+
relay_state = util.rndstr()
133164
ht_args = self.sp.apply_binding(binding, "%s" % req, destination, relay_state=relay_state)
134165
satosa_logging(logger, logging.DEBUG, "ht_args: %s" % ht_args, context.state)
135166
except Exception as exc:

0 commit comments

Comments
 (0)