This repository has been archived by the owner on Jul 24, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[project @ Added document about making associations offline]
- Loading branch information
Josh Hoyt
committed
Feb 16, 2007
1 parent
8b513bf
commit 2b44497
Showing
1 changed file
with
96 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
Background association requests | ||
############################### | ||
|
||
This document describes how to make signing in with OpenID faster for | ||
users of your application by never making the users wait for an | ||
association to be made, but using associations when they're | ||
available. Most OpenID libraries and applications attempt to make | ||
associations during the discovery phase of the OpenID authentication | ||
request. Because association requests may have to do Diffie-Hellman | ||
key exchange, which is time consuming. Even if Diffie-Hellman key | ||
exchange is not used, the user still needs to wait for the association | ||
request. | ||
|
||
Setting up your application to make associations in the background | ||
================================================================== | ||
|
||
When making associations background, there are two components that | ||
need access to the OpenID association store: the consumer application | ||
and the background association fetcher. The consumer needs to be set | ||
up to record the server URL for any request for which an association | ||
does not exist or is expired instead of making a new association. The | ||
background fetcher looks at the server URL queue and makes | ||
associations for any server URLs that need them. After the | ||
associations are made, the consumer will use them until they expire | ||
again. While associations are expired or missing, the consumer will | ||
use stateless mode to complete authentications with the servers that | ||
need associations. | ||
|
||
The OpenID server endpoint URL queue | ||
----------------------------------------------------------------- | ||
|
||
You will have to set up a conduit between the consumer and the | ||
background association fetcher so that the background association | ||
fetcher knows what servers need associations. The background | ||
association fetcher will not fetch associations for servers that | ||
already have them, so the queue does not have to be very smart. It | ||
could be as simple as a file to which the server URLs are | ||
appended. Either way, the queue needs to be write-able by the consumer | ||
and readable by the background fetcher. | ||
|
||
Configuring the consumer | ||
----------------------------------------------------------------- | ||
|
||
Create a subclass of ``GenericConsumer`` that overrides | ||
``_negotiateAssociation`` so that it just records the server URL that | ||
needs an association:: | ||
|
||
from openid.consumer.consumer import GenericConsumer, Consumer | ||
|
||
class LazyAssociationConsumer(GenericConsumer): | ||
needs_assoc_file = None | ||
|
||
def _negotiateAssociation(self, endpoint): | ||
# Do whatever you need to do here to send the server_url to | ||
# the queue. This example just appends it to a file. | ||
self.needs_assoc_file.write(endpoint.server_url + '\n') | ||
self.needs_assoc_file.flush() | ||
|
||
You could also store the whole endpoint object. When you instantiate | ||
the consumer, pass this generic consumer class to the controlling | ||
consumer:: | ||
|
||
return Consumer(session, store, consumer_class=LazyAssociationConsumer) | ||
|
||
The background association fetcher | ||
----------------------------------------------------------------- | ||
|
||
The background association fetcher is just a script that should be | ||
added to ``cron`` or triggered periodically. If you are ambitious, you | ||
could make the background fetcher listen for inserts into the queue. | ||
|
||
The background fetcher needs to do something similar to the following:: | ||
|
||
def refresh(consumer, endpoint): | ||
if consumer.store.getAssociation(endpoint.server_url): | ||
logging.info("We don't need to associate with %r", endpoint.server_url) | ||
return | ||
|
||
logging.info("Associating with %r", endpoint.server_url) | ||
now = time.time() | ||
assoc = consumer._negotiateAssociation(endpoint) | ||
if assoc: | ||
elapsed = time.time() - now | ||
logging.info('(%0.2f seconds) Associated with %r', elapsed, | ||
endpoint.server_url) | ||
consumer.store.storeAssociation(endpoint.server_url, assoc) | ||
else: | ||
logging.error('Failed to make an association with %r', | ||
endpoint.server_url) | ||
|
||
The code in this example logs the amount of time that the association | ||
request took. This is time that the user would have been waiting. The | ||
``consumer`` in this example is a standard consumer, not the | ||
``LazyAssociationConsumer`` that was defined in the section | ||
above. This is important, because the lazy consumer above will not | ||
actually make any associations. |