Commits

ja...@nottheoilrig.com  committed 83df38b

Prevent a malicious user who controls an OP-local identifier from impersonating claimed identifiers that the OP is authorized to make assertions about, but that the user doesn't control.

  • Participants
  • Parent commits ea0a2f5

Comments (0)

Files changed (1)

File openid2rp/testapp.py

     ('Launchpad', 'https://login.launchpad.net/favicon.ico', 'https://login.launchpad.net/')
     )
              
-# Mapping from Claimed Identifier to OP Endpoint URL.  Always updated on
-# initiation (end user enters User-Supplied Identifier) and used to avoid
-# repeating discovery when verifying assertions.  When verifying assertions, OP
-# Endpoint URL is used to get an association if one is stored, and to perform
-# Direct Verification otherwise
+# Mapping from Claimed Identifier to OP Endpoint URL and OP-Local Identifier.
+# Always updated on initiation (end user enters User-Supplied Identifier) and
+# used to avoid repeating discovery when verifying assertions.  When verifying
+# assertions, OP Endpoint URL is used to get an association if one is stored,
+# and to perform Direct Verification otherwise.  OP-Local Identifier is used to
+# prevent a malicious user from impersonating Claimed Identifiers that the OP
+# is authorized to make assertions about, but that the user doesn't control
 disco = {}
 
 # Mapping from OP Endpoint URL and association handle to association response
                 services, url, op_local = res
 
                 # Avoid repeating discovery when verifying assertions
-                disco[claimed] = url
+                disco[claimed] = url, op_local or claimed
 
                 try:
                     session = associate(services, url)
                 # Claimed Identifier in the response to make sure that the OP
                 # is authorized to make assertions about the Claimed Identifier
                 try:
-                    op_endpoint = disco[no_fragment]
+                    disco_endpoint, disco_identity = disco[no_fragment]
                 except KeyError:
-                    _, op_endpoint, _ = discover(no_fragment)
+                    _, disco_endpoint, disco_identity = discover(no_fragment)
+                    if not disco_identity:
+                        disco_identity = no_fragment
+
+                # Prevent a malicious user who controls an OP-Local Identifier
+                # from impersonating Claimed Identifiers that the OP is
+                # authorized to make assertions about, but that the user
+                # doesn't control.  A user who controls an OP-Local Identifier
+                # can obtain assertions from the OP about Claimed Identifiers
+                # that the user doesn't control
+                identity, = query['openid.identity']
+                if disco_identity != identity:
+                    return self.error('OP-Local Identifier in the assertion not present in the discovered information')
 
                 # If the RP has stored an association with the association
                 # handle specified in the assertion, it MUST check the
                 # signature via Direct Verification
                 handle = query['openid.assoc_handle'][0]
                 try:
-                    session = sessions[op_endpoint, handle]
+                    session = sessions[disco_endpoint, handle]
                 except KeyError:
                     try:
-                        verify_signature_directly(op_endpoint, query)
+                        verify_signature_directly(disco_endpoint, query)
                     except Exception, e:
                         return self.error('Authentication failed: '+repr(e))
                     signed, = query['openid.signed']