def delete(self): """ Logout user. Invalidate token :return: """ data = flask.request.json try: refresh_token = data[FormKeyInput.KEYCLOAK_REFRESH_TOKEN.value] return AuthorizationManager.get_keycloak_instance().logout(refresh_token) except KeyError: raise InvalidInputException("Invalid refresh token input.")
def _build_secured_request(): token_file_path = os.path.join(HPCSchedulerClient.HOME_FOLDER_MOUNT, ".token") kc_config_file_path = os.path.join(HPCSchedulerClient.HOME_FOLDER_MOUNT, ".kc_config") token = "" if os.path.exists(token_file_path) and os.path.exists(kc_config_file_path): try: with open(token_file_path, "r") as file: refresh_token = file.read() kc_instance = AuthorizationManager(kc_config_file_path).get_keycloak_instance() response = kc_instance.refresh_token(refresh_token.replace('\n', '')) token = response['access_token'] except Exception as e: log.error(e, exc_info=True) else: log.warning("Token file was not found.") with requests.Session() as request: auth_header = {"Authorization": "Bearer {}".format(token)} request.headers.update(auth_header) return request
def get(self): redirect_uri = flask.request.args.get(FormKeyInput.REDIRECT_URI.value) if redirect_uri is None: raise InvalidInputException(message="Invalid redirect uri") keycloak_instance = AuthorizationManager.get_keycloak_instance() auth_url = keycloak_instance.auth_url(redirect_uri) + "&scope=openid profile email" account_url = keycloak_instance.connection.base_url + "realms/{}/account".format(keycloak_instance.realm_name) return { Strings.AUTH_URL.value: auth_url, Strings.ACCOUNT_URL.value: account_url }
def post(self): """ Authorize user in the configured Keycloak server :return a dict which contains user's tokens """ try: data = flask.request.json return AuthorizationManager.get_keycloak_instance().token( data[FormKeyInput.USERS_USERNAME.value], data[FormKeyInput.USERS_PASSWORD.value]) except KeyError: raise InvalidInputException("Invalid input.")
def index(self, **data): """ Login page (with or without messages). """ template_specification = dict(mainContent="user/login", title="Login", data=data) self._set_base_url() if cherrypy.request.method == 'POST': keycloak_login = TvbProfile.current.KEYCLOAK_LOGIN_ENABLED form = LoginForm() if not keycloak_login else KeycloakLoginForm() try: data = form.to_python(data) if keycloak_login: auth_token = data[KEY_AUTH_TOKEN] kc_user_info = AuthorizationManager( TvbProfile.current.KEYCLOAK_WEB_CONFIG ).get_keycloak_instance().userinfo(auth_token) user = self.user_service.get_external_db_user(kc_user_info) else: username = data[KEY_USERNAME] password = data[KEY_PASSWORD] user = self.user_service.check_login(username, password) if user is not None: common.add2session(common.KEY_USER, user) common.set_info_message('Welcome ' + user.display_name) self.logger.debug("User " + user.username + " has just logged in!") if user.selected_project is not None: prj = user.selected_project prj = ProjectService().find_project(prj) self._mark_selected(prj) raise cherrypy.HTTPRedirect('/user/profile') elif not keycloak_login: common.set_error_message( 'Wrong username/password, or user not yet validated...' ) self.logger.debug("Wrong username " + username + " !!!") else: common.set_error_message( 'Your account is not validated. Please contact us at [email protected] for more details' ) self.logger.debug("Invalidated account") template_specification[common.KEY_ERRORS] = { 'invalid_user': True } except formencode.Invalid as excep: template_specification[ common.KEY_ERRORS] = excep.unpack_errors() return self.fill_default_attributes(template_specification)
def _extract_user_info(self, keycloak_data): email = keycloak_data['email'] if 'email' in keycloak_data else None user_roles = keycloak_data['roles'] if 'roles' in keycloak_data else [] client_id = AuthorizationManager().get_keycloak_instance().client_id user_client_roles = user_roles[client_id] if client_id in user_roles else [] role = ROLE_ADMINISTRATOR if ROLE_ADMINISTRATOR in user_client_roles else None if role == ROLE_ADMINISTRATOR: self.logger.info("Administrator logged in") username = keycloak_data['preferred_username'] if 'preferred_username' in keycloak_data else keycloak_data[ 'sub'] name = keycloak_data['name'] if 'name' in keycloak_data else keycloak_data['sub'] return username, name, email, role
def post(self): """ Authorize user in the configured Keycloak server :return a dict which contains user's tokens """ try: data = flask.request.json code = data[FormKeyInput.CODE.value] redirect_uri = data[FormKeyInput.REDIRECT_URI.value] return AuthorizationManager.get_keycloak_instance().token(code=code, grant_type=["authorization_code"], redirect_uri=redirect_uri) except KeyError: raise InvalidInputException("Invalid input.")
def deco(*a, **b): authorization = cherrypy.request.headers["Authorization"] if "Authorization" in cherrypy.request.headers \ else None if not authorization: raise cherrypy.HTTPError(HTTPStatus.UNAUTHORIZED, "Token is missing") token = authorization.replace("Bearer ", "") try: AuthorizationManager(TvbProfile.current.KEYCLOAK_WEB_CONFIG ).get_keycloak_instance().userinfo(token) except KeycloakError as kc_error: try: error_message = json.loads( kc_error.error_message.decode())['error_description'] except (KeyError, TypeError): error_message = kc_error.error_message.decode() raise cherrypy.HTTPError(HTTPStatus.UNAUTHORIZED, error_message) return func(*a, **b)
def _extract_user_info(self, keycloak_data): email = keycloak_data['email'] if 'email' in keycloak_data else None if email is None: self.logger.info("No email provided by the keycloak server") user_roles = keycloak_data['roles'] if 'roles' in keycloak_data else [] client_id = AuthorizationManager().get_keycloak_instance().client_id user_client_roles = user_roles[ client_id] if client_id in user_roles else [] if len(user_roles) == 0: self.logger.info("No client roles for client {}".format(client_id)) role = ROLE_ADMINISTRATOR if ROLE_ADMINISTRATOR in user_client_roles else None username = keycloak_data[ 'preferred_username'] if 'preferred_username' in keycloak_data else keycloak_data[ 'sub'] name = keycloak_data[ 'name'] if 'name' in keycloak_data else keycloak_data['sub'] return username, name, email, role
def deco(*a, **b): authorization = request.headers[Strings.AUTH_HEADER.value] if Strings.AUTH_HEADER.value in request.headers \ else None if not authorization: raise AuthorizationRequestException() token = authorization.replace(Strings.BEARER.value, "") try: # Load user details kc_user_info = AuthorizationManager.get_keycloak_instance().userinfo(token) db_user = UserService().get_external_db_user(kc_user_info) set_current_user(db_user) except KeycloakError as kc_error: try: error_message = json.loads(kc_error.error_message.decode())['error_description'] except (KeyError, TypeError): error_message = kc_error.error_message.decode() raise AuthorizationRequestException(message=error_message, code=kc_error.response_code) return func(*a, **b)
def initialize_flask(): # creating the flask app app = Flask(__name__) app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1) app.json_encoder = CustomFlaskEncoder # creating an API object api = RestApi(app, title="Rest services for TVB", doc="/doc/") # Users namespace name_space_users = api.namespace( build_path(RestNamespace.USERS), description="TVB-REST APIs for users management") name_space_users.add_resource(GetUsersResource, "/") name_space_users.add_resource(LoginUserResource, RestLink.LOGIN.compute_url()) name_space_users.add_resource(GetProjectsListResource, RestLink.PROJECTS.compute_url()) name_space_users.add_resource(LinksResource, RestLink.USEFUL_URLS.compute_url()) # Projects namespace name_space_projects = api.namespace( build_path(RestNamespace.PROJECTS), description="TVB-REST APIs for projects management") name_space_projects.add_resource( GetDataInProjectResource, RestLink.DATA_IN_PROJECT.compute_url( values={LinkPlaceholder.PROJECT_GID.value: "<string:project_gid>" })) name_space_projects.add_resource( GetOperationsInProjectResource, RestLink.OPERATIONS_IN_PROJECT.compute_url( values={LinkPlaceholder.PROJECT_GID.value: "<string:project_gid>" })) name_space_projects.add_resource( ProjectMembersResource, RestLink.PROJECT_MEMBERS.compute_url( values={LinkPlaceholder.PROJECT_GID.value: "<string:project_gid>" })) # Datatypes namepsace name_space_datatypes = api.namespace( build_path(RestNamespace.DATATYPES), description="TVB-REST APIs for datatypes management") name_space_datatypes.add_resource( RetrieveDatatypeResource, RestLink.GET_DATATYPE.compute_url( values={ LinkPlaceholder.DATATYPE_GID.value: '<string:datatype_gid>' })) name_space_datatypes.add_resource( GetOperationsForDatatypeResource, RestLink.DATATYPE_OPERATIONS.compute_url( values={ LinkPlaceholder.DATATYPE_GID.value: '<string:datatype_gid>' })) # Operations namespace name_space_operations = api.namespace( build_path(RestNamespace.OPERATIONS), description="TVB-REST APIs for operations management") name_space_operations.add_resource( LaunchOperationResource, RestLink.LAUNCH_OPERATION.compute_url( values={ LinkPlaceholder.PROJECT_GID.value: '<string:project_gid>', LinkPlaceholder.ALG_MODULE.value: '<string:algorithm_module>', LinkPlaceholder.ALG_CLASSNAME.value: '<string:algorithm_classname>' })) name_space_operations.add_resource( GetOperationStatusResource, RestLink.OPERATION_STATUS.compute_url( values={ LinkPlaceholder.OPERATION_GID.value: '<string:operation_gid>' })) name_space_operations.add_resource( GetOperationResultsResource, RestLink.OPERATION_RESULTS.compute_url( values={ LinkPlaceholder.OPERATION_GID.value: '<string:operation_gid>' })) # Simulation namespace name_space_simulation = api.namespace( build_path(RestNamespace.SIMULATION), description="TVB-REST APIs for simulation management") name_space_simulation.add_resource( FireSimulationResource, RestLink.FIRE_SIMULATION.compute_url( values={LinkPlaceholder.PROJECT_GID.value: '<string:project_gid>' })) api.add_namespace(name_space_users) api.add_namespace(name_space_projects) api.add_namespace(name_space_datatypes) api.add_namespace(name_space_operations) api.add_namespace(name_space_simulation) # Register keycloak authorization manager AuthorizationManager(TvbProfile.current.KEYCLOAK_CONFIG) http_server = WSGIServer(("0.0.0.0", FLASK_PORT), app) http_server.serve_forever()