customization.rst 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. Customization
  2. =============
  3. Now that you've got django-browserid installed and configured, it's time to see
  4. how to customize it to your needs.
  5. Local Assertion Verification
  6. ----------------------------
  7. When a user authenticates via django-browserid, they do so by sending your site
  8. an assertion, which, when verified, gives you an email address for the user.
  9. Normally, this verification is handled by sending the assertion to a
  10. `verification service hosted by Mozilla`_.
  11. However, you can also verify assertions locally and avoid relying on the
  12. verification service. To do so, you must install PyBrowserID_. django-browserid
  13. checks for PyBrowserID, and if it is found, it enables the use of the
  14. :class:`LocalVerifier <django_browserid.LocalVerifier>` class.
  15. Once you've installed PyBrowserID, add the
  16. :class:`LocalBrowserIDBackend <django_browserid.auth.LocalBrowserIDBackend>`
  17. class to your ``AUTHENTICATION_BACKENDS`` setting:
  18. .. code-block:: python
  19. AUTHENTICATION_BACKENDS = (
  20. 'django_browserid.auth.LocalBrowserIDBackend',
  21. )
  22. .. note:: Because the BrowserID certificate format has not been finalized,
  23. PyBrowserID may fail to verify a valid assertion if the format
  24. changes. Be aware of the risks before enabling local verification.
  25. .. _`verification service hosted by Mozilla`: https://developer.mozilla.org/en-US/Persona/Remote_Verification_API
  26. .. _PyBrowserID: https://pypi.python.org/pypi/PyBrowserID/
  27. Customizing the Verify View
  28. ---------------------------
  29. Many common customizations involve overriding methods on the
  30. :class:`Verify <django_browserid.views.Verify>` class. But how do you use a
  31. custom ``Verify`` subclass?
  32. You can substitute a custom verification view by setting
  33. :attr:`BROWSERID_VERIFY_CLASS <django.conf.settings.BROWSERID_VERIFY_CLASS>` to
  34. the import path for your view:
  35. .. code-block:: python
  36. BROWSERID_VERIFY_CLASS = 'project.application.views.MyCustomVerifyClass'
  37. Customizing the Authentication Backend
  38. --------------------------------------
  39. Another common way to customize django-browserid is to subclass
  40. :class:`BrowserIDBackend <django_browserid.auth.BrowserIDBackend>`. To use a
  41. custom ``BrowserIDBackend`` class, simply use the python path to your custom
  42. class in the ``AUTHENTICATION_BACKENDS`` setting instead of the path to
  43. ``BrowserIDBackend``.
  44. Post-login Response
  45. -------------------
  46. After logging the user in, the default view redirects the user to
  47. :attr:`LOGIN_REDIRECT_URL <django.conf.settings.LOGIN_REDIRECT_URL>` or
  48. :attr:`LOGIN_REDIRECT_URL_FAILURE <django.conf.settings.LOGIN_REDIRECT_URL_FAILURE>`,
  49. depending on if login succeeded or failed. You can modify those settings to
  50. change where they are redirected to.
  51. .. note:: You can use ``django.core.urlresolvers.reverse_lazy`` to generate a
  52. URL for these settings from a URL pattern name or function name.
  53. You can also override the
  54. :attr:`success_url <django_browserid.views.Verify.success_url>` and
  55. :attr:`failure_url <django_browserid.views.Verify.failure_url>` properties on
  56. the ``Verify`` view if you need more control over how the redirect URLs are
  57. retrieved.
  58. If you need to control the entire response to the ``Verify`` view, such as when
  59. you're :ref:`using custom JavaScript <customjs>`, you'll want to override
  60. :attr:`login_success <django_browserid.views.Verify.login_success>`
  61. and :attr:`login_failure <django_browserid.views.Verify.login_failure>`.
  62. Automatic User Creation
  63. -----------------------
  64. If a user signs in with an email that doesn't match an existing user,
  65. django-browserid automatically creates a new User object for them that is tied
  66. to their email address. You can disable this behavior by setting
  67. :attr:`BROWSERID_CREATE_USER <django.conf.settings.BROWSERID_CREATE_USER>` to
  68. False, which will cause authentication to fail if a user signs in with an
  69. unrecognized email address.
  70. If you want to customize how new users are created (perhaps you want to
  71. generate a display name for them), you can override the
  72. :attr:`create_user <django_browserid.auth.BrowserIDBackend.create_user>` method
  73. on ``BrowserIDBackend``:
  74. .. code-block:: python
  75. from django_browserid.auth import BrowserIDBackend
  76. class CustomBackend(BrowserIDBackend):
  77. def create_user(self, email):
  78. username = my_custom_username_algo()
  79. return self.User.objects.create_user(username, email)
  80. .. note:: ``self.User`` points to the User model defined in
  81. ``AUTH_USER_MODEL`` for custom User model support. See `Custom User Models`_
  82. for more details.
  83. Limiting Authentication
  84. -----------------------
  85. There are two ways to limit who can authenticate with your site: prohibiting
  86. certain email addresses, or filtering the queryset that emails are compared to.
  87. filter_users_by_email
  88. ~~~~~~~~~~~~~~~~~~~~~
  89. :attr:`filter_users_by_email <django_browserid.auth.BrowserIDBackend.filter_users_by_email>`
  90. returns the queryset that is searched when looking for a user account that
  91. matches a user's email. Overriding this allows you to limit the set of users
  92. that are searched:
  93. .. code-block:: python
  94. from django_browserid.auth import BrowserIDBackend
  95. class CustomBackend(BrowserIDBackend):
  96. def filter_users_by_email(self, email):
  97. # Only allow staff users to login.
  98. return self.User.objects.filter(email=email, is_staff=True)
  99. .. note:: If you customize ``filter_users_by_email``, you should probably make
  100. sure that `Automatic User Creation`_ is either disabled or customized to
  101. only create users that match your limited set.
  102. is_valid_email
  103. ~~~~~~~~~~~~~~
  104. :attr:`is_valid_email <django_browserid.auth.BrowserIDBackend.is_valid_email>`
  105. determines if the email a user attempts to log in with is considered valid.
  106. Override this to exclude users with certain emails:
  107. from django_browserid.auth import BrowserIDBackend
  108. class CustomBackend(BrowserIDBackend):
  109. def is_valid_email(self, email):
  110. # Ignore users from fakeemails.com
  111. return not email.endswith('@fakeemails.com')
  112. Custom User Models
  113. ------------------
  114. Django allows you to `use a custom User model for authentication
  115. <https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model>`_. If you are using a custom User model, and the model has
  116. an ``email`` attribute that can store email addresses, django-browserid should
  117. work out-of-the-box for you.
  118. If this isn't the case, then you will probably have to override the
  119. :attr:`is_valid_email <django_browserid.auth.BrowserIDBackend.is_valid_email>`,
  120. :attr:`filter_users_by_email <django_browserid.auth.BrowserIDBackend.filter_users_by_email>`,
  121. and :attr:`create_user <django_browserid.auth.BrowserIDBackend.create_user>`
  122. methods to work with your custom User class.
  123. .. _custom_user_model: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model
  124. .. _customjs:
  125. Using the JavaScript API
  126. ------------------------
  127. django-browserid comes with two JavaScript files to include in your webpage:
  128. 1. ``api.js``: An API for triggering logins via BrowserID and verifying
  129. assertions via the server.
  130. 2. ``browserid.js``: A basic example of hooking up links with the JavaScript
  131. API.
  132. ``browserid.js`` only covers basic use cases. If your site has more complex
  133. behavior behind trigger login, you should replace ``browserid.js`` in your
  134. templates with your own JavaScript file that uses the django-browserid
  135. JavaScript API.
  136. .. seealso::
  137. :js:data:`JavaScript API <django_browserid>`
  138. API Documentation for ``api.js``.
  139. Django Admin Support
  140. --------------------
  141. If you want to use BrowserID for login on the built-in Django admin interface,
  142. you must use the
  143. :data:`django-browserid admin site <django_browserid.admin.site>` instead of
  144. the default Django admin site:
  145. .. code-block:: python
  146. from django.contrib import admin
  147. from django_browserid.admin import site as browserid_admin
  148. from myapp.foo.models import Bar
  149. class BarAdmin(admin.ModelAdmin):
  150. pass
  151. browserid_admin.register(Bar, BarAdmin)
  152. You must also use the django-browserid admin site in your ``urls.py`` file:
  153. .. code-block:: python
  154. from django.conf.urls import patterns, include, url
  155. # Autodiscover admin.py files in your project.
  156. from django.contrib import admin
  157. admin.autodiscover()
  158. # copy_registry copies ModelAdmins registered with the default site, like
  159. # the built-in Django User model.
  160. from django_browserid.admin import site as browserid_admin
  161. browserid_admin.copy_registry(admin.site)
  162. urlpatterns = patterns('',
  163. # ...
  164. url(r'^admin/', include(browserid_admin.urls)),
  165. )
  166. .. seealso::
  167. :class:`django_browserid.admin.BrowserIDAdminSite`
  168. API documentation for BrowserIDAdminSite, including how to customize the
  169. login page (such as including a normal login alongside BrowserID login).
  170. Alternative Template Languages
  171. ------------------------------
  172. By default, django-browserid supports use in Django templates as well as use in
  173. Jinja2_ templates via the jingo_ library. Template helpers are registered as
  174. helper functions with jingo, so you can use them directly in Jinja2 templates:
  175. .. code-block:: jinja
  176. <div class="authentication">
  177. {% if user.is_authenticated() %}
  178. {{ browserid_logout(text='Logout') }}
  179. {% else %}
  180. {{ browserid_login(text='Login', color='dark') }}
  181. {% endif %}
  182. </div>
  183. {{ browserid_js() }}
  184. For other libraries or template languages, you will have to register the
  185. django-browserid helpers manually. The relevant helper functions can be found
  186. in the :py:mod:`django_browserid.helpers` module.
  187. .. _Jinja2: http://jinja.pocoo.org/
  188. .. _jingo: https://github.com/jbalogh/jingo