Skip to content

Commit 4e660fe

Browse files
Merge pull request #616 from SUNET/eduid-nameid_fixes
Check for an existing local-persistent NameID when retrieving it
2 parents 20de055 + 70084f5 commit 4e660fe

File tree

5 files changed

+44
-10
lines changed

5 files changed

+44
-10
lines changed

src/saml2/client_base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ def create_authn_request(self, destination, vorg="", scoping=None,
339339
# If no nameid_format has been set in the configuration
340340
# or passed in then transient is the default.
341341
if nameid_format is None:
342+
# SAML 2.0 errata says AllowCreate MUST NOT be used for
343+
# transient ids - to make a conservative change this is
344+
# only applied for the default cause
345+
allow_create = None
342346
nameid_format = NAMEID_FORMAT_TRANSIENT
343347

344348
# If a list has been configured or passed in choose the

src/saml2/ident.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ def remove_local(self, sid):
155155
pass
156156

157157
def get_nameid(self, userid, nformat, sp_name_qualifier, name_qualifier):
158+
if nformat == NAMEID_FORMAT_PERSISTENT:
159+
nameid = self.match_local_id(userid, sp_name_qualifier, name_qualifier)
160+
if nameid:
161+
logger.debug(
162+
"Found existing persistent NameId {nid} for user {uid}".format(
163+
nid=nameid, uid=userid
164+
)
165+
)
166+
return nameid
167+
158168
_id = self.create_id(nformat, name_qualifier, sp_name_qualifier)
159169

160170
if nformat == NAMEID_FORMAT_EMAILADDRESS:
@@ -163,11 +173,12 @@ def get_nameid(self, userid, nformat, sp_name_qualifier, name_qualifier):
163173

164174
_id = "%s@%s" % (_id, self.domain)
165175

166-
# if nformat == NAMEID_FORMAT_PERSISTENT:
167-
# _id = userid
168-
169-
nameid = NameID(format=nformat, sp_name_qualifier=sp_name_qualifier,
170-
name_qualifier=name_qualifier, text=_id)
176+
nameid = NameID(
177+
format=nformat,
178+
sp_name_qualifier=sp_name_qualifier,
179+
name_qualifier=name_qualifier,
180+
text=_id,
181+
)
171182

172183
self.store(userid, nameid)
173184
return nameid
@@ -236,7 +247,7 @@ def nim_args(self, local_policy=None, sp_name_qualifier="",
236247
def construct_nameid(self, userid, local_policy=None,
237248
sp_name_qualifier=None, name_id_policy=None,
238249
name_qualifier=""):
239-
""" Returns a name_id for the object. How the name_id is
250+
""" Returns a name_id for the userid. How the name_id is
240251
constructed depends on the context.
241252
242253
:param local_policy: The policy the server is configured to follow

src/saml2/mongo_store.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from pymongo.mongo_replica_set_client import MongoReplicaSetClient
66
import pymongo.uri_parser
77
import pymongo.errors
8+
from saml2.saml import NAMEID_FORMAT_PERSISTENT
9+
810
from saml2.eptid import Eptid
911
from saml2.mdstore import InMemoryMetaData
1012
from saml2.mdstore import metadata_modules
@@ -163,6 +165,23 @@ def find_local_id(self, name_id):
163165
return item[self.mdb.primary_key]
164166
return None
165167

168+
def match_local_id(self, userid, sp_name_qualifier, name_qualifier):
169+
"""
170+
Match a local persistent identifier.
171+
172+
Look for an existing persistent NameID matching userid,
173+
sp_name_qualifier and name_qualifier.
174+
"""
175+
filter = {
176+
"name_id.sp_name_qualifier": sp_name_qualifier,
177+
"name_id.name_qualifier": name_qualifier,
178+
"name_id.format": NAMEID_FORMAT_PERSISTENT,
179+
}
180+
res = self.mdb.get(value=userid, **filter)
181+
if not res:
182+
return None
183+
return from_dict(res[0]["name_id"], ONTS, True)
184+
166185
def remove_remote(self, name_id):
167186
cnid = to_dict(name_id, MMODS, True)
168187
self.mdb.remove(name_id=cnid)

tests/test_50_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ def test_parse_ok_request(self):
267267
assert resp_args["destination"] == "http://lingon.catalogix.se:8087/"
268268
assert resp_args["in_response_to"] == "id1"
269269
name_id_policy = resp_args["name_id_policy"]
270-
assert _eq(name_id_policy.keyswv(), ["format", "allow_create"])
270+
assert _eq(name_id_policy.keyswv(), ["format"])
271271
assert name_id_policy.format == saml.NAMEID_FORMAT_TRANSIENT
272272
assert resp_args[
273273
"sp_entity_id"] == "urn:mace:example.com:saml:roland:sp"
@@ -1341,7 +1341,7 @@ def test_parse_ok_request(self):
13411341
assert resp_args["destination"] == "http://lingon.catalogix.se:8087/"
13421342
assert resp_args["in_response_to"] == "id1"
13431343
name_id_policy = resp_args["name_id_policy"]
1344-
assert _eq(name_id_policy.keyswv(), ["format", "allow_create"])
1344+
assert _eq(name_id_policy.keyswv(), ["format"])
13451345
assert name_id_policy.format == saml.NAMEID_FORMAT_TRANSIENT
13461346
assert resp_args[
13471347
"sp_entity_id"] == "urn:mace:example.com:saml:roland:sp"

tests/test_51_client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def test_create_auth_request_0(self):
269269
assert ar.provider_name == "urn:mace:example.com:saml:roland:sp"
270270
assert ar.issuer.text == "urn:mace:example.com:saml:roland:sp"
271271
nid_policy = ar.name_id_policy
272-
assert nid_policy.allow_create == "false"
272+
assert nid_policy.allow_create is None
273273
assert nid_policy.format == saml.NAMEID_FORMAT_TRANSIENT
274274

275275
node_requested_attributes = None
@@ -1757,7 +1757,7 @@ def test_create_auth_request_0(self):
17571757
assert ar.provider_name == "urn:mace:example.com:saml:roland:sp"
17581758
assert ar.issuer.text == "urn:mace:example.com:saml:roland:sp"
17591759
nid_policy = ar.name_id_policy
1760-
assert nid_policy.allow_create == "false"
1760+
assert nid_policy.allow_create is None
17611761
assert nid_policy.format == saml.NAMEID_FORMAT_TRANSIENT
17621762

17631763
node_requested_attributes = None

0 commit comments

Comments
 (0)