def account_login_browserid(context, request): return_key = key_from_request(request) def fail(msg=None): if msg: request.session.flash(msg, level=u'error', icon='key--exclamation') # XXX setting the status to 403 triggers Pyramid's exception view next_url = request.route_url('account.login') if return_key is not None: next_url = update_params(next_url, return_key=return_key) return {'next_url': next_url} ## Verify the identity assertion assertion = request.POST.get('assertion') try: data = verify_browserid(assertion, request) except BrowserIDError as e: flash_browserid_error(e, request) return fail() ## Attempt to resolve the identity to a local user email = data.get('email') if data.get('status') != 'okay' or not email: return fail("BrowserID authentication failed.") identity_email = model.session.query(IdentityEmail) \ .filter_by(email=email) \ .limit(1).first() if not identity_email: # New user or new ID request.session['pending_identity_email'] = email return {'next_url': request.route_url('account.register'), 'post_id': 'postform'} ## Attempt to log in try: auth_headers = security.remember( request, identity_email.user, browserid_email=email) request.session.changed() except BrowserIDNotFoundError: return fail("The email address '{0}' is registered against the account " "'{1}'. To log in as '{1}', log out then back in." .format(email, identity_email.user.name)) except BrowserIDAuthDisabledError: return fail("Your BrowserID is no longer accepted as your account has " "disabled BrowserID authentication.") # An existing user has logged in successfully. Bravo! request.response.headerlist.extend(auth_headers) log.debug("User {0} logged in via BrowserID: {1}" .format(identity_email.user.name, identity_email)) ## Handle redirection if identity_email.user == request.user: # Someone is just freshening up their cookie request.session.flash(u'Re-authentication successful', icon='user') if return_key is not None: old_url = fetch_stash(request, key=return_key)['url'] if old_url: next_url = update_params(old_url, return_key=return_key) log.debug('Following Return Key \'{0}\' to URL: {1}' .format(return_key, next_url)) return {'next_url': next_url} return {'next_url': request.route_url('root')} # Existing user; new login request.session.flash( 'Logged in with BrowserID', level=u'success', icon='user') return {'next_url': request.route_url('root')}
def account_login_persona(context, request): return_key = key_from_request(request) def fail(msg=None, exc=None): if msg: request.session.flash(msg, level=u'error', icon='key--exclamation') # XXX setting the status to 403 triggers Pyramid's exception view next_url = request.route_url('account.login') if return_key is not None: next_url = update_params(next_url, return_key=return_key) return { 'status': 'redirect', 'redirect-to': next_url, } ## Verify the identity assertion assertion = request.POST.get('assertion') try: data = verify_persona(assertion, request) except PersonaError as e: flash_persona_error(e, request) return fail() ## Attempt to resolve the identity to a local user email = data.get('email') if data.get('status') != 'okay' or not email: return fail("Persona authentication failed.") identity_email = model.session.query(IdentityEmail) \ .filter_by(email=email) \ .limit(1).first() if not identity_email: # New user or new ID request.session['pending_identity_email'] = email return { 'status': 'redirect', 'redirect-to': request.route_url('account.register'), } ## Attempt to log in try: auth_headers = security.remember( request, identity_email.user, persona_addr=email) request.session.changed() except PersonaNotFoundError: return fail("The email address '{0}' is registered against the account " "'{1}'. To log in as '{1}', log out then back in." .format(email, identity_email.user.name)) except PersonaAuthDisabledError: return fail("Your Persona is no longer accepted as your account has " "disabled Persona authentication.") # An existing user has logged in successfully. Bravo! request.response.headerlist.extend(auth_headers) log.debug("User {0} logged in via Persona: {1}" .format(identity_email.user.name, identity_email)) ## Handle redirection if identity_email.user == request.user: # Someone is just freshening up their cookie request.session.flash(u'Re-authentication successful', icon='user') if return_key is not None: old_url = fetch_stash(request, key=return_key)['url'] if old_url: next_url = update_params(old_url, return_key=return_key) log.debug('Following Return Key \'{0}\' to URL: {1}' .format(return_key, next_url)) return { 'status': 'redirect', 'redirect-to': next_url, } else: # Existing user; new login request.session.flash( 'Logged in with Persona', level=u'success', icon='user') # XXX this seems a mite fragile redirect = request.route_url('root') pathq = request.POST.get('pathq') if pathq and not pathq.startswith(request.route_path('account.login')): scheme, netloc = urlparse(redirect)[:2] redirect = urlunparse((scheme, netloc, pathq, '', '', '')) return { 'status': 'redirect', 'redirect-to': redirect, }
def login_finish(context, request): """Step two of logging in; the OpenID provider redirects back here.""" def retry(): """Redirect to the login page, preserving the return key (if any).""" location = request.route_url('account.login') if return_key: location = update_params(location, return_key=return_key) return HTTPSeeOther(location=location) return_url = request.route_url('account.login_finish') return_key = key_from_request(request) if return_key is not None: return_url = update_params(return_url, return_key=return_key) try: identity_url, identity_webfinger, auth_time, sreg_res = openid_end( return_url=return_url, request=request) except OpenIDError as exc: request.session.flash(exc.message, level='error', icon='key--exclamation') return retry() # Find who owns this URL, if anyone identity_owner = model.session.query(User) \ .filter(User.identity_urls.any(url=identity_url)) \ .limit(1).first() if not identity_owner: if return_key: request.session.flash('Unknown OpenID URL.', level='error', icon='key--exclamation') return retry() # Someone is either registering a new account, or adding a new OpenID # to an existing account request.session['pending_identity_url'] = identity_url request.session.changed() # Try to pull a name and email address out of the SReg response username = re.sub(u'[^_a-z0-9]', u'', sreg_res.get('nickname', u'').lower()) form = RegistrationForm( username=username, email=sreg_res.get('email', u''), timezone=sreg_res.get('timezone', u'UTC'), ) return render_to_response( 'account/register.mako', dict( form=form, identity_url=identity_url, identity_webfinger=identity_webfinger, identity_email=None), request=request) elif identity_owner == request.user: # Someone is just freshening up their cookie auth_headers = safe_openid_login(request, identity_owner, identity_url) if auth_headers is None: return retry() request.session.flash(u'Re-authentication successful', icon='user') if return_key: # Fetch a stashed request old_url = fetch_stash(request, key=return_key)['url'] if old_url: location = update_params(old_url, return_key=return_key) log.debug('Following Return Key \'{0}\' to URL: {1}' .format(return_key, location)) return HTTPSeeOther(location, headers=auth_headers) return HTTPSeeOther(request.route_url('root'), headers=auth_headers) else: # Existing user; new login # Log the successful OpenID authentication, mindful of users that may # have OpenID logins disabled, for instance. # XXX should we deny a logged-in user to authenticate as another user? auth_headers = security.forget(request) headers = safe_openid_login(request, identity_owner, identity_url) if headers is None: return retry() auth_headers += headers # An existing user has logged in successfully. Bravo! log.debug("User {0!r} logged in via OpenID: {1!r}" .format(identity_owner.name, identity_url)) request.session.flash( u"Welcome back, {0}!" .format(identity_owner.display_name or identity_owner.name), level=u'success', icon='user') # XXX this should ALSO probably do the return_key redirect, good grief return HTTPSeeOther( location=request.route_url('root'), headers=auth_headers)