41
by James Henstridge
Slap BSD license headers on source code. Attribute Simon Willison for |
1 |
# django-openid-auth - OpenID integration for django.contrib.auth
|
2 |
#
|
|
3 |
# Copyright (C) 2007 Simon Willison
|
|
93
by Anthony Lenton
[r=elachuni,facundobatista] LP#936153, After login, redirecting to a URL that contains non-ASCII characters would fail because the naive "str(foo)" scheme used in urllib would use the default system encoding, which we can't trust at all. |
4 |
# Copyright (C) 2008-2013 Canonical Ltd.
|
41
by James Henstridge
Slap BSD license headers on source code. Attribute Simon Willison for |
5 |
#
|
6 |
# Redistribution and use in source and binary forms, with or without
|
|
7 |
# modification, are permitted provided that the following conditions
|
|
8 |
# are met:
|
|
9 |
#
|
|
10 |
# * Redistributions of source code must retain the above copyright
|
|
11 |
# notice, this list of conditions and the following disclaimer.
|
|
12 |
#
|
|
13 |
# * Redistributions in binary form must reproduce the above copyright
|
|
14 |
# notice, this list of conditions and the following disclaimer in the
|
|
15 |
# documentation and/or other materials provided with the distribution.
|
|
16 |
#
|
|
17 |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
18 |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
19 |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
20 |
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
21 |
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
22 |
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
|
23 |
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
24 |
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
25 |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
26 |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
27 |
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
28 |
# POSSIBILITY OF SUCH DAMAGE.
|
|
29 |
||
112.1.2
by Natalia
Ensure that we handle unicode everywhere. |
30 |
from __future__ import unicode_literals |
31 |
||
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
32 |
import re |
33 |
import urllib |
|
59.1.1
by stuart.langridge at canonical
Allow redirect URL to be external if it's on the permitted list of external domains, defined in settings |
34 |
from urlparse import urlsplit |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
35 |
|
36 |
from django.conf import settings |
|
19
by James Henstridge
Convert the auth.py code into a django.contrib.auth authentication |
37 |
from django.contrib.auth import ( |
38 |
REDIRECT_FIELD_NAME, authenticate, login as auth_login) |
|
56.1.1
by Thomas Bechtold
add possibility to map automatic all django-groups to launchpad teams |
39 |
from django.contrib.auth.models import Group |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
40 |
from django.core.urlresolvers import reverse |
41 |
from django.http import HttpResponse, HttpResponseRedirect |
|
42 |
from django.shortcuts import render_to_response |
|
2
by swillison
Initial checkin |
43 |
from django.template import RequestContext |
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
44 |
from django.template.loader import render_to_string |
75.1.1
by Anthony Lenton
Added a try/except block when importing csrf decorator. |
45 |
try: |
46 |
from django.views.decorators.csrf import csrf_exempt |
|
47 |
except ImportError: |
|
48 |
from django.contrib.csrf.middleware import csrf_exempt |
|
2
by swillison
Initial checkin |
49 |
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
50 |
from openid.consumer.consumer import ( |
51 |
Consumer, SUCCESS, CANCEL, FAILURE) |
|
2
by swillison
Initial checkin |
52 |
from openid.consumer.discover import DiscoveryFailure |
80.1.3
by Michael Hall
Finish test cases, add implementation |
53 |
from openid.extensions import sreg, ax, pape |
27.1.4
by john.lenton at canonical
made teams optional |
54 |
|
30
by James Henstridge
Add teams extension to tree, rather than requiring patched |
55 |
from django_openid_auth import teams |
18
by James Henstridge
Rename package to django_openid_auth, since it differs from the |
56 |
from django_openid_auth.forms import OpenIDLoginForm |
76.2.1
by Michael Nelson
Adds a signal on successful login that includes the request and the sreg_response. |
57 |
from django_openid_auth.models import UserOpenID |
78.1.1
by Michael Nelson
Correct signal name and provide openid_response as kwarg instead of sreg_response. |
58 |
from django_openid_auth.signals import openid_login_complete |
18
by James Henstridge
Rename package to django_openid_auth, since it differs from the |
59 |
from django_openid_auth.store import DjangoOpenIDStore |
80.2.4
by Michael Hall
Merge from trunk |
60 |
from django_openid_auth.exceptions import ( |
61 |
DjangoOpenIDException, |
|
62 |
)
|
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
63 |
|
2
by swillison
Initial checkin |
64 |
|
3
by swillison
Ready for launch |
65 |
next_url_re = re.compile('^/[-\w/]+$') |
66 |
||
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
67 |
|
3
by swillison
Ready for launch |
68 |
def is_valid_next_url(next): |
2
by swillison
Initial checkin |
69 |
# When we allow this:
|
3
by swillison
Ready for launch |
70 |
# /openid/?next=/welcome/
|
76.1.1
by Michael Nelson
Add an optional OPENID_SREG_EXTRA_FIELDS setting. |
71 |
# For security reasons we want to restrict the next= bit to being a local
|
2
by swillison
Initial checkin |
72 |
# path, not a complete URL.
|
3
by swillison
Ready for launch |
73 |
return bool(next_url_re.match(next)) |
2
by swillison
Initial checkin |
74 |
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
75 |
|
76 |
def sanitise_redirect_url(redirect_to): |
|
77 |
"""Sanitise the redirection URL."""
|
|
78 |
# Light security check -- make sure redirect_to isn't garbage.
|
|
63.1.1
by James Henstridge
Fix the sanitise_redirect_url function to handle an empty string properly. |
79 |
is_valid = True |
80 |
if not redirect_to or ' ' in redirect_to: |
|
81 |
is_valid = False |
|
82 |
elif '//' in redirect_to: |
|
59.1.1
by stuart.langridge at canonical
Allow redirect URL to be external if it's on the permitted list of external domains, defined in settings |
83 |
# Allow the redirect URL to be external if it's a permitted domain
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
84 |
allowed_domains = getattr( |
85 |
settings, "ALLOWED_EXTERNAL_OPENID_REDIRECT_DOMAINS", []) |
|
59.1.1
by stuart.langridge at canonical
Allow redirect URL to be external if it's on the permitted list of external domains, defined in settings |
86 |
s, netloc, p, q, f = urlsplit(redirect_to) |
87 |
# allow it if netloc is blank or if the domain is allowed
|
|
88 |
if netloc: |
|
89 |
# a domain was specified. Is it an allowed domain?
|
|
90 |
if netloc.find(":") != -1: |
|
91 |
netloc, _ = netloc.split(":", 1) |
|
92 |
if netloc not in allowed_domains: |
|
63.1.1
by James Henstridge
Fix the sanitise_redirect_url function to handle an empty string properly. |
93 |
is_valid = False |
94 |
||
95 |
# If the return_to URL is not valid, use the default.
|
|
96 |
if not is_valid: |
|
97 |
redirect_to = settings.LOGIN_REDIRECT_URL |
|
98 |
||
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
99 |
return redirect_to |
100 |
||
101 |
||
102 |
def make_consumer(request): |
|
103 |
"""Create an OpenID Consumer object for the given Django request."""
|
|
104 |
# Give the OpenID library its own space in the session object.
|
|
105 |
session = request.session.setdefault('OPENID', {}) |
|
106 |
store = DjangoOpenIDStore() |
|
107 |
return Consumer(session, store) |
|
108 |
||
109 |
||
25
by James Henstridge
Add a test for the SSO login code path. |
110 |
def render_openid_request(request, openid_request, return_to, trust_root=None): |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
111 |
"""Render an OpenID authentication request."""
|
112 |
if trust_root is None: |
|
113 |
trust_root = getattr(settings, 'OPENID_TRUST_ROOT', |
|
114 |
request.build_absolute_uri('/')) |
|
115 |
||
116 |
if openid_request.shouldSendRedirect(): |
|
117 |
redirect_url = openid_request.redirectURL( |
|
118 |
trust_root, return_to) |
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
119 |
response = HttpResponseRedirect(redirect_url) |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
120 |
else: |
121 |
form_html = openid_request.htmlMarkup( |
|
122 |
trust_root, return_to, form_tag_attrs={'id': 'openid_message'}) |
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
123 |
response = HttpResponse( |
124 |
form_html, content_type='text/html;charset=UTF-8') |
|
125 |
return response |
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
126 |
|
127 |
||
66.1.4
by Richard Marko
Add posibility to change location of failure template. |
128 |
def default_render_failure(request, message, status=403, |
80.2.1
by Michael Hall
Let exceptions bubble up and pass them on to render_failure so we can give users helpful information when their login fails |
129 |
template_name='openid/failure.html', |
130 |
exception=None): |
|
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
131 |
"""Render an error page to the user."""
|
132 |
data = render_to_string( |
|
80.2.1
by Michael Hall
Let exceptions bubble up and pass them on to render_failure so we can give users helpful information when their login fails |
133 |
template_name, dict(message=message, exception=exception), |
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
134 |
context_instance=RequestContext(request)) |
135 |
return HttpResponse(data, status=status) |
|
136 |
||
137 |
||
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
138 |
def parse_openid_response(request): |
139 |
"""Parse an OpenID response from a Django request."""
|
|
140 |
# Short cut if there is no request parameters.
|
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
141 |
# if len(request.REQUEST) == 0:
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
142 |
# return None
|
143 |
||
144 |
current_url = request.build_absolute_uri() |
|
145 |
||
146 |
consumer = make_consumer(request) |
|
147 |
return consumer.complete(dict(request.REQUEST.items()), current_url) |
|
148 |
||
149 |
||
150 |
def login_begin(request, template_name='openid/login.html', |
|
72
by James Henstridge
(Richard Marko) Add hooks for customising the view behaviour. |
151 |
login_complete_view='openid-complete', |
152 |
form_class=OpenIDLoginForm, |
|
66.1.4
by Richard Marko
Add posibility to change location of failure template. |
153 |
render_failure=default_render_failure, |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
154 |
redirect_field_name=REDIRECT_FIELD_NAME): |
155 |
"""Begin an OpenID login request, possibly asking for an identity URL."""
|
|
156 |
redirect_to = request.REQUEST.get(redirect_field_name, '') |
|
157 |
||
158 |
# Get the OpenID URL to try. First see if we've been configured
|
|
159 |
# to use a fixed server URL.
|
|
160 |
openid_url = getattr(settings, 'OPENID_SSO_SERVER_URL', None) |
|
161 |
||
162 |
if openid_url is None: |
|
163 |
if request.POST: |
|
72
by James Henstridge
(Richard Marko) Add hooks for customising the view behaviour. |
164 |
login_form = form_class(data=request.POST) |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
165 |
if login_form.is_valid(): |
26
by James Henstridge
Add more tests for the other login modes. |
166 |
openid_url = login_form.cleaned_data['openid_identifier'] |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
167 |
else: |
72
by James Henstridge
(Richard Marko) Add hooks for customising the view behaviour. |
168 |
login_form = form_class() |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
169 |
|
170 |
# Invalid or no form data:
|
|
171 |
if openid_url is None: |
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
172 |
context = {'form': login_form, redirect_field_name: redirect_to} |
173 |
return render_to_response( |
|
174 |
template_name, context, |
|
175 |
context_instance=RequestContext(request)) |
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
176 |
|
177 |
consumer = make_consumer(request) |
|
178 |
try: |
|
179 |
openid_request = consumer.begin(openid_url) |
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
180 |
except DiscoveryFailure as exc: |
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
181 |
return render_failure( |
80.2.1
by Michael Hall
Let exceptions bubble up and pass them on to render_failure so we can give users helpful information when their login fails |
182 |
request, "OpenID discovery error: %s" % (str(exc),), status=500, |
183 |
exception=exc) |
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
184 |
|
65.1.1
by James Henstridge
Add support for attribute exchange as a way to query user details. |
185 |
# Request some user details. If the provider advertises support
|
186 |
# for attribute exchange, use that.
|
|
99.2.20
by Ricardo Kirkner
only request account_verified if there are valid schemes registered for the endpoint |
187 |
endpoint = openid_request.endpoint |
188 |
if endpoint.supportsType(ax.AXMessage.ns_uri): |
|
65.1.1
by James Henstridge
Add support for attribute exchange as a way to query user details. |
189 |
fetch_request = ax.FetchRequest() |
190 |
# We mark all the attributes as required, since Google ignores
|
|
191 |
# optional attributes. We request both the full name and
|
|
192 |
# first/last components since some providers offer one but not
|
|
193 |
# the other.
|
|
194 |
for (attr, alias) in [ |
|
99.2.1
by James Tait
Request account verification in the AX request. |
195 |
('http://axschema.org/contact/email', 'email'), |
196 |
('http://axschema.org/namePerson', 'fullname'), |
|
197 |
('http://axschema.org/namePerson/first', 'firstname'), |
|
198 |
('http://axschema.org/namePerson/last', 'lastname'), |
|
199 |
('http://axschema.org/namePerson/friendly', 'nickname'), |
|
200 |
# The myOpenID provider advertises AX support, but uses
|
|
201 |
# attribute names from an obsolete draft of the
|
|
202 |
# specification. We request them for compatibility.
|
|
203 |
('http://schema.openid.net/contact/email', 'old_email'), |
|
204 |
('http://schema.openid.net/namePerson', 'old_fullname'), |
|
205 |
('http://schema.openid.net/namePerson/friendly', |
|
99.2.20
by Ricardo Kirkner
only request account_verified if there are valid schemes registered for the endpoint |
206 |
'old_nickname')]: |
65.1.1
by James Henstridge
Add support for attribute exchange as a way to query user details. |
207 |
fetch_request.add(ax.AttrInfo(attr, alias=alias, required=True)) |
99.2.20
by Ricardo Kirkner
only request account_verified if there are valid schemes registered for the endpoint |
208 |
|
209 |
# conditionally require account_verified attribute
|
|
210 |
verification_scheme_map = getattr( |
|
211 |
settings, 'OPENID_VALID_VERIFICATION_SCHEMES', {}) |
|
212 |
valid_schemes = verification_scheme_map.get( |
|
213 |
endpoint.server_url, verification_scheme_map.get(None, ())) |
|
214 |
if valid_schemes: |
|
215 |
# there are valid schemes configured for this endpoint, so
|
|
216 |
# request account_verified status
|
|
217 |
fetch_request.add(ax.AttrInfo( |
|
218 |
'http://ns.login.ubuntu.com/2013/validation/account', |
|
219 |
alias='account_verified', required=True)) |
|
220 |
||
65.1.1
by James Henstridge
Add support for attribute exchange as a way to query user details. |
221 |
openid_request.addExtension(fetch_request) |
222 |
else: |
|
82.1.1
by Michael Nelson
RED: Required fields should be required in SRegRequest. |
223 |
sreg_required_fields = [] |
224 |
sreg_required_fields.extend( |
|
225 |
getattr(settings, 'OPENID_SREG_REQUIRED_FIELDS', [])) |
|
76.1.1
by Michael Nelson
Add an optional OPENID_SREG_EXTRA_FIELDS setting. |
226 |
sreg_optional_fields = ['email', 'fullname', 'nickname'] |
82.1.2
by Michael Nelson
GREEN: Enable required fields to be included in request. |
227 |
sreg_optional_fields.extend( |
228 |
getattr(settings, 'OPENID_SREG_EXTRA_FIELDS', [])) |
|
229 |
sreg_optional_fields = [ |
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
230 |
field for field in sreg_optional_fields |
231 |
if field not in sreg_required_fields] |
|
65.1.1
by James Henstridge
Add support for attribute exchange as a way to query user details. |
232 |
openid_request.addExtension( |
82.1.1
by Michael Nelson
RED: Required fields should be required in SRegRequest. |
233 |
sreg.SRegRequest(optional=sreg_optional_fields, |
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
234 |
required=sreg_required_fields)) |
99.2.20
by Ricardo Kirkner
only request account_verified if there are valid schemes registered for the endpoint |
235 |
|
80.1.3
by Michael Hall
Finish test cases, add implementation |
236 |
if getattr(settings, 'OPENID_PHYSICAL_MULTIFACTOR_REQUIRED', False): |
237 |
preferred_auth = [ |
|
238 |
pape.AUTH_MULTI_FACTOR_PHYSICAL, |
|
239 |
]
|
|
240 |
pape_request = pape.Request(preferred_auth_policies=preferred_auth) |
|
241 |
openid_request.addExtension(pape_request) |
|
242 |
||
30
by James Henstridge
Add teams extension to tree, rather than requiring patched |
243 |
# Request team info
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
244 |
teams_mapping_auto = getattr( |
245 |
settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO', False) |
|
246 |
teams_mapping_auto_blacklist = getattr( |
|
247 |
settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING_AUTO_BLACKLIST', []) |
|
32
by James Henstridge
Only add the teams extension to the request if we have teams to check. |
248 |
launchpad_teams = getattr(settings, 'OPENID_LAUNCHPAD_TEAMS_MAPPING', {}) |
56.1.1
by Thomas Bechtold
add possibility to map automatic all django-groups to launchpad teams |
249 |
if teams_mapping_auto: |
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
250 |
# ignore launchpad teams. use all django-groups
|
56.1.1
by Thomas Bechtold
add possibility to map automatic all django-groups to launchpad teams |
251 |
launchpad_teams = dict() |
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
252 |
all_groups = Group.objects.exclude( |
253 |
name__in=teams_mapping_auto_blacklist) |
|
56.1.1
by Thomas Bechtold
add possibility to map automatic all django-groups to launchpad teams |
254 |
for group in all_groups: |
255 |
launchpad_teams[group.name] = group.name |
|
256 |
||
32
by James Henstridge
Only add the teams extension to the request if we have teams to check. |
257 |
if launchpad_teams: |
258 |
openid_request.addExtension(teams.TeamsRequest(launchpad_teams.keys())) |
|
27.1.1
by john.lenton at canonical
got it working! woohoo! |
259 |
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
260 |
# Construct the request completion URL, including the page we
|
261 |
# should redirect to.
|
|
72
by James Henstridge
(Richard Marko) Add hooks for customising the view behaviour. |
262 |
return_to = request.build_absolute_uri(reverse(login_complete_view)) |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
263 |
if redirect_to: |
264 |
if '?' in return_to: |
|
265 |
return_to += '&' |
|
266 |
else: |
|
267 |
return_to += '?' |
|
93
by Anthony Lenton
[r=elachuni,facundobatista] LP#936153, After login, redirecting to a URL that contains non-ASCII characters would fail because the naive "str(foo)" scheme used in urllib would use the default system encoding, which we can't trust at all. |
268 |
# Django gives us Unicode, which is great. We must encode URI.
|
269 |
# urllib enforces str. We can't trust anything about the default
|
|
89.2.1
by Chad MILLER
LP#936153, After login, redirecting to a URL that contains non-ASCII characters would fail because the naive "str(foo)" scheme used in urllib would use the default system encoding, which we can't trust at all. |
270 |
# encoding inside str(foo) , so we must explicitly make foo a str.
|
271 |
return_to += urllib.urlencode( |
|
93
by Anthony Lenton
[r=elachuni,facundobatista] LP#936153, After login, redirecting to a URL that contains non-ASCII characters would fail because the naive "str(foo)" scheme used in urllib would use the default system encoding, which we can't trust at all. |
272 |
{redirect_field_name: redirect_to.encode("UTF-8")}) |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
273 |
|
274 |
return render_openid_request(request, openid_request, return_to) |
|
275 |
||
276 |
||
68
by James Henstridge
Make the login_complete view csrf_exempt, since it can legitimately |
277 |
@csrf_exempt
|
66.1.4
by Richard Marko
Add posibility to change location of failure template. |
278 |
def login_complete(request, redirect_field_name=REDIRECT_FIELD_NAME, |
80.2.2
by Michael Hall
Cleanup exception class heirarchy and imports, make overriding the login failure handler a settings option, add additional test cases to veryfiy that overriding the handler works and that the proper exceptions are being passed |
279 |
render_failure=None): |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
280 |
redirect_to = request.REQUEST.get(redirect_field_name, '') |
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
281 |
render_failure = ( |
282 |
render_failure or getattr(settings, 'OPENID_RENDER_FAILURE', None) or |
|
283 |
default_render_failure) |
|
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
284 |
|
285 |
openid_response = parse_openid_response(request) |
|
286 |
if not openid_response: |
|
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
287 |
return render_failure( |
288 |
request, 'This is an OpenID relying party endpoint.') |
|
13
by James Henstridge
Some changes for compatibility with current Django and Python-OpenID. |
289 |
|
2
by swillison
Initial checkin |
290 |
if openid_response.status == SUCCESS: |
80.2.1
by Michael Hall
Let exceptions bubble up and pass them on to render_failure so we can give users helpful information when their login fails |
291 |
try: |
292 |
user = authenticate(openid_response=openid_response) |
|
293 |
except DjangoOpenIDException, e: |
|
80.2.4
by Michael Hall
Merge from trunk |
294 |
return render_failure(request, e.message, exception=e) |
99.2.20
by Ricardo Kirkner
only request account_verified if there are valid schemes registered for the endpoint |
295 |
|
17
by James Henstridge
Add code to integrate the OpenID code with django.contrib.auth. |
296 |
if user is not None: |
297 |
if user.is_active: |
|
298 |
auth_login(request, user) |
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
299 |
response = HttpResponseRedirect( |
300 |
sanitise_redirect_url(redirect_to)) |
|
76.2.1
by Michael Nelson
Adds a signal on successful login that includes the request and the sreg_response. |
301 |
|
302 |
# Notify any listeners that we successfully logged in.
|
|
112.1.1
by Natalia
Fully test suite passing on djangos from 1.4 to 1.8. |
303 |
openid_login_complete.send( |
304 |
sender=UserOpenID, request=request, |
|
78.1.1
by Michael Nelson
Correct signal name and provide openid_response as kwarg instead of sreg_response. |
305 |
openid_response=openid_response) |
76.2.1
by Michael Nelson
Adds a signal on successful login that includes the request and the sreg_response. |
306 |
|
307 |
return response |
|
17
by James Henstridge
Add code to integrate the OpenID code with django.contrib.auth. |
308 |
else: |
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
309 |
return render_failure(request, 'Disabled account') |
17
by James Henstridge
Add code to integrate the OpenID code with django.contrib.auth. |
310 |
else: |
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
311 |
return render_failure(request, 'Unknown user') |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
312 |
elif openid_response.status == FAILURE: |
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
313 |
return render_failure( |
314 |
request, 'OpenID authentication failed: %s' % |
|
315 |
openid_response.message) |
|
2
by swillison
Initial checkin |
316 |
elif openid_response.status == CANCEL: |
45
by James Henstridge
Clean up the failure handling a little, generating 403 responses rather |
317 |
return render_failure(request, 'Authentication cancelled') |
2
by swillison
Initial checkin |
318 |
else: |
15
by James Henstridge
Rework the OpenID consumer code to be a bit clearer, and make it |
319 |
assert False, ( |
320 |
"Unknown OpenID response type: %r" % openid_response.status) |
|
321 |
||
3
by swillison
Ready for launch |
322 |
|
10
by swillison
Extracted new logo() view |
323 |
def logo(request): |
324 |
return HttpResponse( |
|
325 |
OPENID_LOGO_BASE_64.decode('base64'), mimetype='image/gif' |
|
326 |
)
|
|
327 |
||
3
by swillison
Ready for launch |
328 |
# Logo from http://openid.net/login-bg.gif
|
329 |
# Embedded here for convenience; you should serve this as a static file
|
|
330 |
OPENID_LOGO_BASE_64 = """ |
|
331 |
R0lGODlhEAAQAMQAAO3t7eHh4srKyvz8/P5pDP9rENLS0v/28P/17tXV1dHEvPDw8M3Nzfn5+d3d
|
|
332 |
3f5jA97Syvnv6MfLzcfHx/1mCPx4Kc/S1Pf189C+tP+xgv/k1N3OxfHy9NLV1/39/f///yH5BAAA
|
|
333 |
AAAALAAAAAAQABAAAAVq4CeOZGme6KhlSDoexdO6H0IUR+otwUYRkMDCUwIYJhLFTyGZJACAwQcg
|
|
334 |
EAQ4kVuEE2AIGAOPQQAQwXCfS8KQGAwMjIYIUSi03B7iJ+AcnmclHg4TAh0QDzIpCw4WGBUZeikD
|
|
335 |
Fzk0lpcjIQA7
|
|
336 |
"""
|