def secure_url_with_token(self, url, user_data=None): if user_data is None: (user_data, _) = self.resolve_user_info() if not user_data: if not self.request_string("reset_token", default=""): logging.warn("No user detected for password change") return util.secure_url(url) token = TransferAuthToken.for_user(user_data).value if url.find('?') == -1: return "%s?transfer_token=%s" % (util.secure_url(url), urllib.quote_plus(token)) else: return "%s&transfer_token=%s" % (util.secure_url(url), urllib.quote_plus(token))
def _resolve_user_in_https_frame(handler): """Determine the current logged in user for the HTTPS request. This has logic in additional to UserData.current(), since it should also accept TransferAuthTokens, since HTTPS requests may not have normal HTTP cookies sent. """ user_data = UserData.current() if user_data: return user_data if not App.is_dev_server and not handler.request.uri.startswith('https'): return None # On https, users aren't recognized through the normal means of cookie auth # since their cookies were set on HTTP domains. token_value = handler.request_string("transfer_token", default=None) return TransferAuthToken.get_user_for_value( token_value, UserData.get_from_user_id)
def _resolve_user_in_https_frame(handler): """Determine the current logged in user for the HTTPS request. This has logic in additional to UserData.current(), since it should also accept TransferAuthTokens, since HTTPS requests may not have normal HTTP cookies sent. """ user_data = UserData.current() if user_data: return user_data if not App.is_dev_server and not handler.request.uri.startswith('https'): return None # On https, users aren't recognized through the normal means of cookie auth # since their cookies were set on HTTP domains. token_value = handler.request_string("transfer_token", default=None) return TransferAuthToken.get_user_for_value(token_value, UserData.get_from_user_id)
def render_outer(self): """Render the second part of the user signup step, after the user has verified ownership of their e-mail account. The request URI must include a valid token from an UnverifiedUser, and can be made via build_link(), or be made by a user without an existing password set. Note that the contents are actually rendered in an iframe so it can be sent over https (generated in render_form). """ (valid_token, _) = self.resolve_token() user_data = UserData.current() if valid_token and user_data: if not user_data.is_phantom: logging.info("User tried to verify e-mail and complete a " + "signup in a browser with an existing " + "signed-in user. Forcefully signing old user " + "out to avoid conflicts") self.redirect(util.create_logout_url(self.request.uri)) return # Ignore phantom users. user_data = None if not valid_token and not user_data: # Just take them to the homepage for now. self.redirect("/") return transfer_token = None if user_data: if user_data.has_password(): # The user already has a KA login - redirect them to their profile self.redirect(user_data.profile_root) return elif not user_data.has_sendable_email(): # This is a case where a Facebook user logged in and tried # to signup for a KA password. Unfortunately, since we don't # have their e-mail, we can't let them proceed, since, without # a valid e-mail we can't reset passwords, etc. logging.error("User tried to signup for password with " "no email associated with the account") self.redirect("/") return else: # Here we have a valid user, and need to transfer their identity # to the inner iframe that will be hosted on https. # Since their current cookies may not be transferred/valid in # https, mint a custom, short-lived token to transfer identity. transfer_token = TransferAuthToken.for_user(user_data).value template_values = { 'params': util.build_params({ 'token': valid_token, 'transfer_token': transfer_token, }), 'continue': self.request_string("continue", default="/") } self.render_jinja2_template('completesignup.html', template_values)