# HG changeset patch
# User Paul Boddie <paul@boddie.org.uk>
# Date 1299970091 -3600
# Node ID 3931b6a8b535c151d17b8969fe8da64c6e88ecdd
# Parent  45714fde847dbbd79fb2d0189da374cc320c9d9b
Introduced the invalidation of associations where the endpoint to be returned in
a response is different from the endpoint for the page being used to handle
OpenID requests. This changing endpoint behaviour occurs when an "identifier
select" request is handled by the front page of a Wiki, where an
identity-specific endpoint is then returned, confusing relying parties which
store their associations in endpoint-specific mappings (as is done by the
python-openid library).

diff -r 45714fde847d -r 3931b6a8b535 MoinMoin/action/serveopenid.py
--- a/MoinMoin/action/serveopenid.py	Mon Mar 07 20:39:30 2011 +0100
+++ b/MoinMoin/action/serveopenid.py	Sat Mar 12 23:48:11 2011 +0100
@@ -16,7 +16,7 @@
 from openid import sreg
 from openid.cryptutil import randomString
 from openid.server import server
-from openid.message import IDENTIFIER_SELECT
+from openid.message import IDENTIFIER_SELECT, OPENID_NS
 from MoinMoin.widget import html
 from MoinMoin.web.request import MoinMoinFinish
 
@@ -301,7 +301,24 @@
         #       sreg_resp = sreg.SRegResponse.extractResponse(openidreq, sreg_data)
         #       sreg_resp.addToOpenIDResponse(reply.fields)
 
-        reply = openidreq.answer(True, identity=identity, server_url=server_url)
+        request = self.request
+
+        # obtain the endpoint if not overridden by an identity endpoint
+        page_url = request.getQualifiedURL(
+                         request.page.url(request, querystr={'action': 'serveopenid'}))
+        endpoint_changed = server_url != page_url
+
+        # prepare the response
+        reply = openidreq.answer(True, identity=identity, server_url=server_url or page_url)
+
+        # if the endpoint has changed, perhaps reflecting an identity-specific
+        # endpoint, remove any association handle in use, working around any
+        # association-related issues in relying parties (such as python-openid)
+        if openidreq.assoc_handle and endpoint_changed:
+            store = MoinOpenIDStore(request)
+            signatory = server.Signatory(store)
+            reply.fields.setArg(OPENID_NS, "invalidate_handle", openidreq.assoc_handle)
+            signatory.invalidate(openidreq.assoc_handle, dumb=False)
         return reply
 
     def user_trusts_url(self, trustroot):
