Commit cfb82d35 by Ricardo Kirkner

Add http://ns.login.ubuntu.com/2013/validation/account to the list of requested…

Add http://ns.login.ubuntu.com/2013/validation/account to the list of requested attributes in the Attribute Exchange request, and store the result in UserOpenID.
parents 0ba276cf dda73b1d
...@@ -198,3 +198,28 @@ information, by setting the following setting: ...@@ -198,3 +198,28 @@ information, by setting the following setting:
Otherwise, and by default, if the server omits nick information and a user is Otherwise, and by default, if the server omits nick information and a user is
created it'll receive a username 'openiduser' + a number. created it'll receive a username 'openiduser' + a number.
Consider also the OPENID_STRICT_USERNAMES setting (see ``Require a valid nickname``) Consider also the OPENID_STRICT_USERNAMES setting (see ``Require a valid nickname``)
== Specify Valid Account Verification Schemes ==
When using OpenID Attribute Exchange, the attribute URI
http://ns.login.ubuntu.com/2013/validation/account is included in the request.
OpenID Providers that support this extension can reply with a token
representing what measures they have taken to validate the e-mail address
included in the response. To change the list of schemes acceptable for your
purposes you can change the setting:
OPENID_VALID_VERIFICATION_SCHEMES = {
None: (),
'http://example.com/': ('token_via_email',),
}
The element with the None key specifies a list of verification schemes that
will be accepted as trusted from OpenID Providers that we haven't explicitly
configured. These are, almost by definition, untrusted, so it is strongly
recommended that this list remain empty. Verified accounts will be granted the
django_openid_auth.account_verified permission, which can be checked using
user.has_perm() and the perms RequestContext attribute in the normal way.
N.B. Users of the South migration framework will need to provide a data
migration to create the permission when upgrading django-openid-auth, due to a
known issue in South. See http://south.aeracode.org/ticket/211 for details.
...@@ -33,7 +33,7 @@ __metaclass__ = type ...@@ -33,7 +33,7 @@ __metaclass__ = type
import re import re
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group, Permission
from openid.consumer.consumer import SUCCESS from openid.consumer.consumer import SUCCESS
from openid.extensions import ax, sreg, pape from openid.extensions import ax, sreg, pape
...@@ -47,6 +47,7 @@ from django_openid_auth.exceptions import ( ...@@ -47,6 +47,7 @@ from django_openid_auth.exceptions import (
RequiredAttributeNotReturned, RequiredAttributeNotReturned,
) )
class OpenIDBackend: class OpenIDBackend:
"""A django.contrib.auth backend that authenticates the user based on """A django.contrib.auth backend that authenticates the user based on
an OpenID response.""" an OpenID response."""
...@@ -79,7 +80,8 @@ class OpenIDBackend: ...@@ -79,7 +80,8 @@ class OpenIDBackend:
claimed_id__exact=openid_response.identity_url) claimed_id__exact=openid_response.identity_url)
except UserOpenID.DoesNotExist: except UserOpenID.DoesNotExist:
if getattr(settings, 'OPENID_CREATE_USERS', False): if getattr(settings, 'OPENID_CREATE_USERS', False):
user = self.create_user_from_openid(openid_response) user, user_openid = self.create_user_from_openid(
openid_response)
else: else:
user = user_openid.user user = user_openid.user
...@@ -88,7 +90,7 @@ class OpenIDBackend: ...@@ -88,7 +90,7 @@ class OpenIDBackend:
if getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False): if getattr(settings, 'OPENID_UPDATE_DETAILS_FROM_SREG', False):
details = self._extract_user_details(openid_response) details = self._extract_user_details(openid_response)
self.update_user_details(user, details, openid_response) self.update_user_details(user_openid, details, openid_response)
if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False): if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False):
pape_response = pape.Response.fromSuccessResponse(openid_response) pape_response = pape.Response.fromSuccessResponse(openid_response)
...@@ -122,6 +124,7 @@ class OpenIDBackend: ...@@ -122,6 +124,7 @@ class OpenIDBackend:
def _extract_user_details(self, openid_response): def _extract_user_details(self, openid_response):
email = fullname = first_name = last_name = nickname = None email = fullname = first_name = last_name = nickname = None
verified = 'no'
sreg_response = sreg.SRegResponse.fromSuccessResponse(openid_response) sreg_response = sreg.SRegResponse.fromSuccessResponse(openid_response)
if sreg_response: if sreg_response:
email = sreg_response.get('email') email = sreg_response.get('email')
...@@ -152,6 +155,8 @@ class OpenIDBackend: ...@@ -152,6 +155,8 @@ class OpenIDBackend:
'http://axschema.org/namePerson/last', last_name) 'http://axschema.org/namePerson/last', last_name)
nickname = fetch_response.getSingle( nickname = fetch_response.getSingle(
'http://axschema.org/namePerson/friendly', nickname) 'http://axschema.org/namePerson/friendly', nickname)
verified = fetch_response.getSingle(
'http://ns.login.ubuntu.com/2013/validation/account', verified)
if fullname and not (first_name or last_name): if fullname and not (first_name or last_name):
# Django wants to store first and last names separately, # Django wants to store first and last names separately,
...@@ -164,14 +169,20 @@ class OpenIDBackend: ...@@ -164,14 +169,20 @@ class OpenIDBackend:
first_name = u'' first_name = u''
last_name = fullname last_name = fullname
return dict(email=email, nickname=nickname, verification_scheme_map = getattr(
settings, 'OPENID_VALID_VERIFICATION_SCHEMES', {})
valid_schemes = verification_scheme_map.get(
openid_response.endpoint.server_url,
verification_scheme_map.get(None, ()))
verified = (verified in valid_schemes)
return dict(email=email, nickname=nickname, account_verified=verified,
first_name=first_name, last_name=last_name) first_name=first_name, last_name=last_name)
def _get_preferred_username(self, nickname, email): def _get_preferred_username(self, nickname, email):
if nickname: if nickname:
return nickname return nickname
if email and getattr(settings, 'OPENID_USE_EMAIL_FOR_USERNAME', if email and getattr(settings, 'OPENID_USE_EMAIL_FOR_USERNAME', False):
False):
suggestion = ''.join([x for x in email if x.isalnum()]) suggestion = ''.join([x for x in email if x.isalnum()])
if suggestion: if suggestion:
return suggestion return suggestion
...@@ -264,10 +275,10 @@ class OpenIDBackend: ...@@ -264,10 +275,10 @@ class OpenIDBackend:
openid_response.identity_url) openid_response.identity_url)
user = User.objects.create_user(username, email, password=None) user = User.objects.create_user(username, email, password=None)
self.associate_openid(user, openid_response) user_openid = self.associate_openid(user, openid_response)
self.update_user_details(user, details, openid_response) self.update_user_details(user_openid, details, openid_response)
return user return user, user_openid
def associate_openid(self, user, openid_response): def associate_openid(self, user, openid_response):
"""Associate an OpenID with a user account.""" """Associate an OpenID with a user account."""
...@@ -289,7 +300,8 @@ class OpenIDBackend: ...@@ -289,7 +300,8 @@ class OpenIDBackend:
return user_openid return user_openid
def update_user_details(self, user, details, openid_response): def update_user_details(self, user_openid, details, openid_response):
user = user_openid.user
updated = False updated = False
if details['first_name']: if details['first_name']:
user.first_name = details['first_name'][:30] user.first_name = details['first_name'][:30]
...@@ -303,6 +315,11 @@ class OpenIDBackend: ...@@ -303,6 +315,11 @@ class OpenIDBackend:
if getattr(settings, 'OPENID_FOLLOW_RENAMES', False): if getattr(settings, 'OPENID_FOLLOW_RENAMES', False):
user.username = self._get_available_username(details['nickname'], openid_response.identity_url) user.username = self._get_available_username(details['nickname'], openid_response.identity_url)
updated = True updated = True
account_verified = details.get('account_verified', None)
if (account_verified is not None and
user_openid.account_verified != account_verified):
user_openid.account_verified = account_verified
user_openid.save()
if updated: if updated:
user.save() user.save()
...@@ -348,4 +365,3 @@ class OpenIDBackend: ...@@ -348,4 +365,3 @@ class OpenIDBackend:
break break
user.save() user.save()
...@@ -27,7 +27,10 @@ ...@@ -27,7 +27,10 @@
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
from django.contrib.auth.models import User from django.contrib.auth.models import (
Permission,
User,
)
from django.db import models from django.db import models
...@@ -56,3 +59,27 @@ class UserOpenID(models.Model): ...@@ -56,3 +59,27 @@ class UserOpenID(models.Model):
user = models.ForeignKey(User) user = models.ForeignKey(User)
claimed_id = models.TextField(max_length=2047, unique=True) claimed_id = models.TextField(max_length=2047, unique=True)
display_id = models.TextField(max_length=2047) display_id = models.TextField(max_length=2047)
account_verified = models.BooleanField(default=False)
class Meta:
permissions = (
('account_verified', 'The OpenID has been verified'),
)
def _get_permission(self):
return Permission.objects.get(codename='account_verified')
def save(self, force_insert=False, force_update=False, using=None):
permission = self._get_permission()
perm_label = '%s.%s' % (permission.content_type.app_label,
permission.codename)
if self.account_verified and not self.user.has_perm(perm_label):
self.user.user_permissions.add(permission)
elif not self.account_verified and self.user.has_perm(perm_label):
self.user.user_permissions.remove(permission)
super(UserOpenID, self).save(force_insert, force_update, using)
def delete(self, using=None):
permission = self._get_permission()
self.user.user_permissions.remove(permission)
super(UserOpenID, self).delete(using)
...@@ -35,7 +35,8 @@ from test_admin import * ...@@ -35,7 +35,8 @@ from test_admin import *
def suite(): def suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
for name in ['test_auth', 'test_store', 'test_views', 'test_admin']: for name in ['test_auth', 'test_models', 'test_store', 'test_views',
'test_admin']:
mod = __import__('%s.%s' % (__name__, name), {}, {}, ['suite']) mod = __import__('%s.%s' % (__name__, name), {}, {}, ['suite'])
suite.addTest(mod.suite()) suite.addTest(mod.suite())
return suite return suite
...@@ -33,6 +33,7 @@ from django.contrib.auth.models import Group, User ...@@ -33,6 +33,7 @@ from django.contrib.auth.models import Group, User
from django.test import TestCase from django.test import TestCase
from django_openid_auth.auth import OpenIDBackend from django_openid_auth.auth import OpenIDBackend
from django_openid_auth.models import UserOpenID
from django_openid_auth.teams import ns_uri as TEAMS_NS from django_openid_auth.teams import ns_uri as TEAMS_NS
from openid.consumer.consumer import SuccessResponse from openid.consumer.consumer import SuccessResponse
from openid.consumer.discover import OpenIDServiceEndpoint from openid.consumer.discover import OpenIDServiceEndpoint
...@@ -72,6 +73,7 @@ class OpenIDBackendTests(TestCase): ...@@ -72,6 +73,7 @@ class OpenIDBackendTests(TestCase):
'first_name': 'Some', 'first_name': 'Some',
'last_name': 'User', 'last_name': 'User',
'email': 'foo@example.com', 'email': 'foo@example.com',
'account_verified': False,
} }
data = { data = {
'nickname': expected['nickname'], 'nickname': expected['nickname'],
...@@ -107,14 +109,17 @@ class OpenIDBackendTests(TestCase): ...@@ -107,14 +109,17 @@ class OpenIDBackendTests(TestCase):
return response return response
def make_response_ax(self, schema="http://axschema.org/", def make_response_ax(self, schema="http://axschema.org/",
fullname="Some User", nickname="someuser", email="foo@example.com", fullname="Some User", nickname="someuser", email="foo@example.com",
first=None, last=None): first=None, last=None, verified=False):
endpoint = OpenIDServiceEndpoint() endpoint = OpenIDServiceEndpoint()
message = Message(OPENID2_NS) message = Message(OPENID2_NS)
attributes = [ attributes = [
("nickname", schema + "namePerson/friendly", nickname), ("nickname", schema + "namePerson/friendly", nickname),
("fullname", schema + "namePerson", fullname), ("fullname", schema + "namePerson", fullname),
("email", schema + "contact/email", email), ("email", schema + "contact/email", email),
("account_verified",
"http://ns.login.ubuntu.com/2013/validation/account",
"token_via_email" if verified else "no")
] ]
if first: if first:
attributes.append( attributes.append(
...@@ -139,7 +144,8 @@ class OpenIDBackendTests(TestCase): ...@@ -139,7 +144,8 @@ class OpenIDBackendTests(TestCase):
self.assertEqual(data, {"nickname": "someuser", self.assertEqual(data, {"nickname": "someuser",
"first_name": "Some", "first_name": "Some",
"last_name": "User", "last_name": "User",
"email": "foo@example.com"}) "email": "foo@example.com",
"account_verified": False})
def test_extract_user_details_ax_split_name(self): def test_extract_user_details_ax_split_name(self):
# Include fullname too to show that the split data takes # Include fullname too to show that the split data takes
...@@ -152,7 +158,8 @@ class OpenIDBackendTests(TestCase): ...@@ -152,7 +158,8 @@ class OpenIDBackendTests(TestCase):
self.assertEqual(data, {"nickname": "someuser", self.assertEqual(data, {"nickname": "someuser",
"first_name": "Some", "first_name": "Some",
"last_name": "User", "last_name": "User",
"email": "foo@example.com"}) "email": "foo@example.com",
"account_verified": False})
def test_extract_user_details_ax_broken_myopenid(self): def test_extract_user_details_ax_broken_myopenid(self):
response = self.make_response_ax( response = self.make_response_ax(
...@@ -164,21 +171,71 @@ class OpenIDBackendTests(TestCase): ...@@ -164,21 +171,71 @@ class OpenIDBackendTests(TestCase):
self.assertEqual(data, {"nickname": "someuser", self.assertEqual(data, {"nickname": "someuser",
"first_name": "Some", "first_name": "Some",
"last_name": "User", "last_name": "User",
"email": "foo@example.com"}) "email": "foo@example.com",
"account_verified": False})
def test_update_user_details_long_names(self): def test_update_user_details_long_names(self):
response = self.make_response_ax() response = self.make_response_ax()
user = User.objects.create_user('someuser', 'someuser@example.com', user = User.objects.create_user('someuser', 'someuser@example.com',
password=None) password=None)
user_openid, created = UserOpenID.objects.get_or_create(
user=user,
claimed_id='http://example.com/existing_identity',
display_id='http://example.com/existing_identity',
account_verified=False)
data = dict(first_name=u"Some56789012345678901234567890123", data = dict(first_name=u"Some56789012345678901234567890123",
last_name=u"User56789012345678901234567890123", last_name=u"User56789012345678901234567890123",
email=u"someotheruser@example.com") email=u"someotheruser@example.com", account_verified=False)
self.backend.update_user_details(user, data, response) self.backend.update_user_details(user_openid, data, response)
self.assertEqual("Some56789012345678901234567890", user.first_name) self.assertEqual("Some56789012345678901234567890", user.first_name)
self.assertEqual("User56789012345678901234567890", user.last_name) self.assertEqual("User56789012345678901234567890", user.last_name)
def make_user(self, username='someuser', email='someuser@example.com',
password=None):
user = User.objects.create_user(username, email, password=password)
return user
def make_user_openid(self, user=None,
claimed_id='http://example.com/existing_identity',
display_id='http://example.com/existing_identity'):
if user is None:
user = self.make_user()
user_openid, created = UserOpenID.objects.get_or_create(
user=user, claimed_id=claimed_id, display_id=display_id)
return user_openid
def _test_account_verified(self, user_openid, verified, expected):
# set user's verification status
user_openid.account_verified = verified
# get a response including verification status
response = self.make_response_ax()
data = dict(first_name=u"Some56789012345678901234567890123",
last_name=u"User56789012345678901234567890123",
email=u"someotheruser@example.com", account_verified=expected)
self.backend.update_user_details(user_openid, data, response)
# refresh object from the database
user_openid = UserOpenID.objects.get(pk=user_openid.pk)
# check the verification status
self.assertEqual(user_openid.account_verified, expected)
self.assertEqual(user_openid.user.has_perm(
'django_openid_auth.account_verified'), expected)
def test_update_user_openid_unverified(self):
user_openid = self.make_user_openid()
for verified in (False, True):
self._test_account_verified(user_openid, verified, expected=False)
def test_update_user_openid_verified(self):
user_openid = self.make_user_openid()
for verified in (False, True):
self._test_account_verified(user_openid, verified, expected=True)
def test_extract_user_details_name_with_trailing_space(self): def test_extract_user_details_name_with_trailing_space(self):
response = self.make_response_ax(fullname="SomeUser ") response = self.make_response_ax(fullname="SomeUser ")
......
# django-openid-auth - OpenID integration for django.contrib.auth
#
# Copyright (C) 2013 Canonical Ltd.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
import unittest
from django.contrib.auth.models import User
from django.test import TestCase
from django_openid_auth.models import UserOpenID
class UserOpenIDModelTestCase(TestCase):
def test_create_useropenid(self):
user = User.objects.create_user('someuser', 'someuser@example.com',
password=None)
user_openid, created = UserOpenID.objects.get_or_create(
user=user,
claimed_id='http://example.com/existing_identity',
display_id='http://example.com/existing_identity',
account_verified=False)
self.assertEqual('someuser', user_openid.user.username)
self.assertEqual(
user_openid.claimed_id, 'http://example.com/existing_identity')
self.assertEqual(
user_openid.display_id, 'http://example.com/existing_identity')
self.assertFalse(user_openid.account_verified)
self.assertFalse(
User.objects.get(username='someuser').has_perm(
'django_openid_auth.account_verified'))
def test_create_verified_useropenid(self):
user = User.objects.create_user('someuser', 'someuser@example.com',
password=None)
user_openid, created = UserOpenID.objects.get_or_create(
user=user,
claimed_id='http://example.com/existing_identity',
display_id='http://example.com/existing_identity',
account_verified=True)
self.assertEqual('someuser', user_openid.user.username)
self.assertEqual(
user_openid.claimed_id, 'http://example.com/existing_identity')
self.assertEqual(
user_openid.display_id, 'http://example.com/existing_identity')
self.assertTrue(user_openid.account_verified)
self.assertTrue(
User.objects.get(username='someuser').has_perm(
'django_openid_auth.account_verified'))
def test_delete_verified_useropenid(self):
user = User.objects.create_user('someuser', 'someuser@example.com',
password=None)
user_openid, created = UserOpenID.objects.get_or_create(
user=user,
claimed_id='http://example.com/existing_identity',
display_id='http://example.com/existing_identity',
account_verified=True)
self.assertTrue(
User.objects.get(username='someuser').has_perm(
'django_openid_auth.account_verified'))
user_openid.delete()
self.assertFalse(
User.objects.get(username='someuser').has_perm(
'django_openid_auth.account_verified'))
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)
...@@ -56,7 +56,6 @@ from django_openid_auth.models import UserOpenID ...@@ -56,7 +56,6 @@ from django_openid_auth.models import UserOpenID
from django_openid_auth.signals import openid_login_complete from django_openid_auth.signals import openid_login_complete
from django_openid_auth.store import DjangoOpenIDStore from django_openid_auth.store import DjangoOpenIDStore
from django_openid_auth.exceptions import ( from django_openid_auth.exceptions import (
RequiredAttributeNotReturned,
DjangoOpenIDException, DjangoOpenIDException,
) )
...@@ -170,7 +169,6 @@ def login_begin(request, template_name='openid/login.html', ...@@ -170,7 +169,6 @@ def login_begin(request, template_name='openid/login.html',
redirect_field_name: redirect_to redirect_field_name: redirect_to
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
error = None
consumer = make_consumer(request) consumer = make_consumer(request)
try: try:
openid_request = consumer.begin(openid_url) openid_request = consumer.begin(openid_url)
...@@ -181,25 +179,40 @@ def login_begin(request, template_name='openid/login.html', ...@@ -181,25 +179,40 @@ def login_begin(request, template_name='openid/login.html',
# Request some user details. If the provider advertises support # Request some user details. If the provider advertises support
# for attribute exchange, use that. # for attribute exchange, use that.
if openid_request.endpoint.supportsType(ax.AXMessage.ns_uri): endpoint = openid_request.endpoint
if endpoint.supportsType(ax.AXMessage.ns_uri):
fetch_request = ax.FetchRequest() fetch_request = ax.FetchRequest()
# We mark all the attributes as required, since Google ignores # We mark all the attributes as required, since Google ignores
# optional attributes. We request both the full name and # optional attributes. We request both the full name and
# first/last components since some providers offer one but not # first/last components since some providers offer one but not
# the other. # the other.
for (attr, alias) in [ for (attr, alias) in [
('http://axschema.org/contact/email', 'email'), ('http://axschema.org/contact/email', 'email'),
('http://axschema.org/namePerson', 'fullname'), ('http://axschema.org/namePerson', 'fullname'),
('http://axschema.org/namePerson/first', 'firstname'), ('http://axschema.org/namePerson/first', 'firstname'),
('http://axschema.org/namePerson/last', 'lastname'), ('http://axschema.org/namePerson/last', 'lastname'),
('http://axschema.org/namePerson/friendly', 'nickname'), ('http://axschema.org/namePerson/friendly', 'nickname'),
# The myOpenID provider advertises AX support, but uses # The myOpenID provider advertises AX support, but uses
# attribute names from an obsolete draft of the # attribute names from an obsolete draft of the
# specification. We request them for compatibility. # specification. We request them for compatibility.
('http://schema.openid.net/contact/email', 'old_email'), ('http://schema.openid.net/contact/email', 'old_email'),
('http://schema.openid.net/namePerson', 'old_fullname'), ('http://schema.openid.net/namePerson', 'old_fullname'),
('http://schema.openid.net/namePerson/friendly', 'old_nickname')]: ('http://schema.openid.net/namePerson/friendly',
'old_nickname')]:
fetch_request.add(ax.AttrInfo(attr, alias=alias, required=True)) fetch_request.add(ax.AttrInfo(attr, alias=alias, required=True))
# conditionally require account_verified attribute
verification_scheme_map = getattr(
settings, 'OPENID_VALID_VERIFICATION_SCHEMES', {})
valid_schemes = verification_scheme_map.get(
endpoint.server_url, verification_scheme_map.get(None, ()))
if valid_schemes:
# there are valid schemes configured for this endpoint, so
# request account_verified status
fetch_request.add(ax.AttrInfo(
'http://ns.login.ubuntu.com/2013/validation/account',
alias='account_verified', required=True))
openid_request.addExtension(fetch_request) openid_request.addExtension(fetch_request)
else: else:
sreg_required_fields = [] sreg_required_fields = []
...@@ -214,7 +227,7 @@ def login_begin(request, template_name='openid/login.html', ...@@ -214,7 +227,7 @@ def login_begin(request, template_name='openid/login.html',
openid_request.addExtension( openid_request.addExtension(
sreg.SRegRequest(optional=sreg_optional_fields, sreg.SRegRequest(optional=sreg_optional_fields,
required=sreg_required_fields)) required=sreg_required_fields))
if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False): if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False):
preferred_auth = [ preferred_auth = [
pape.AUTH_MULTI_FACTOR_PHYSICAL, pape.AUTH_MULTI_FACTOR_PHYSICAL,
...@@ -271,7 +284,7 @@ def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME, ...@@ -271,7 +284,7 @@ def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME,
user = authenticate(openid_response=openid_response) user = authenticate(openid_response=openid_response)
except DjangoOpenIDException, e: except DjangoOpenIDException, e:
return render_failure(request, e.message, exception=e) return render_failure(request, e.message, exception=e)
if user is not None: if user is not None:
if user.is_active: if user.is_active:
auth_login(request, user) auth_login(request, user)
......
...@@ -133,6 +133,14 @@ OPENID_CREATE_USERS = True ...@@ -133,6 +133,14 @@ OPENID_CREATE_USERS = True
# data received via Simple Registration? # data received via Simple Registration?
OPENID_UPDATE_DETAILS_FROM_SREG = True OPENID_UPDATE_DETAILS_FROM_SREG = True
# Map of OpenID Provider base URLs to recognised account verification schemes
# returned in response to a http://ns.login.ubuntu.com/2013/validation/account
# request. Use None as the key in place of a URL to specify verification
# schemes that will be trusted from unknown OpenID Providers (not recommended).
OPENID_VALID_VERIFICATION_SCHEMES = {
None: (),
}
# If set, always use this as the identity URL rather than asking the # If set, always use this as the identity URL rather than asking the
# user. This only makes sense if it is a server URL. # user. This only makes sense if it is a server URL.
OPENID_SSO_SERVER_URL = 'https://login.launchpad.net/' OPENID_SSO_SERVER_URL = 'https://login.launchpad.net/'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment