def dispatch(self): """Dispatches the requested method.""" request = self.request method_name = request.route.handler_method if not method_name: method_name = webapp2._normalize_handler_method(request.method) method = getattr(self, method_name, None) if method is None: # 405 Method Not Allowed. # The response MUST include an Allow header containing a # list of valid methods for the requested resource. # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6 valid = ', '.join(webapp2._get_handler_methods(self)) self.abort(405, headers=[('Allow', valid)]) # The handler only receives *args if no named variables are set. args, kwargs = request.route_args, request.route_kwargs if kwargs: args = () # bind session on dispatch (not in __init__) self.session = get_current_session() # init messages array based on session self.session['_gaetk_messages'] = self.session.get('_gaetk_messages', []) # Give authentication Hooks opportunity to do their thing self.authchecker(method, *args, **kwargs) # Execute the method. reply = method(*args, **kwargs) # find out which return convention was used - first set defaults ... content = reply statuscode = 200 cachingtime = self.default_cachingtime # ... then check if we got a 2-tuple reply ... if isinstance(reply, tuple) and len(reply) == 2: content, statuscode = reply # ... or a 3-tuple reply. if isinstance(reply, tuple) and len(reply) == 3: content, statuscode, cachingtime = reply # Finally begin sending the response response = self.serialize(content) if cachingtime: self.response.headers['Cache-Control'] = 'max-age=%d, public' % cachingtime # If we have gotten a `callback` parameter, we expect that this is a # [JSONP](http://en.wikipedia.org/wiki/JSONP#JSONP) cann and therefore add the padding if self.request.get('callback', None): response = "%s (%s)" % (self.request.get('callback', None), response) self.response.headers['Content-Type'] = 'text/javascript' else: self.response.headers['Content-Type'] = 'application/json' # Set status code and write JSON to output stream self.response.set_status(statuscode) self.response.out.write(response) self.response.out.write('\n')
def __init__(self, *args, **kwargs): """Initialize handler instance""" super(OpenIdLoginHandler, self).__init__(*args, **kwargs) # clean previous session self.session = get_current_session() self.session.regenerate_id() if self.session.is_active(): self.session.terminate()
def __init__(self, *args, **kwargs): """Initialize RequestHandler""" self.credential = None try: self.session = get_current_session() except AttributeError: # session middleware might not be enabled self.session = {} super(BasicHandler, self).__init__(*args, **kwargs) self.credential = None
def login_required(self): """Returns the currently logged in user.""" self.session = get_current_session() self.credential = None if self.session.get('uid'): self.credential = memcache.get("cred_%s" % self.session['uid']) if self.credential is None: self.credential = Credential.get_by_key_name(self.session['uid']) memcache.add("cred_%s" % self.session['uid'], self.credential, CRED_CACHE_TIMEOUT) # we don't have an active session if not self.credential: # no session information - try HTTP - Auth uid, secret = None, None # see if we have HTTP-Basic Auth Data if self.request.headers.get('Authorization'): auth_type, encoded = self.request.headers.get('Authorization').split(None, 1) if auth_type.lower() == 'basic': uid, secret = encoded.decode('base64').split(':', 1) credential = memcache.get("cred_%s" % uid) if not credential: credential = Credential.get_by_key_name(uid.strip() or ' *invalid* ') memcache.add("cred_%s" % uid, credential, CRED_CACHE_TIMEOUT) if credential and credential.secret == secret.strip(): # Successful login self.credential = credential self.session['uid'] = credential.uid # Log, but only once every 10h data = memcache.get("login_%s_%s" % (uid, self.request.remote_addr)) if not data: memcache.set("login_%s_%s" % (uid, self.request.remote_addr), True, 60 * 60 * 10) logging.info("HTTP-Login from %s/%s", uid, self.request.remote_addr) else: logging.error("failed HTTP-Login from %s/%s %s", uid, self.request.remote_addr, self.request.headers.get('Authorization')) else: logging.error("unknown HTTP-Login type %r %s %s", auth_type, self.request.remote_addr, self.request.headers.get('Authorization')) # HTTP Basic Auth failed if not self.credential: # Login not successfull if 'text/html' in self.request.headers.get('Accept', ''): # we assume the request came via a browser - redirect to the "nice" login page self.response.set_status(302) absolute_url = self.abs_url("/_ah/login_required?continue=%s" % urllib.quote(self.request.url)) self.response.headers['Location'] = str(absolute_url) raise HTTP302_Found(location=str(absolute_url)) else: # We assume the access came via cURL et al, request Auth vie 401 Status code. logging.debug("requesting HTTP-Auth %s %s", self.request.remote_addr, self.request.headers.get('Authorization')) raise HTTP401_Unauthorized(headers={'WWW-Authenticate': 'Basic realm="API Login"'}) return self.credential
def get(self): session = get_current_session() session['uid'] = None if session.is_active(): session.terminate() # log out OpenID user = users.get_current_user() if user: self.redirect(users.create_logout_url("/logout")) else: # Render Template with logout confirmation self.render({}, 'logout.html')
def get_current_user(): """Helper function to return a valid User instance. For users logged in via OpenID, the result is equivalent to users.get_current_user. If the user logged in via Basic Auth, the user id is taken from the related Credential object. """ user = users.get_current_user() if user is not None: return user else: session = get_current_session() if session and 'uid' in session: return users.User(_user_id=session['uid'], email=session.get('email', ''), _strict_mode=False)
def get(self): session = get_current_session() session['uid'] = None if session.is_active(): session.terminate() # log out OpenID and either redirect to 'continue' or display # the default logout confirmation page continue_url = self.request.get('continue') user = users.get_current_user() if user: self.redirect(users.create_logout_url(continue_url or '/logout')) else: # render template with logout confirmation if continue_url: self.redirect(continue_url) else: self.render({}, 'logout.html')
def get(self): """Logout user and terminate the current session""" session = get_current_session() session['uid'] = None if session.is_active(): session.terminate() # log out OpenID and either redirect to 'continue' or display # the default logout confirmation page continue_url = self.request.get('continue') user = users.get_current_user() if user: path = self.request.path self.redirect(users.create_logout_url(path)) else: if continue_url: self.redirect(continue_url) else: self.render({}, 'logout.html')
def dispatch(self): """Dispatches the requested method.""" request = self.request method_name = request.route.handler_method if not method_name: method_name = webapp2._normalize_handler_method(request.method) method = getattr(self, method_name, None) if method is None: # 405 Method Not Allowed. # The response MUST include an Allow header containing a # list of valid methods for the requested resource. # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.6 methods = [] for method in ('GET', 'POST', 'HEAD', 'OPTIONS', 'PUT', 'DELETE', 'TRACE'): if getattr(self, webapp2._normalize_handler_method(method), None): methods.append(method) valid = ', '.join(methods) self.abort(405, headers=[('Allow', valid)]) # The handler only receives *args if no named variables are set. args, kwargs = request.route_args, request.route_kwargs if kwargs: args = () # bind session on dispatch (not in __init__) try: self.session = get_current_session() except AttributeError: # session handling not activated self.session = {} # init messages array based on session self.session['_gaetk_messages'] = self.session.get('_gaetk_messages', []) # Give authentication Hooks opportunity to do their thing self.authchecker(method, *args, **kwargs) ret = method(*args, **kwargs) self.finished_hook(ret, method, *args, **kwargs) return ret
def dispatch(self): """Dispatches the requested method fom the WSGI App. Meant for internal use by the stack. """ request = self.request method_name = request.route.handler_method if not method_name: method_name = webapp2._normalize_handler_method(request.method) method = getattr(self, method_name, None) if hasattr(self, '__class__'): sentry_client.tags_context({ 'handler': self.__class__.__name__, 'method': method_name }) if method is None: # 405 Method Not Allowed. valid = b', '.join(webapp2._get_handler_methods(self)) raise exc.HTTP405_HTTPMethodNotAllowed( 'Method not allowed in {}'.format(self.__class__.__name__), headers=[(b'Allow', valid)], ) # The handler only receives *args if no named variables are set. args, kwargs = request.route_args, request.route_kwargs if kwargs: args = () # bind session on dispatch (not in __init__) try: self.session = gaesessions.get_current_session() except AttributeError: # probably session middleware not loaded self.session = {} if str(self.session) != 'uninitialized session': sentry_client.note('storage', 'Session loaded', data=dict(session=self.session)) try: self._call_all_inherited('pre_authentication_hook', method_name, *args, **kwargs) self._call_all_inherited('authentication_preflight_hook', method_name, *args, **kwargs) self._call_all_inherited('authentication_hook', method_name, *args, **kwargs) self._call_all_inherited('authorisation_hook', method_name, *args, **kwargs) self._call_all_inherited('method_preperation_hook', method_name, *args, **kwargs) try: response = method(*args, **kwargs) except TypeError: # parameter missmatch is the error we see most often # so help to pin down where it happens klass = introspection.get_class_that_defined_method(method) methname = method.__name__ sourcepos = '{}:{}'.format( os.path.basename(method.__func__.__code__.co_filename), method.__func__.__code__.co_firstlineno, ) LOGGER.debug( 'method called: %s.%s(%r) from %s', klass.__name__, methname, (args, kwargs), sourcepos, ) LOGGER.debug('defined at: %s %s', klass, sourcepos) raise response = self.response_overwrite(response, method, *args, **kwargs) except exc.HTTPException as e: # for HTTP exceptions execute `finished_hooks` if e.code < 500: self._call_all_inherited('finished_hook', method_name, *args, **kwargs) return self.handle_exception(e, self.app.debug) except BaseException as e: return self.handle_exception(e, self.app.debug) if response and not getattr(self, '_gaetk2_allow_strange_responses', False): assert isinstance(response, webapp2.Response) self._set_cache_headers() self._call_all_inherited('finished_hook', method_name, *args, **kwargs) self.finished_overwrite(response, method, *args, **kwargs) return response
def login_required(self, deny_localhost=True): """Returns the currently logged in user and forces login. Access from 127.0.0.1 is allowed without authentication if deny_localhost is false. """ self.session = get_current_session() self.credential = None if self.session.get('uid'): self.credential = memcache.get("cred_%s" % self.session['uid']) if self.credential is None: self.credential = Credential.get_by_key_name(self.session['uid']) memcache.add("cred_%s" % self.session['uid'], self.credential, CREDENTIAL_CACHE_TIMEOUT) # we don't have an active session - check if we are logged in via OpenID at least user = users.get_current_user() if user: logging.info('Google user = %s', user) # yes, active OpenID session # user.federated_provider() == 'https://www.google.com/a/hudora.de/o8/ud?be=o8' if not user.federated_provider(): # development server apps_domain = user.email().split('@')[-1].lower() else: apps_domain = user.federated_provider().split('/')[4].lower() username = user.email() self.credential = Credential.get_by_key_name(username) if not self.credential or not self.credential.uid == username: # So far we have no Credential entity for that user, create one if getattr(config, 'LOGIN_OPENID_CREDENTIAL_CREATOR', None): self.credential = config.LOGIN_OPENID_CREDENTIAL_CREATOR(user, apps_domain) if not self.credential: self.credential = create_credential_from_federated_login(user, apps_domain) self.session['uid'] = self.credential.uid # self.response.set_cookie('gaetk_opid', apps_domain, max_age=60*60*24*90) self.response.headers['Set-Cookie'] = 'gaetk_opid=%s; Max-Age=7776000' % apps_domain if not self.credential: # still no session information - try HTTP - Auth uid, secret = None, None # see if we have HTTP-Basic Auth Data if self.request.headers.get('Authorization'): auth_type, encoded = self.request.headers.get('Authorization').split(None, 1) if auth_type.lower() == 'basic': decoded = encoded.decode('base64') # If the Client send us invalid credentials, let him know , else parse into # username and password if ':' not in decoded: raise HTTP400_BadRequest("invalid credentials %r" % decoded) uid, secret = decoded.split(':', 1) # Pull credential out of memcache or datastore credential = memcache.get("cred_%s" % uid) if not credential: credential = Credential.get_by_key_name(uid.strip() or ' *invalid* ') memcache.add("cred_%s" % uid, credential, CREDENTIAL_CACHE_TIMEOUT) if credential and credential.secret == secret.strip(): # Successful login self.credential = credential self.session['uid'] = credential.uid # Log successful login, but only once every 10h data = memcache.get("login_%s_%s" % (uid, self.request.remote_addr)) if not data: memcache.set("login_%s_%s" % (uid, self.request.remote_addr), True, 60 * 60 * 10) logging.info("HTTP-Login from %s/%s", uid, self.request.remote_addr) else: logging.error("failed HTTP-Login from %s/%s %s", uid, self.request.remote_addr, self.request.headers.get('Authorization')) else: logging.error("unknown HTTP-Login type %r %s %s", auth_type, self.request.remote_addr, self.request.headers.get('Authorization')) # HTTP Basic Auth failed if not self.credential: if (self.request.remote_addr == '127.0.0.1') and not deny_localhost: logging.info('for testing we allow unauthenticated access from localhost') # create credential self.credential = Credential.create(tenant='localhost.', uid='0x7f000001', text='Automatically created for testing') else: # Login not successful if 'text/html' in self.request.headers.get('Accept', ''): # we assume the request came via a browser - redirect to the "nice" login page self.response.set_status(302) absolute_url = self.abs_url("/_ah/login_required?continue=%s" % urllib.quote(self.request.url)) self.response.headers['Location'] = str(absolute_url) raise HTTP302_Found(location=str(absolute_url)) else: # We assume the access came via cURL et al, request Auth vie 401 Status code. logging.info("requesting HTTP-Auth %s %s", self.request.remote_addr, self.request.headers.get('Authorization')) raise HTTP401_Unauthorized(headers={'WWW-Authenticate': 'Basic realm="API Login"'}) return self.credential
def get(self): """Handler for Federated login consumer (OpenID) AND HTTP-Basic-Auth. See http://code.google.com/appengine/articles/openid.html""" msg = '' continue_url = self.request.GET.get('continue', '/') openid_url = None session = get_current_session() # clean previous session if session.is_active(): session.terminate() # check if we are logged in via OpenID user = users.get_current_user() if user: logging.info('Google user = %s', user) # yes, active OpenID session # user.federated_provider() == 'https://www.google.com/a/hudora.de/o8/ud?be=o8' if not user.federated_provider(): # development server apps_domain = user.email().split('@')[-1].lower() else: apps_domain = user.federated_provider().split('/')[4].lower() username = user.email() credential = Credential.get_by_key_name(username) if not credential or not credential.uid == username: # So far we have no Credential entity for that user, create one if getattr(config, 'LOGIN_OPENID_CREDENTIAL_CREATOR', None): self.credential = config.LOGIN_OPENID_CREDENTIAL_CREATOR(user, apps_domain) if not self.credential: self.credential = create_credential_from_federated_login(user, apps_domain) session['uid'] = credential.uid # self.response.set_cookie('gaetk_opid', apps_domain, max_age=60*60*24*90) self.response.headers['Set-Cookie'] = 'gaetk_opid=%s; Max-Age=7776000' % apps_domain self.redirect(continue_url) return # we returned from the login form - did the user request OpenID login? for domain in ALLOWED_DOMAINS: if self.request.GET.get('%s.x' % domain): openid_url = 'https://www.google.com/accounts/o8/site-xrds?hd=%s' % domain if openid_url: logging.info("Openid login requested to %s", openid_url) if openid_url: # Hand over Authentication Processing to Google/OpenID self.redirect(users.create_login_url(continue_url, None, openid_url)) return else: # Try user:pass based Authentication username, password = None, None # see if we have HTTP-Basic Auth Data if self.request.headers.get('Authorization'): auth_type, encoded = self.request.headers.get('Authorization').split(None, 1) if auth_type.lower() == 'basic': username, password = encoded.decode('base64').split(':', 1) # see if we have gotten some Form Data instead if not (username and password): username = self.request.get('username').strip() password = self.request.get('password').strip() # verify user & password if username: logging.info("Login Attempt for %s", username) credential = Credential.get_by_key_name(username) if credential and credential.secret == password: # successfull login session['uid'] = credential.uid # redirect back where we came from logging.info("Login durch %s/%s, Umleitung zu %s", username, self.request.remote_addr, continue_url) self.redirect(continue_url) return else: logging.warning("Invalid Password for %s:%s", username, password) msg = 'Kann sie nicht anmelden' # Render Template with Login form self.render({'continue': continue_url, 'domains': ALLOWED_DOMAINS, 'msg': msg}, 'login.html')