Permalink
Browse files

Updating README. Adding warning when SITE_URL doesn't look right.

  • Loading branch information...
1 parent c0c5d6e commit c0dcead75767087f2bb7024db451b5207547f78d @ozten ozten committed Dec 1, 2011
Showing with 69 additions and 30 deletions.
  1. +8 −2 CHANGELOG.rst
  2. +38 −20 README.rst
  3. +21 −7 django_browserid/auth.py
  4. +2 −1 django_browserid/tests/test_verification.py
View
@@ -1,9 +1,15 @@
CHANGELOG
---------
-0.9.2 - *NOTE* get_audience API breakage - Train 2011-10-20 now accepts the scheme and port number as part of the audience.
+0.9.2a - **API breakage** - BrowserID Train 2011-10-20 now accepts the scheme and port number as part of the audience.
- get_audience(self, host, port) has become get_audience(self, request, host, port)
+ ``get_audience(host, port)`` has become ``get_audience(request)``
+ ``authenticate(assertion, host, port)`` has become ``authenticate(assertion, audience)``
+
+ ``verify`` has been updated, so if you use the basic integration with browserid_verify, you should be fine. This mainly
+ breaks sites that have custom account creation or use the ``auth.authenticate`` function.
+
+ To improve security, you should add ``SITE_URL`` to your Django settings. See README.rst for details.
0.9.1 - Create User refactoring, navigator.id, httplib2/verify fixes
View
@@ -62,21 +62,6 @@ You can also set the following optional config in ``settings.py``
# Path to redirect to on unsuccessful login attempt.
LOGIN_REDIRECT_URL_FAILURE = '/'
-Unless your really noodling around with BrowserID, you probably won't need these
-optional config in ``settings.py`` (they have sensible defaults): ::
-
- # URL of a BrowserID verification service.
- BROWSERID_VERIFICATION_URL = 'https://browserid.org/verify'
-
- # Proxy Info, see httplib2 documentation
- BROWSERID_PROXY_INFO = None
-
- # CA cert file for validating SSL certificate
- BROWSERID_CACERT_FILE = None
-
- # Disable SSL cert validation
- BROWSERID_DISABLE_CERT_CHECK = False
-
# Create user accounts automatically if no user is found.
BROWSERID_CREATE_USER = True
@@ -115,12 +100,27 @@ Finally, you'll need some Javascript to handle the onclick event. If you use ``d
});
});
+Automatic Account Creation
+--------------------------
+
+``django-browserid`` will automatically create a user account for new users if the setting ``BROWSERID_CREATE_USER`` is set to ``True`` in ``settings.py``. The user account will be created with the verified email returned from the BrowserID verification service, and a URL safe base64 encoded SHA1 of the email with the padding removed as the username.
+
+To provide a customized username, you can provide a different algorytm via your settings.py. ::
+
+ # settings.py
+ BROWSERID_CREATE_USER = True
+ def username(email):
+ return email.split('@')[0]
+ BROWSERID_USERNAME_ALGO = username
+
+You can __disable account creation__, but continue to use the ``browserid_verify`` view to authenticate existing users with the following: ::
+
+ BROWSERID_CREATE_USER = False
+
Creating User Accounts
----------------------
-``django-browserid`` will automatically create a user account for new users if the setting ``BROWSERID_CREATE_USER`` is set to ``True`` in ``settings.py``. The user account will be created with the verified email returned from the BrowserID verification service, and a URL safe base64 encoded SHA1 of the email with the padding removed as the username.
-
-If you do not wish to automatically create user accounts, you may manually verify a BrowserID assertion with something like the following: ::
+If you want full control over account creation, don't use django-browserid's browserid_verify view. Create your own view and use ``verify`` to manually verify a BrowserID assertion with something like the following: ::
from django_browserid.auth import get_audience, verify
from django_browserid.forms import BrowserIDForm
@@ -131,12 +131,12 @@ If you do not wish to automatically create user accounts, you may manually verif
if request.method == 'POST':
form = BrowserIDForm(data=request.POST)
if not form.is_valid():
- result = verify(form.cleaned_data['assertion'], get_audience())
+ result = verify(form.cleaned_data['assertion'], get_audience(request))
if result:
# check for user account, create account for new users, etc
user = my_get_or_create_user(result.email)
-``result`` will be False if the assertion failed, or a dictionary similar to the following: ::
+``result`` will be ``False`` if the assertion failed, or a dictionary similar to the following: ::
{
u'audience': u'https://mysite.com:443',
@@ -148,6 +148,24 @@ If you do not wish to automatically create user accounts, you may manually verif
You are of course then free to store the email in the session and prompt the user to sign up using a chosen identifier as their username, or whatever else makes sense for your site.
+Obscure Options
+-------
+
+Unless your really noodling around with BrowserID, you probably won't need these
+optional config in ``settings.py`` (they have sensible defaults): ::
+
+ # URL of a BrowserID verification service.
+ BROWSERID_VERIFICATION_URL = 'https://browserid.org/verify'
+
+ # Proxy Info, see httplib2 documentation
+ BROWSERID_PROXY_INFO = None
+
+ # CA cert file for validating SSL ceprtificate
+ BROWSERID_CACERT_FILE = None
+
+ # Disable SSL cert validation
+ BROWSERID_DISABLE_CERT_CHECK = False
+
License
-------
View
@@ -47,30 +47,44 @@ def get_audience(request):
"""
site_url = getattr(settings, 'SITE_URL', False)
+ # Note audience based on request for developer warnings
+ if request.is_secure():
+ req_proto = 'https://'
+ else:
+ req_proto = 'http://'
+ req_domain = request.get_host()
+
# If we don't define it explicitly
if not site_url:
- if request.is_secure():
- req_proto = 'https://'
- else:
- req_proto = 'http://'
protocol = getattr(settings, 'PROTOCOL', req_proto)
- req_domain = request.get_host()
if not getattr(settings, 'DOMAIN'):
log.warning('django-browserid WARNING you are missing '
'settings.SITE_URL. This is not a secure way '
'to verify assertions. Please fix me. '
'Setting domain to %s.' % req_domain)
- domain = getattr(settings, 'DOMAIN', req_domain)
+ # DOMAIN is example.com req_domain is example.com:8001
+ domain = getattr(settings, 'DOMAIN', req_domain.split(':')[0])
+
standards = {'https://': 443, 'http://': 80}
- port = getattr(settings, 'PORT', standards[protocol])
+ if ':' in req_domain:
+ req_port = req_domain.split(':')[1]
+ else:
+ req_port = None
+ port = getattr(settings, 'PORT', req_port or standards[protocol])
if port == standards[protocol]:
site_url = ''.join(map(str, (protocol, domain)))
else:
site_url = ''.join(map(str, (protocol, domain, ':', port)))
+ req_url = "%s%s" % (req_proto, req_domain)
+ if site_url != "%s%s" % (req_proto, req_domain):
+ log.warning('Misconfigured SITE_URL? settings has [%s], but '
+ 'actual request was [%s] BrowserID may fail on '
+ 'audience' % (site_url, req_url))
return site_url
+
def default_username_algo(email):
# store the username as a base64 encoded sha1 of the email address
# this protects against data leakage because usernames are often
@@ -83,7 +83,8 @@ def test_authenticate_create_user(fake):
"""Test that automatic user creation works when enabled."""
with positive_assertion(fake):
setattr(settings, 'BROWSERID_CREATE_USER', True)
- delattr(settings, 'BROWSERID_USERNAME_ALGO')
+ if getattr(settings, 'BROWSERID_USERNAME_ALGO', None):
+ delattr(settings, 'BROWSERID_USERNAME_ALGO')
user = auth.authenticate(**authenticate_kwargs)
# user should have been created
assert user

0 comments on commit c0dcead

Please sign in to comment.