def get_session(self): try: # Get session based on OAuth token auth_hdr = request.headers.get("authorization", None) if auth_hdr: valid, req = self.oauth.verify_request([self.oauth_scope]) if valid: actor_id = flask.g.oauth_user.get("actor_id", "") actor_user = self.idm_client.read_actor_identity(actor_id) session_attrs = dict(is_logged_in=True, is_registered=True, attributes={"roles":actor_user.details.contact.roles}, roles={}) if actor_user.session: session_attrs.update(actor_user.session) return build_json_response(session_attrs) # Support quick reload access_token = flask.session.get("access_token", None) actor_id = flask.session.get("actor_id", None) if access_token and actor_id: actor_user = self.idm_client.read_actor_identity(actor_id) session_attrs = dict(access_token=access_token, is_logged_in=True, is_registered=True, attributes={"roles":actor_user.details.contact.roles}, roles={}) if actor_user.session: session_attrs.update(actor_user.session) return build_json_response(session_attrs) # Get session from Flask session and cookie user_info = get_auth() if 0 < int(user_info.get("valid_until", 0)) * 1000 < current_time_millis(): clear_auth() user_info = get_auth() return build_json_response(user_info) except Exception: return build_json_error()
def get_governance_info_from_request(self, json_params=None): # Default values for governance headers. actor_id = DEFAULT_ACTOR_ID expiry = DEFAULT_EXPIRY authtoken = "" user_session = get_auth() if user_session.get("actor_id", None) and user_session.get("valid_until", 0): # Get info from current server session # NOTE: Actor id may be inside server session actor_id = user_session["actor_id"] expiry = str(int(user_session.get("valid_until", 0)) * 1000) log.info("Request associated with session actor_id=%s, expiry=%s", actor_id, expiry) # Developer access using api_key if self.develop_mode and "api_key" in request.args and request.args["api_key"]: actor_id = str(request.args["api_key"]) expiry = str(int(user_session.get("valid_until", 0)) * 1000) if 0 < int(expiry) < current_time_millis(): expiry = str(current_time_millis() + 10000) # flask.session["valid_until"] = int(expiry / 1000) log.info("Request associated with actor_id=%s, expiry=%s from developer api_key", actor_id, expiry) # Check in headers for OAuth2 bearer token auth_hdr = request.headers.get("authorization", None) if auth_hdr: valid, req = self.process.oauth.verify_request([self.process.oauth_scope]) if valid: actor_id = flask.g.oauth_user.get("actor_id", "") if actor_id: log.info("Request associated with actor_id=%s, expiry=%s from OAuth token", actor_id, expiry) return actor_id, DEFAULT_EXPIRY # Try to find auth token override if not authtoken: if json_params: if "authtoken" in json_params: authtoken = json_params["authtoken"] else: if "authtoken" in request.args: authtoken = str(request.args["authtoken"]) # Enable temporary authentication tokens to resolve to actor ids if authtoken: try: token_info = self.idm_client.check_authentication_token(authtoken, headers=self._get_gateway_headers()) actor_id = token_info.get("actor_id", actor_id) expiry = token_info.get("expiry", expiry) log.info("Resolved token %s into actor_id=%s expiry=%s", authtoken, actor_id, expiry) except NotFound: log.info("Provided authentication token not found: %s", authtoken) except Unauthorized: log.info("Authentication token expired or invalid: %s", authtoken) except Exception as ex: log.exception("Problem resolving authentication token") return actor_id, expiry
def _get_user_info(self, actor_id, username=None): actor_user = self.idm_client.read_identity_details(actor_id) if actor_user.type_ != OT.UserIdentityDetails: raise BadRequest("Bad identity details") full_name = actor_user.contact.individual_names_given + " " + actor_user.contact.individual_name_family valid_until = int(get_ion_ts_millis() / 1000 + self.session_timeout) set_auth(actor_id, username, full_name, valid_until=valid_until, roles=actor_user.contact.roles) user_info = get_auth() return user_info
def _set_server_session(self, actor_id, username=None): """ Sets server session based on user_id and ActorIdentity. """ actor_user = self.idm_client.read_identity_details(actor_id) if actor_user.type_ != OT.UserIdentityDetails: raise BadRequest("Bad identity details") full_name = actor_user.contact.individual_names_given + " " + actor_user.contact.individual_name_family valid_until = int(get_ion_ts_millis() / 1000 + self.session_timeout) set_auth(actor_id, username, full_name, valid_until=valid_until, roles=actor_user.contact.roles) user_info = get_auth() return user_info
def validate_request(self, ion_actor_id, expiry, in_whitelist=False): # There is no point in looking up an anonymous user - so return default values. if ion_actor_id == DEFAULT_ACTOR_ID: # Since this is an anonymous request, there really is no expiry associated with it if not in_whitelist and self.require_login: raise Unauthorized("Anonymous access not permitted") else: return DEFAULT_ACTOR_ID, DEFAULT_EXPIRY try: user = self.idm_client.read_actor_identity( actor_id=ion_actor_id, headers=self._get_gateway_headers()) except NotFound as e: if not in_whitelist and self.require_login: # This could be a restart of the system with a new preload. # TODO: Invalidate Flask sessions on relaunch/bootstrap with creating new secret user_session = get_auth() if user_session.get("actor_id", None) == ion_actor_id: clear_auth() raise Unauthorized("Invalid identity", exc_id="01.10") else: # If the user isn't found default to anonymous return DEFAULT_ACTOR_ID, DEFAULT_EXPIRY # Need to convert to int first in order to compare against current time. try: int_expiry = int(expiry) except Exception as ex: raise Inconsistent( "Unable to read the expiry value in the request '%s' as an int" % expiry) # The user has been validated as being known in the system, so not check the expiry and raise exception if # the expiry is not set to 0 and less than the current time. if 0 < int_expiry < current_time_millis(): if not in_whitelist and self.require_login: raise Unauthorized("User authentication expired") else: log.warn("User authentication expired") return DEFAULT_ACTOR_ID, DEFAULT_EXPIRY return ion_actor_id, expiry
def validate_request(self, ion_actor_id, expiry, in_whitelist=False): # There is no point in looking up an anonymous user - so return default values. if ion_actor_id == DEFAULT_ACTOR_ID: # Since this is an anonymous request, there really is no expiry associated with it if not in_whitelist and self.require_login: raise Unauthorized("Anonymous access not permitted") else: return DEFAULT_ACTOR_ID, DEFAULT_EXPIRY try: user = self.idm_client.read_actor_identity(actor_id=ion_actor_id, headers=self._get_gateway_headers()) except NotFound as e: if not in_whitelist and self.require_login: # This could be a restart of the system with a new preload. # TODO: Invalidate Flask sessions on relaunch/bootstrap with creating new secret user_session = get_auth() if user_session.get("actor_id", None) == ion_actor_id: clear_auth() raise Unauthorized("Invalid identity", exc_id="01.10") else: # If the user isn't found default to anonymous return DEFAULT_ACTOR_ID, DEFAULT_EXPIRY # Need to convert to int first in order to compare against current time. try: int_expiry = int(expiry) except Exception as ex: raise Inconsistent("Unable to read the expiry value in the request '%s' as an int" % expiry) # The user has been validated as being known in the system, so not check the expiry and raise exception if # the expiry is not set to 0 and less than the current time. if 0 < int_expiry < current_time_millis(): if not in_whitelist and self.require_login: raise Unauthorized("User authentication expired") else: log.warn("User authentication expired") return DEFAULT_ACTOR_ID, DEFAULT_EXPIRY return ion_actor_id, expiry
def get_session(self): """ Returns user session information for current authentication. This can be polled regularly by client code to detect changes in session state and expiration. """ def call_extend_session_attrs(session_attrs, actor_user): """ Call UI extensions to make additions to user session """ for ext_obj in self.extension_objs: func = getattr(ext_obj, "extend_user_session_attributes", None) if func: try: func(session_attrs, actor_user) except Exception: log.exception("Error calling UI extension extend_user_session_attributes()") try: # Get user session from OAuth access token in HTTP Authorization header auth_hdr = request.headers.get("authorization", None) if auth_hdr: valid, req = self.oauth.verify_request([self.oauth_scope]) # Note: Do NOT extend session timeout here! if valid: actor_id = flask.g.oauth_user.get("actor_id", "") actor_user = self.idm_client.read_actor_identity(actor_id) session_attrs = dict(is_logged_in=True, is_registered=True, attributes={"roles": actor_user.details.contact.roles}, roles={}) if actor_user.session: session_attrs.update(actor_user.session) call_extend_session_attrs(session_attrs, actor_user) return build_json_response(session_attrs) if self.remember_user: # Get user session from user_id/access_token placed inside server session (Cookie) # This is a feature to allow returning users to resume a session if still valid access_token = flask.session.get("access_token", None) actor_id = flask.session.get("actor_id", None) if access_token and actor_id: actor_user = self.idm_client.read_actor_identity(actor_id) session_attrs = dict(access_token=access_token, is_logged_in=True, is_registered=True, attributes={"roles": actor_user.details.contact.roles}, roles={}) if actor_user.session: # Check validity in persisted user session if 0 < int(actor_user.session.get("valid_until", 0)) * 1000 < current_time_millis(): clear_auth() return build_json_response(get_auth()) session_attrs.update(actor_user.session) else: # No trace of existing session in user object clear_auth() return build_json_response(get_auth()) call_extend_session_attrs(session_attrs, actor_user) return build_json_response(session_attrs) # Get user session from Flask session and cookie (non-token mode) user_info = get_auth() if 0 < int(user_info.get("valid_until", 0)) * 1000 < current_time_millis(): clear_auth() # Clear expired session user_info = get_auth() call_extend_session_attrs(user_info, None) return build_json_response(user_info) except Exception: return build_json_error()
def get_governance_info_from_request(self, json_params=None): # Default values for governance headers. actor_id = DEFAULT_ACTOR_ID expiry = DEFAULT_EXPIRY authtoken = "" user_session = get_auth() #if user_session.get("actor_id", None) and user_session.get("valid_until", 0): if user_session.get("actor_id", None): # Get info from current server session # NOTE: Actor id may be inside server session expiry = int(user_session.get("valid_until", 0)) * 1000 if expiry: # This was a proper non-token server session authentication expiry = str(expiry) actor_id = user_session["actor_id"] log.info( "Request associated with session actor_id=%s, expiry=%s", actor_id, expiry) else: # We are just taking the user_id out of the session # TODO: Need to check access token here expiry = str(expiry) if self.token_from_session: actor_id = user_session["actor_id"] log.info( "Request associated with actor's token from session; actor_id=%s, expiry=%s", actor_id, expiry) # Developer access using api_key if self.develop_mode and "api_key" in request.args and request.args[ "api_key"]: actor_id = str(request.args["api_key"]) expiry = str(int(user_session.get("valid_until", 0)) * 1000) if 0 < int(expiry) < current_time_millis(): expiry = str(current_time_millis() + 10000) # flask.session["valid_until"] = int(expiry / 1000) log.info( "Request associated with actor_id=%s, expiry=%s from developer api_key", actor_id, expiry) # Check in headers for OAuth2 bearer token auth_hdr = request.headers.get("authorization", None) if auth_hdr: valid, req = self.process.oauth.verify_request( [self.process.oauth_scope]) if valid: actor_id = flask.g.oauth_user.get("actor_id", "") if actor_id: log.info( "Request associated with actor_id=%s, expiry=%s from OAuth token", actor_id, expiry) return actor_id, DEFAULT_EXPIRY # Try to find auth token override if not authtoken: if json_params: if "authtoken" in json_params: authtoken = json_params["authtoken"] else: if "authtoken" in request.args: authtoken = str(request.args["authtoken"]) # Enable temporary authentication tokens to resolve to actor ids if authtoken: try: token_info = self.idm_client.check_authentication_token( authtoken, headers=self._get_gateway_headers()) actor_id = token_info.get("actor_id", actor_id) expiry = token_info.get("expiry", expiry) log.info("Resolved token %s into actor_id=%s expiry=%s", authtoken, actor_id, expiry) except NotFound: log.info("Provided authentication token not found: %s", authtoken) except Unauthorized: log.info("Authentication token expired or invalid: %s", authtoken) except Exception as ex: log.exception("Problem resolving authentication token") return actor_id, expiry
def get_governance_info_from_request(self, json_params=None): # Default values for governance headers. actor_id = DEFAULT_ACTOR_ID expiry = DEFAULT_EXPIRY authtoken = "" user_session = get_auth() #if user_session.get("actor_id", None) and user_session.get("valid_until", 0): if user_session.get("actor_id", None): # Get info from current server session # NOTE: Actor id may be inside server session expiry = int(user_session.get("valid_until", 0)) * 1000 if expiry: # This was a proper non-token server session authentication expiry = str(expiry) actor_id = user_session["actor_id"] log.info("Request associated with session actor_id=%s, expiry=%s", actor_id, expiry) else: # We are just taking the user_id out of the session # TODO: Need to check access token here expiry = str(expiry) if self.token_from_session: actor_id = user_session["actor_id"] log.info("Request associated with actor's token from session; actor_id=%s, expiry=%s", actor_id, expiry) # Developer access using api_key if self.develop_mode and "api_key" in request.args and request.args["api_key"]: actor_id = str(request.args["api_key"]) expiry = str(int(user_session.get("valid_until", 0)) * 1000) if 0 < int(expiry) < current_time_millis(): expiry = str(current_time_millis() + 10000) # flask.session["valid_until"] = int(expiry / 1000) log.info("Request associated with actor_id=%s, expiry=%s from developer api_key", actor_id, expiry) # Check in headers for OAuth2 bearer token auth_hdr = request.headers.get("authorization", None) if auth_hdr: valid, req = self.process.oauth.verify_request([self.process.oauth_scope]) if valid: actor_id = flask.g.oauth_user.get("actor_id", "") if actor_id: log.info("Request associated with actor_id=%s, expiry=%s from OAuth token", actor_id, expiry) return actor_id, DEFAULT_EXPIRY # Try to find auth token override if not authtoken: if json_params: if "authtoken" in json_params: authtoken = json_params["authtoken"] else: if "authtoken" in request.args: authtoken = str(request.args["authtoken"]) # Enable temporary authentication tokens to resolve to actor ids if authtoken: try: if authtoken.startswith(("Bearer_")): # Backdoor way for OAuth2 access tokens as request args for GET URLs authtoken = authtoken[7:] token_id = "access_token_" + str(authtoken) token_obj = self.process.container.object_store.read(token_id) token = OAuthTokenObj.from_security_token(token_obj) if token.is_valid(check_expiry=True): actor_id = token.user["actor_id"] expiry = str(token._token_obj.expires) log.info("Resolved OAuth2 token %s into actor_id=%s expiry=%s", authtoken, actor_id, expiry) else: token_info = self.idm_client.check_authentication_token(authtoken, headers=self._get_gateway_headers()) actor_id = token_info.get("actor_id", actor_id) expiry = token_info.get("expiry", expiry) log.info("Resolved token %s into actor_id=%s expiry=%s", authtoken, actor_id, expiry) except NotFound: log.info("Provided authentication token not found: %s", authtoken) except Unauthorized: log.info("Authentication token expired or invalid: %s", authtoken) except Exception as ex: log.exception("Problem resolving authentication token") return actor_id, expiry