# HG changeset patch
# User Paul Boddie <paul@boddie.org.uk>
# Date 1299970091 -3600
# Node ID 81e2a354edeb99161e987e57ede643310fc49732
# Parent  c946edb45d5fe4daae4eb1df363db838c4a1520f
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 c946edb45d5f -r 81e2a354edeb MoinMoin/action/serveopenid.py
--- a/MoinMoin/action/serveopenid.py	Sat Mar 12 21:00:51 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.request import MoinMoinFinish
 
@@ -309,7 +309,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):
