Files changed (3)
+This is the implementation of a `Django <http://www.djangoproject.com/>`_ authentication backend for OpenID, based on the openid2rp package. It is automatically installed together with openid2rp.
+In contrast to most (all ?) other Django OpenID authentication packages, this one does not try to cover any view aspects. All error cases are reported by exceptions, which you can render in whatever way you prefer.
-Since the Django authentication framework is not prepared for a multi-step auth scenario with several
-Session storage is based on a module-scope variable. I was to lazy to decode the openid2rp session dict
+In your original login view code, call ``openid2rp_django.auth.preAuthenticate`` instead of Django's ``authenticate`` if you want to perform an OpenID authentication. Input parameters are the user-provided OpenID URI, and the (absolute !) URL of the newly created view. The results of this call are an ``HttpResponse`` object you must return as view result, and the normalized OpenID URI ('claim') you must store in the user session.
+After authentication, the provider will send the users browser back to your newly created second login view. Call Django's ``authenticate`` in there with two keyword arguments for the request object and the claim stored in the session. The result is a Django ``User`` object (if a user record in the database has this claim attached), a Django ``AnonymousUser`` object (if the claim could not be found, but OpenID authentication was ok), or an Exception if anything went wrong. In the second case, you might offer some user registration facility. You can use ``openid2rp_django.auth.linkOpenID`` to assign claims to Django user objects, so that ``authenticate`` is successfull the next time.
+.. function:: openid2rp_django.auth.preAuthenticate(uri, answer_url, sreg = (('nickname', 'email'), ()), ax = ((openid2rp.AX.email, openid2rp.AX.first, openid2rp.AX.last), ())) -> response, claimedID
+``uri`` is the OpenID URI input from the user. ``answer_url`` is the absolute address of the view that will later call ``authenticate()``. You can realize this view in whatever way you prefer, for example also by using the original login view with another GET parameter. ``sreg`` resp. ``ax`` allow you to request a set of information attributes from the authentication provider. Check the openid2rp and OpenID documentation for details.
+The first result is the ``HttpResponse`` object you should directly return from the view code after calling ``preAuthenticate``. It contains a 307 redirection to the authentication provider URL, so that the user's browser goes forward to the actual provider authentication screen. The second result is the normalized version of the OpenID URI, called a 'claim'. You need this in the following call to ``authenticate()``, so store it somewhere (e.g. in the user session).
+* ``IncorrectClaimError``: The OpenID discovery step for this claim failed. This might be a typo, but can also be reasoned by an unavailable provider.
+In the handling of the providers redirection back to your site, you need to call Django's ``authenticate`` function with two keyword parameters. ``request`` is the ``HttpRequest`` input object for your view code. The authentication provider fetches all relevant information from it. The second parameter must be ``claim``, which is one of the results from ``preAuthenticate`` we asked you to store somewhere.
+* A Django ``User`` object. In this case, the OpenID claim was successfully authenticated, and the backend found a user in the database with this claim attached. The object as additional attributes:
+ * ``openid_claim``: The claim that was finally authenticated. Depending on the OpenID provider, this might or might not be the original method input. In a later call to ``linkOpenID``, use only this one.
+* A Django ``AnonymousUser`` object. In this case, the claim could not be related to any user in the database, but the OpenID authentication was ok. The object has the same additional attributes as above. In this situation, you should normally proceed with some new user registration functionality. You can use the AX / SREG data to pre-fill some registration form.
+ * ``MissingSessionError``: There is no stored session for this result. This typically means that you forgot to start with ``preAuthenticate``.
+ * ``AuthenticationError``: Something went wrong in the OpenID authentication process. The exception message contains more information.
+ * ``MultipleClaimUsageError``: The authenticated claim was linked to multiple users, which is not valid. You need to correct your database.
+ * ``ReplayAttackError``: The nonce checking mechanisms identified an answer that was already given before.
+ * ``TookTooLongError``: The authentication at the provider side took too long. You can override the default value (5 min) in your settings file with the parameter ``OPENID2RP_MAXLOGINDELAY``.
+Returns a string list of stored OpenID claim URIs for this Django user object. This is intended for your user settings view.
+Unlinks the given Django user object from the given OpenID claim. This is intended for your user settings view.
+The openid2rp package also provides a Django authentication backend, which is described separately:
# we need to accept some difference between provider time and our time, for nonce and session checking
- finished, and the sreg / ax parameters as with the original openid2rp.request_authentication() call.
- - request: Django request object, which has all the GET parameters being given by the OpenID provider
- - openid_claim: The real claimId string for this user. You might want to use that in the storeID() call.
- If you get an AnonymousUser object as result, you need to assign the returned claim string first to some
- form. If you somehow came to a Django user object for the returned claim string, use the storeID() call.
- Possible errors: MissingSession, AuthenticationError, IncompleteAnswer, MultipleClaimUsage, ReplayAttackError
- # provider timestamp was signed (=not forged), with replay, it would be too old; consider time shift
# provider-based auth returns claim id, OpenID not (if I got that right) - in this case we take the original value