Merge lp:~wallyworld/launchpad/openid-oops-810623 into lp:launchpad

Proposed by Ian Booth
Status: Merged
Approved by: Curtis Hovey
Approved revision: no longer in the source branch.
Merged at revision: 16173
Proposed branch: lp:~wallyworld/launchpad/openid-oops-810623
Merge into: lp:launchpad
Diff against target: 86 lines (+33/-6)
2 files modified
lib/lp/services/webapp/login.py (+20/-6)
lib/lp/services/webapp/tests/test_login.py (+13/-0)
To merge this branch: bzr merge lp:~wallyworld/launchpad/openid-oops-810623
Reviewer Review Type Date Requested Status
Curtis Hovey (community) code Approve
Review via email: mp+130467@code.launchpad.net

Commit message

Display a login error rather than oopsing if open id provider sends a response with missing fields

Description of the change

== Implementation ==

When the response from the open id provider does not contain the expected full name and email fields, display the error page rather than oopsing.

== Tests ==

Add new test to TestOpenIDCallbackView

== Lint ==

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/services/webapp/login.py
  lib/lp/services/webapp/tests/test_login.py

To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :

Thank. I really do dislike the "assert" keyword

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/services/webapp/login.py'
--- lib/lp/services/webapp/login.py 2012-09-28 06:01:02 +0000
+++ lib/lp/services/webapp/login.py 2012-10-19 02:20:31 +0000
@@ -24,6 +24,10 @@
24 setDefaultFetcher,24 setDefaultFetcher,
25 Urllib2Fetcher,25 Urllib2Fetcher,
26 )26 )
27from paste.httpexceptions import (
28 HTTPBadRequest,
29 HTTPException,
30 )
27import transaction31import transaction
28from z3c.ptcompat import ViewPageTemplateFile32from z3c.ptcompat import ViewPageTemplateFile
29from zope.app.security.interfaces import IUnauthenticatedPrincipal33from zope.app.security.interfaces import IUnauthenticatedPrincipal
@@ -333,12 +337,14 @@
333 # asked to. Once we start using other OPs we won't be able to337 # asked to. Once we start using other OPs we won't be able to
334 # make this assumption here as they might not include what we338 # make this assumption here as they might not include what we
335 # want in the response.339 # want in the response.
336 assert self.sreg_response is not None, (340 if self.sreg_response is None:
337 "OP didn't include an sreg extension in the response.")341 raise HTTPBadRequest(
342 "OP didn't include an sreg extension in the response.")
338 email_address = self.sreg_response.get('email')343 email_address = self.sreg_response.get('email')
339 full_name = self.sreg_response.get('fullname')344 full_name = self.sreg_response.get('fullname')
340 assert email_address is not None and full_name is not None, (345 if email_address is None or full_name is None:
341 "No email address or full name found in sreg response")346 raise HTTPBadRequest(
347 "No email address or full name found in sreg response.")
342 return email_address, full_name348 return email_address, full_name
343349
344 def processPositiveAssertion(self):350 def processPositiveAssertion(self):
@@ -389,7 +395,11 @@
389395
390 def render(self):396 def render(self):
391 if self.openid_response.status == SUCCESS:397 if self.openid_response.status == SUCCESS:
392 return self.processPositiveAssertion()398 try:
399 return self.processPositiveAssertion()
400 except HTTPException as error:
401 return OpenIDLoginErrorView(
402 self.context, self.request, login_error=error.message)()
393403
394 if self.account is not None:404 if self.account is not None:
395 # The authentication failed (or was canceled), but the user is405 # The authentication failed (or was canceled), but the user is
@@ -432,10 +442,14 @@
432 page_title = 'Error logging in'442 page_title = 'Error logging in'
433 template = ViewPageTemplateFile("templates/login-error.pt")443 template = ViewPageTemplateFile("templates/login-error.pt")
434444
435 def __init__(self, context, request, openid_response):445 def __init__(self, context, request, openid_response=None,
446 login_error=None):
436 super(OpenIDLoginErrorView, self).__init__(context, request)447 super(OpenIDLoginErrorView, self).__init__(context, request)
437 assert self.account is None, (448 assert self.account is None, (
438 "Don't try to render this page when the user is logged in.")449 "Don't try to render this page when the user is logged in.")
450 if login_error:
451 self.login_error = login_error
452 return
439 if openid_response.status == CANCEL:453 if openid_response.status == CANCEL:
440 self.login_error = "User cancelled"454 self.login_error = "User cancelled"
441 elif openid_response.status == FAILURE:455 elif openid_response.status == FAILURE:
442456
=== modified file 'lib/lp/services/webapp/tests/test_login.py'
--- lib/lp/services/webapp/tests/test_login.py 2012-09-28 06:25:44 +0000
+++ lib/lp/services/webapp/tests/test_login.py 2012-10-19 02:20:31 +0000
@@ -439,6 +439,19 @@
439 main_content = extract_text(find_main_content(html))439 main_content = extract_text(find_main_content(html))
440 self.assertIn('Team email address conflict', main_content)440 self.assertIn('Team email address conflict', main_content)
441441
442 def test_missing_fields(self):
443 # If the OpenID provider response does not include required fields
444 # (full name or email missing), the login error page is shown.
445 person = self.factory.makePerson()
446 with SRegResponse_fromSuccessResponse_stubbed():
447 view, html = self._createViewWithResponse(
448 person.account, email=None)
449 self.assertFalse(view.login_called)
450 main_content = extract_text(find_main_content(html))
451 self.assertIn(
452 'No email address or full name found in sreg response',
453 main_content)
454
442 def test_negative_openid_assertion(self):455 def test_negative_openid_assertion(self):
443 # The OpenID provider responded with a negative assertion, so the456 # The OpenID provider responded with a negative assertion, so the
444 # login error page is shown.457 # login error page is shown.