class UserUpdateController(Resource):
    def __init__(self, *args, **kwargs):
        self.user_service = UserService()

    def get(self, id):
        users = self.user_service.retrieve(id)
        if not users:
            return {'data': [], 'message': 'No se encontró el usuario'}, 404
        return {'data': users, 'message': 'success'}, 200

    def put(self, id):
        body = request.get_json()

        data = self.user_service.modify(id, **body)
        if not data:
            return {
                'message':
                'Ocurrio un error al modificar el usuario/Usuario no encontrado'
            }, 404
        return {'data': data, 'message': 'Success'}, 200

    def delete(self, id):
        data = self.user_service.delete(id)
        if not data:
            return {
                'message':
                'Ocurrio un error al eliminar el usuario/Usuario no encontrado'
            }, 404
        return {'data': data, 'message': 'Success'}, 200
예제 #2
0
def login_route():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')

        if not UserService.authenticate(username, password):
            flash('Invalid user key or password. Please try again.', 'danger')
            current_app.logger.warn(
                "Invalid credentials attempted for username '{0}'.".format(
                    username))

            return redirect(url_for('auth.login_route'))

        # Find or create user
        user = UserService.find_by(username=username, fetch_one=True)
        if user:
            UserService.update(user.id, authenticated=True)
        else:
            user = UserService.create(username=username, authenticated=True)

        # Log in user in Flask
        login_user(user)

        # Go to next page if defined
        next_page = session.pop('next') or request.args.get('next')
        if next_page:
            return redirect(next_page)

        return redirect(url_for('auth.login_route'))
    else:
        if current_user.is_authenticated:
            return redirect(url_for('user.me_route'))
        else:
            return render_template('pages/auth/authenticate.html')
예제 #3
0
    def get(self):
        id = request.values.get('id', None)
        email = request.values.get('email', None)

        if email:
            response = UserService().get_user_by_email(email)
        else:
            response = UserService().get_user(id)
        return response, HTTPStatus.OK
예제 #4
0
def register():
    body = validate(
        {
            'email': field('email'),
            'password': field('password'),
            'repeat_password': field('password'),
            'tos': field('tos')
        }, request.get_json(force=True, silent=True))

    UserService.add_user(body)

    return 'Hi'
예제 #5
0
    def facebook_login(self, facebook_access_token):
        # facebook login by using facebook access token, return user_name, user_id and boolean variable indicate if this user is new user
        try:
            # validate access_token
            facebook_app_id = get_system_config()["facebook_app"]
            verify_token_app_id = "https://graph.facebook.com/debug_token?input_token={}&access_token={}|{}".format(
                facebook_access_token, facebook_app_id["app_id"],
                facebook_app_id["app_secret"])
            req = requests.get(url=verify_token_app_id)
            if req.status_code != 200:
                raise Exception(Message.FACEBOOK_ACCESS_TOKEN_INVALID)
            facebook_token_app_id_info = req.json()
            facebook_token_app_id = facebook_token_app_id_info["data"][
                "app_id"]
            if facebook_token_app_id != facebook_app_id["app_id"]:
                raise Exception(Message.FACEBOOK_ACCESS_TOKEN_INVALID)

            verify_token_url = "https://graph.facebook.com/me?fields=id,name,email&access_token=" + facebook_access_token
            req = requests.get(url=verify_token_url)

            if req.status_code != 200:
                raise Exception(Message.FACEBOOK_ACCESS_TOKEN_INVALID)
            facebook_token_info = req.json()

            logger.info("Facebook login token spec:")
            logger.info(facebook_token_info)

            facebook_id = facebook_token_info["id"]
            facebook_email = facebook_token_info["email"]
            facebook_name = facebook_token_info["name"]
            # check account exits
            user = self.get_user_by_email(facebook_id)
            if user:
                user_info = UserService().get_user_by_id(user["id"])
                return facebook_id, user[
                    "id"], user_info.password_verifier is None or user_info.password_verifier == ""
            else:
                # create new user
                new_user_id = KeyCloakUtils.create_user_without_password(
                    facebook_email, facebook_id, "", facebook_name)
                new_user = UserService().create_user_social(
                    id=new_user_id,
                    email=facebook_email,
                    display_name=facebook_name,
                    auth_source='facebook')
                if new_user is None:
                    self.delete_user(new_user_id)
                    raise Exception(Message.REGISTER_USER_FAILED)
                return facebook_id, new_user_id, True
        except Exception as e:
            logger.info(e)
            raise Exception(Message.FACEBOOK_AUTH_FAILED)
예제 #6
0
    async def register_srp(self, request, context):
        # check exist user
        try:
            email = request.email
            display_name = request.display_name
            password_verifier = request.password_verifier
            salt = request.salt
            iv_parameter = request.iv_parameter

            exists_user = self.service.get_user_by_email(email)
            if exists_user:
                raise Exception(Message.REGISTER_USER_ALREADY_EXISTS)

            # register new user
            new_user_id = self.service.register_srp_user(
                email, password_verifier, display_name)

            if new_user_id:
                # create new user in database
                UserService().create_new_user_srp(new_user_id, email,
                                                  password_verifier, salt,
                                                  iv_parameter, display_name,
                                                  'account')
            else:
                self.service.delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)
            try:
                SignalService().peer_register_client_key(
                    new_user_id, request.client_key_peer)
            except Exception:
                self.service.delete_user(new_user_id)
                UserService().delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)

            return auth_messages.RegisterSRPRes()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.REGISTER_USER_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)
예제 #7
0
    def office_login(self, office_access_token):
        # office login by using office access token, return user_name, user_id and boolean variable indicate if this user is new user
        try:
            verify_token_url = "https://graph.microsoft.com/v1.0/me"
            bearer = 'Bearer ' + office_access_token
            headers = {'Authorization': bearer}

            req = requests.get(url=verify_token_url, headers=headers)
            if req.status_code != 200:
                raise Exception(Message.OFFICE_ACCESS_TOKEN_INVALID)
            office_token_info = req.json()

            logger.info("Office login token spec:")
            logger.info(office_token_info)

            office_id = office_token_info["id"]
            # check account exits
            user = self.get_user_by_email(office_id)
            if user:
                user_info = UserService().get_user_by_id(user["id"])
                return office_id, user[
                    "id"], user_info.password_verifier is None or user_info.password_verifier == ""
            else:
                display_name = office_token_info["displayName"]
                email = ""
                if not display_name:
                    if office_token_info["userPrincipalName"]:
                        user_principal_name = office_token_info[
                            "userPrincipalName"].split("@")
                        if len(user_principal_name) > 0:
                            display_name = user_principal_name[0]
                            email = office_token_info["userPrincipalName"]
                # create new user
                new_user_id = KeyCloakUtils.create_user_without_password(
                    email, office_id, "", display_name)
                new_user = UserService().create_user_social(
                    id=new_user_id,
                    email=office_token_info["mail"],
                    display_name=display_name,
                    auth_source='office')
                if new_user is None:
                    self.delete_user(new_user_id)
                    raise Exception(Message.REGISTER_USER_FAILED)
                return office_id, new_user_id, True
        except Exception as e:
            logger.info(e)
            raise Exception(Message.OFFICE_AUTH_FAILED)
class UserController(Resource):
    def __init__(self, *args, **kwargs):
        self.user_service = UserService()

    def get(self):
        users = self.user_service.fetch()
        if not users:
            return {'data': [], 'message': 'No se encontraron usuarios'}, 404
        return {'data': users, 'message': 'success'}, 200

    def post(self):
        body = request.get_json()

        data = self.user_service.create(**body)
        if not data:
            return {'message': 'Ocurrio un error al insertar'}, 404
        return {'data': data, 'message': 'Success'}, 200
예제 #9
0
    def google_login(self, google_id_token):
        # google login by using google id token, return user_name, user_id and boolean variable indicate if this user is new user
        try:
            verify_id_token_url = "https://oauth2.googleapis.com/tokeninfo?id_token=" + google_id_token
            req = requests.get(url=verify_id_token_url)
            if req.status_code != 200:
                raise Exception(Message.GOOGLE_AUTH_ID_TOKEN_INVALID)
            google_token_info = req.json()

            logger.info("Google login token spec:")
            logger.info(google_token_info)

            # check google_token_info["aud"] matching with google app id
            google_app_id = get_system_config()["google_app_id"]
            if google_token_info["aud"] != google_app_id[
                    "ios"] and google_token_info["aud"] != google_app_id[
                        "android"]:
                raise Exception(Message.GOOGLE_AUTH_FAILED)

            google_email = google_token_info["email"]
            # check account exits
            user = self.get_user_by_email(email=google_email)
            #active_user
            if user:
                if not user["emailVerified"]:
                    KeyCloakUtils.active_user(user["id"])
                user_info = UserService().get_user_by_id(user["id"])
                return google_email, user[
                    "id"], user_info.password_verifier is None or user_info.password_verifier == ""
            else:
                # create new user
                new_user_id = KeyCloakUtils.create_user_without_password(
                    google_email, google_email, "", google_token_info["name"])
                new_user = UserService().create_user_social(
                    id=new_user_id,
                    email=google_email,
                    display_name=google_token_info["name"],
                    auth_source='google')
                if new_user is None:
                    self.delete_user(new_user_id)
                    raise Exception(Message.REGISTER_USER_FAILED)
                return google_email, new_user_id, True
        except Exception as e:
            logger.info(e)
            raise Exception(Message.GOOGLE_AUTH_FAILED)
예제 #10
0
 def get(self):
     """
     Get the dummy client for testing purposes.
     """
     client = OAuth2ClientService.find_by(
         resource_owner_id=UserService.find_by(username='******',
                                               fetch_one=True).id,
         fetch_one=True)
     return client.client_info
예제 #11
0
    def reset_user_words(user_telegram_id):
        """
        Change all user word status to unused

        :param user_telegram_id:
        :return:
        """
        user = UserService.filter(telegram_id=user_telegram_id)
        if user:
            user = user[0]
        else:
            return None

        user_words = UserWordService.filter(user_id=user.id)

        for word in user_words:
            UserWordService.update(user_word_id=word.id, status=True)

        return True
예제 #12
0
    def add_user_word(user_telegram_id, word):
        """
        add word to user word list

        :param user_telegram_id:
        :param word:
        :return:
        """

        user = UserService.filter(telegram_id=user_telegram_id)

        if not user:  # if no such word
            return None

        user = user[0]

        # if user already has this word
        if user_word := UserWordService.filter(user_id=user.id,
                                               word_id=word.id):
            return user_word[0]
예제 #13
0
    def get_user_word(user_telegram_id):
        """
        Return one of user`s unseen word

        :param user_telegram_id:
        :return:
        """
        user = UserService.filter(telegram_id=user_telegram_id)

        if not user:
            return None

        user = user[0]

        user_word = UserWordService.pick_random_word(user.id)

        if not user_word:
            return None

        UserWordService.update(user_word.id, status=False)  # mark word as used
        word = WordService.get_by_id(user_word.word_id)

        return word
예제 #14
0
 def authenticate_user(self, credential):
     return UserService.get(credential.resource_owner.id)
예제 #15
0
 def authenticate_user(self, username, password):
     user = UserService.find_by(username=username, fetch_one=True)
     if user and UserService.authenticate(username, password):
         return user
예제 #16
0
 def authenticate_user(self, authorization_code):
     return UserService.get(authorization_code.resource_owner.id)
예제 #17
0
 def post(self):
     payload = request.json
     saved_id = UserService().save(payload)
     return {"id": saved_id}, HTTPStatus.OK
예제 #18
0
 async def register_pincode(self, request, context):
     try:
         exists_user = self.service.get_user_by_email(request.user_name)
         if not exists_user:
             raise Exception(Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
         user_info = self.user_service.get_user_by_id(exists_user["id"])
         if user_info.password_verifier is not None:
             raise Exception(Message.REGISTER_USER_ALREADY_EXISTS)
         salt = request.salt
         self.user_service.change_password(request, None,
                                           request.hash_pincode,
                                           exists_user['id'])
         # using hash_pincode as password for social user
         try:
             SignalService().peer_register_client_key(
                 exists_user['id'], request.client_key_peer)
         except Exception as e:
             logger.error(e)
         try:
             UserService().update_hash_pin(exists_user['id'],
                                           request.hash_pincode,
                                           request.salt,
                                           request.iv_parameter)
         except Exception as e:
             logger.error(e)
             ## TODO: revert change_password
             SignalService().delete_client_peer_key(exists_user['id'])
             raise Message.get_error_object(
                 Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
         require_action = ""
         client_key_obj = request.client_key_peer
         client_key_peer = auth_messages.PeerGetClientKeyResponse(
             clientId=exists_user['id'],
             workspace_domain=get_owner_workspace_domain(),
             registrationId=client_key_obj.registrationId,
             deviceId=client_key_obj.deviceId,
             identityKeyPublic=client_key_obj.identityKeyPublic,
             preKeyId=client_key_obj.preKeyId,
             preKey=client_key_obj.preKey,
             signedPreKeyId=client_key_obj.signedPreKeyId,
             signedPreKey=client_key_obj.signedPreKey,
             signedPreKeySignature=client_key_obj.signedPreKeySignature,
             identityKeyEncrypted=client_key_obj.identityKeyEncrypted)
         token = self.service.token(request.user_name, request.hash_pincode)
         introspect_token = KeyCloakUtils.introspect_token(
             token['access_token'])
         self.user_service.update_last_login(
             user_id=introspect_token['sub'])
         return auth_messages.AuthRes(
             workspace_domain=get_owner_workspace_domain(),
             workspace_name=get_system_config()['server_name'],
             access_token=token["access_token"],
             expires_in=token['expires_in'],
             refresh_expires_in=token['refresh_expires_in'],
             refresh_token=token['refresh_token'],
             token_type=token['token_type'],
             session_state=token['session_state'],
             scope=token['scope'],
             salt=request.salt,
             client_key_peer=client_key_peer,
             iv_parameter=request.iv_parameter)
     except Exception as e:
         logger.error(e)
         if not e.args or e.args[0] not in Message.msg_dict:
             errors = [
                 Message.get_error_object(
                     Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
             ]
         else:
             errors = [Message.get_error_object(e.args[0])]
         context.set_details(
             json.dumps(errors, default=lambda x: x.__dict__))
         context.set_code(grpc.StatusCode.INTERNAL)
예제 #19
0
def load_user(user_id):
    return UserService.get(user_id)
예제 #20
0
 async def reset_pincode(self, request, context):
     try:
         success_status = self.service.verify_hash_pre_access_token(
             request.user_name, request.reset_pincode_token,
             "verify_pincode")
         exists_user = self.service.get_user_by_email(request.user_name)
         if not exists_user:
             raise Exception(Message.USER_NOT_FOUND)
         if not success_status:
             raise Exception(Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
         self.user_service.change_password(request, None,
                                           request.hash_pincode,
                                           exists_user["id"])
         old_client_key_peer = SignalService().peer_get_client_key(
             exists_user["id"])
         SignalService().client_update_peer_key(exists_user["id"],
                                                request.client_key_peer)
         try:
             salt, iv_parameter = UserService().update_hash_pin(
                 exists_user["id"], request.hash_pincode, request.salt,
                 request.iv_parameter)
         except Exception as e:
             logger.error(e)
             SignalService().client_update_peer_key(exists_user["id"],
                                                    old_client_key_peer)
             raise Message.get_error_object(
                 Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
         client_key_obj = request.client_key_peer
         client_key_peer = auth_messages.PeerGetClientKeyResponse(
             clientId=exists_user["id"],
             workspace_domain=get_owner_workspace_domain(),
             registrationId=client_key_obj.registrationId,
             deviceId=client_key_obj.deviceId,
             identityKeyPublic=client_key_obj.identityKeyPublic,
             preKeyId=client_key_obj.preKeyId,
             preKey=client_key_obj.preKey,
             signedPreKeyId=client_key_obj.signedPreKeyId,
             signedPreKey=client_key_obj.signedPreKey,
             signedPreKeySignature=client_key_obj.signedPreKeySignature,
             identityKeyEncrypted=client_key_obj.identityKeyEncrypted)
         # logout all device before get new token for user after updated new key
         user_sessions = KeyCloakUtils.get_sessions(
             user_id=exists_user["id"])
         for user_session in user_sessions:
             KeyCloakUtils.remove_session(session_id=user_session['id'])
         token = self.service.token(request.user_name, request.hash_pincode)
         introspect_token = KeyCloakUtils.introspect_token(
             token['access_token'])
         return auth_messages.AuthRes(
             workspace_domain=get_owner_workspace_domain(),
             workspace_name=get_system_config()['server_name'],
             access_token=token["access_token"],
             expires_in=token['expires_in'],
             refresh_expires_in=token['refresh_expires_in'],
             refresh_token=token['refresh_token'],
             token_type=token['token_type'],
             session_state=token['session_state'],
             scope=token['scope'],
             salt=salt,
             client_key_peer=client_key_peer,
             iv_parameter=iv_parameter)
     except Exception as e:
         logger.error(e)
         if not e.args or e.args[0] not in Message.msg_dict:
             errors = [
                 Message.get_error_object(
                     Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
             ]
         else:
             errors = [Message.get_error_object(e.args[0])]
             context.set_details(
                 json.dumps(errors, default=lambda x: x.__dict__))
             context.set_code(grpc.StatusCode.INTERNAL)
예제 #21
0
 def __init__(self, *args, **kwargs):
     self.user_service = UserService()
예제 #22
0
class UserController(BaseController, user_pb2_grpc.UserServicer):
    def __init__(self, *kwargs):
        self.service = UserService()

    @auth_required
    async def request_change_password(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            user_name = introspect_token['preferred_username']
            user_info = self.service.get_user_by_auth_source(
                user_name, "account")
            if not user_info:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_public = bytes.fromhex(request.client_public)

            srv = srp.Verifier(user_name, salt, password_verifier,
                               client_public)
            s, B = srv.get_challenge()
            # need store private b of server

            server_private = srv.get_ephemeral_secret().hex()
            user_info.srp_server_private = server_private
            user_info.update()

            public_challenge_b = B.hex()
            auth_challenge_res = user_messages.RequestChangePasswordRes(
                salt=user_info.salt, public_challenge_b=public_challenge_b)
            return auth_challenge_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.CHANGE_PASSWORD_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @auth_required
    async def change_password(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            user_name = introspect_token['preferred_username']
            client_session_key_proof = request.client_session_key_proof
            user_info = self.service.get_user_by_auth_source(
                user_name, "account")

            if not user_info:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_session_key_proof_bytes = bytes.fromhex(
                client_session_key_proof)

            srv = srp.Verifier(username=user_name,
                               bytes_s=salt,
                               bytes_v=password_verifier,
                               bytes_A=bytes.fromhex(request.client_public),
                               bytes_b=bytes.fromhex(
                                   user_info.srp_server_private))
            srv.verify_session(client_session_key_proof_bytes)
            authenticated = srv.authenticated()
            if not authenticated:
                raise Exception(Message.AUTHENTICATION_FAILED)

            self.service.change_password(
                request, user_info.password_verifier, request.hash_password,
                introspect_token['sub'])  # update for keycloak

            try:
                old_identity_key_encrypted = SignalService(
                ).client_update_identity_key(introspect_token["sub"],
                                             request.identity_key_encrypted)
            except Exception as e:
                logger.error(e)
                self.service.change_password(request, request.hash_password,
                                             user_info.password_verifier,
                                             introspect_token['sub'])
                raise Exception(Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
            try:
                salt, iv_parameter = self.service.update_hash_pass(
                    introspect_token["sub"], request.hash_password,
                    request.salt, request.iv_parameter)
            except Exception as e:
                logger.error(e)
                self.service.change_password(request, request.hash_password,
                                             request.password_verifier,
                                             introspect_token['sub'])
                SignalService().client_update_identity_key(
                    introspect_token["sub"], old_identity_key_encrypted)
                raise Exception(Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
            user_sessions = KeyCloakUtils.get_sessions(
                user_id=introspect_token["sub"])
            for user_session in user_sessions:
                if user_session['id'] != introspect_token['session_state']:
                    KeyCloakUtils.remove_session(session_id=user_session['id'])
            return user_messages.BaseResponse()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.CHANGE_PASSWORD_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @auth_required
    async def get_mfa_state(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            mfa_enable = self.service.get_mfa_state(client_id)
            return user_messages.MfaStateResponse(mfa_enable=mfa_enable, )

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_MFA_STATE_FALED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @auth_required
    async def disable_mfa(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            if not introspect_token or 'sub' not in introspect_token:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            client_id = introspect_token['sub']
            success, next_step = self.service.init_mfa_state_disabling(
                client_id)
            return user_messages.MfaBaseResponse(success=success,
                                                 next_step=next_step)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_MFA_STATE_FALED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    @auth_required
    async def enable_mfa(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            user_info = self.service.get_user_by_id(client_id)

            if user_info.phone_number is None:
                success = False
                next_step = 'mfa_update_phone_number'
            else:
                success, next_step = self.service.init_mfa_state_enabling(
                    client_id)
            return user_messages.MfaBaseResponse(success=success,
                                                 next_step=next_step)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_MFA_STATE_FALED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    @auth_required
    async def mfa_auth_challenge(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            email = introspect_token['preferred_username']

            self.service.mfa_validate_password_flow(client_id)
            user_info = self.service.get_user_by_id(client_id)
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_public = bytes.fromhex(request.client_public)

            srv = srp.Verifier(email, salt, password_verifier, client_public)
            s, B = srv.get_challenge()

            server_private = srv.get_ephemeral_secret().hex()
            user_info.srp_server_private = server_private
            user_info.update()

            public_challenge_b = B.hex()

            auth_challenge_res = user_messages.MfaAuthChallengeResponse(
                salt=user_info.salt, public_challenge_b=public_challenge_b)
            return auth_challenge_res
        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_MFA_STATE_FALED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    @auth_required
    async def mfa_validate_password(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            user_info = self.service.get_user_by_id(client_id)

            client_session_key_proof = request.client_session_key_proof
            user_name = introspect_token['preferred_username']
            phone_number = user_info.phone_number
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_session_key_proof_bytes = bytes.fromhex(
                client_session_key_proof)

            srv = srp.Verifier(username=user_name,
                               bytes_s=salt,
                               bytes_v=password_verifier,
                               bytes_A=bytes.fromhex(request.client_public),
                               bytes_b=bytes.fromhex(
                                   user_info.srp_server_private))
            srv.verify_session(client_session_key_proof_bytes)
            authenticated = srv.authenticated()

            if not authenticated:
                raise Exception(Message.AUTHENTICATION_FAILED)
            success, next_step = self.service.mfa_request_otp(
                client_id, phone_number)
            return user_messages.MfaBaseResponse(success=success,
                                                 next_step=next_step)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.OTP_SERVER_NOT_RESPONDING)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @auth_required
    async def mfa_validate_otp(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            success, next_step = self.service.validate_otp(
                client_id, request.otp)
            return user_messages.MfaBaseResponse(success=success,
                                                 next_step=next_step)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_MFA_STATE_FALED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @auth_required
    async def mfa_resend_otp(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            success, next_step = self.service.re_init_otp(client_id)
            return user_messages.MfaBaseResponse(success=success,
                                                 next_step=next_step)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.OTP_SERVER_NOT_RESPONDING)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    @auth_required
    async def get_profile(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']

            user_info = self.service.get_profile(client_id)
            if user_info is not None:
                return user_info
            else:
                errors = [Message.get_error_object(Message.USER_NOT_FOUND)]
                context.set_details(
                    json.dumps(errors, default=lambda x: x.__dict__))
                context.set_code(grpc.StatusCode.NOT_FOUND)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [Message.get_error_object(Message.GET_PROFILE_FAILED)]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @auth_required
    async def update_profile(self, request, context):
        logger.info("user update_profile api")
        try:
            display_name = request.display_name
            avatar = request.avatar
            phone_number = request.phone_number
            clear_phone_number = request.clear_phone_number

            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']

            self.service.update_profile(client_id, display_name, phone_number,
                                        avatar, clear_phone_number)
            return user_messages.BaseResponse()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.UPDATE_PROFILE_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    # @auth_required
    # @request_logged
    async def get_user_info(self, request, context):
        try:
            client_id = request.client_id
            client_workspace_domain = request.workspace_domain
            owner_workspace_domain = get_owner_workspace_domain()

            if client_workspace_domain == owner_workspace_domain:
                user_info = self.service.get_user_info(client_id,
                                                       owner_workspace_domain)
            else:
                client = ClientUser(client_workspace_domain)
                user_info = client.get_user_info(
                    client_id=client_id,
                    workspace_domain=client_workspace_domain)

            if user_info is not None:
                return user_info
            else:
                errors = [Message.get_error_object(Message.USER_NOT_FOUND)]
                context.set_details(
                    json.dumps(errors, default=lambda x: x.__dict__))
                context.set_code(grpc.StatusCode.NOT_FOUND)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_USER_INFO_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    @auth_required
    async def search_user(self, request, context):
        logger.info("user search_user api")
        try:
            keyword = request.keyword
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']

            obj_res = self.service.search_user(keyword, client_id)
            return obj_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [Message.get_error_object(Message.SEARCH_USER_FAILED)]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    @auth_required
    async def get_users(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            owner_workspace_domain = get_owner_workspace_domain()
            obj_res = self.service.get_users(client_id, owner_workspace_domain)
            return obj_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [Message.get_error_object(Message.SEARCH_USER_FAILED)]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    @auth_required
    async def get_user_domain(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            domain = "server.domain2"
            obj_res = self.service.get_users_domain(domain=domain)
            return obj_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [Message.get_error_object(Message.SEARCH_USER_FAILED)]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    # update status for user ("Active, Busy, Away, Do not disturb")
    @request_logged
    @auth_required
    async def update_status(self, request, context):
        logger.info("user update_status api")
        try:
            status = request.status
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']

            self.service.set_user_status(client_id, status)
            return user_messages.BaseResponse()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.UPDATE_USER_STATUS_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def ping_request(self, request, context):
        logger.info("ping_request api")
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            self.service.update_client_record(client_id)
            return user_messages.BaseResponse()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.PING_PONG_SERVER_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def get_clients_status(self, request, context):
        logger.info("get_client_status api")
        try:
            list_clients = request.lst_client
            should_get_profile = request.should_get_profile
            list_user_status = self.service.get_list_clients_status(
                list_clients, should_get_profile)
            return list_user_status

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_USER_STATUS_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def upload_avatar(self, request, context):
        logger.info("upload_avatar api")
        try:
            file_name = request.file_name
            file_content = request.file_data
            file_content_type = request.file_content_type
            file_hash = request.file_hash
            # client_id from headers
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            client_id = introspect_token['sub']
            obj_res = self.service.upload_avatar(client_id, file_name,
                                                 file_content,
                                                 file_content_type, file_hash)
            return obj_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_USER_STATUS_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)
예제 #23
0
 def __init__(self, *kwargs):
     self.service = AuthService()
     self.user_service = UserService()
예제 #24
0
    async def forgot_password_update(self, request, context):
        try:
            logger.info("from email {}".format(request.email))
            user_info = self.user_service.get_user_by_auth_source(
                request.email, "account")
            old_user_id = user_info.id
            self.service.verify_hash_pre_access_token(old_user_id,
                                                      request.pre_access_token,
                                                      "forgot_password")
            new_user_id = self.service.forgot_user(request.email,
                                                   request.password_verifier,
                                                   user_info.display_name)
            try:
                await GroupService().forgot_peer_groups_for_client(user_info)
            except Exception as e:
                logger.error("cannot send notify to other group")
                logger.error(e)
            SignalService().delete_client_peer_key(old_user_id)
            if new_user_id:
                # create new user in database
                UserService().forgot_user(user_info, new_user_id,
                                          request.password_verifier,
                                          request.salt, request.iv_parameter)
            else:
                self.service.delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)
            try:
                SignalService().peer_register_client_key(
                    new_user_id, request.client_key_peer)
            except Exception:
                self.service.delete_user(new_user_id)
                UserService().delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)

            token = self.service.token(request.email,
                                       request.password_verifier)
            if token:
                client_key_obj = request.client_key_peer
                client_key_peer = auth_messages.PeerGetClientKeyResponse(
                    clientId=new_user_id,
                    workspace_domain=get_owner_workspace_domain(),
                    registrationId=client_key_obj.registrationId,
                    deviceId=client_key_obj.deviceId,
                    identityKeyPublic=client_key_obj.identityKeyPublic,
                    preKeyId=client_key_obj.preKeyId,
                    preKey=client_key_obj.preKey,
                    signedPreKeyId=client_key_obj.signedPreKeyId,
                    signedPreKey=client_key_obj.signedPreKey,
                    signedPreKeySignature=client_key_obj.signedPreKeySignature,
                    identityKeyEncrypted=client_key_obj.identityKeyEncrypted)
                self.user_service.update_last_login(user_id=new_user_id)
                auth_message = auth_messages.AuthRes(
                    workspace_domain=get_owner_workspace_domain(),
                    workspace_name=get_system_config()['server_name'],
                    access_token=token['access_token'],
                    expires_in=token['expires_in'],
                    refresh_expires_in=token['refresh_expires_in'],
                    refresh_token=token['refresh_token'],
                    token_type=token['token_type'],
                    session_state=token['session_state'],
                    scope=token['scope'],
                    salt=request.salt,
                    client_key_peer=client_key_peer,
                    iv_parameter=request.iv_parameter)
            else:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            return auth_message

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.CHANGE_PASSWORD_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)
예제 #25
0
 def __init__(self, *kwargs):
     self.service = UserService()
예제 #26
0
class AuthController(BaseController):
    def __init__(self, *kwargs):
        self.service = AuthService()
        self.user_service = UserService()

    @request_logged
    async def login_challenge(self, request, context):
        try:
            email = request.email
            user_info = self.user_service.get_user_by_auth_source(
                email, "account")
            if not user_info:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_public = bytes.fromhex(request.client_public)

            srv = srp.Verifier(email, salt, password_verifier, client_public)
            s, B = srv.get_challenge()

            server_private = srv.get_ephemeral_secret().hex()
            logger.info(server_private)
            user_info.srp_server_private = server_private
            user_info.update()

            public_challenge_b = B.hex()
            auth_challenge_res = auth_messages.AuthChallengeRes(
                salt=user_info.salt, public_challenge_b=public_challenge_b)
            return auth_challenge_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTHENTICATION_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def login_authenticate(self, request, context):
        try:
            user_name = request.user_name
            exists_user = self.service.get_user_by_email(user_name)
            client_session_key_proof = request.client_session_key_proof
            user_info = self.user_service.get_user_by_id(exists_user["id"])

            if not user_info:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_session_key_proof_bytes = bytes.fromhex(
                client_session_key_proof)

            srv = srp.Verifier(username=user_name,
                               bytes_s=salt,
                               bytes_v=password_verifier,
                               bytes_A=bytes.fromhex(request.client_public),
                               bytes_b=bytes.fromhex(
                                   user_info.srp_server_private))
            srv.verify_session(client_session_key_proof_bytes)
            authenticated = srv.authenticated()

            if not authenticated:
                raise Exception(Message.AUTHENTICATION_FAILED)

            token = self.service.token(user_name, user_info.password_verifier)
            if token:
                user_id = user_info.id
                mfa_state = self.user_service.get_mfa_state(user_id=user_id)

                if not mfa_state:
                    client_key_obj = SignalService().peer_get_client_key(
                        user_id)
                    client_key_peer = auth_messages.PeerGetClientKeyResponse(
                        clientId=user_id,
                        workspace_domain=get_owner_workspace_domain(),
                        registrationId=client_key_obj.registration_id,
                        deviceId=client_key_obj.device_id,
                        identityKeyPublic=client_key_obj.identity_key_public,
                        preKeyId=client_key_obj.prekey_id,
                        preKey=client_key_obj.prekey,
                        signedPreKeyId=client_key_obj.signed_prekey_id,
                        signedPreKey=client_key_obj.signed_prekey,
                        signedPreKeySignature=client_key_obj.
                        signed_prekey_signature,
                        identityKeyEncrypted=client_key_obj.
                        identity_key_encrypted)
                    self.user_service.update_last_login(user_id=user_id)
                    auth_message = auth_messages.AuthRes(
                        workspace_domain=get_owner_workspace_domain(),
                        workspace_name=get_system_config()['server_name'],
                        access_token=token['access_token'],
                        expires_in=token['expires_in'],
                        refresh_expires_in=token['refresh_expires_in'],
                        refresh_token=token['refresh_token'],
                        token_type=token['token_type'],
                        session_state=token['session_state'],
                        scope=token['scope'],
                        salt=user_info.salt,
                        client_key_peer=client_key_peer,
                        iv_parameter=user_info.iv_parameter)
                else:
                    pre_access_token = self.service.create_otp_service(user_id)
                    auth_message = auth_messages.AuthRes(
                        workspace_domain=get_owner_workspace_domain(),
                        workspace_name=get_system_config()['server_name'],
                        sub=user_id,
                        pre_access_token=pre_access_token,
                        require_action="mfa_validate_otp")
                return auth_message
        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTH_USER_NOT_FOUND)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def login_google(self, request, context):
        try:
            user_name, user_id, is_registered_pincode = self.service.google_login(
                request.id_token)
            user_info = self.user_service.get_user_by_id(user_id)
            require_action_mess = "verify_pincode" if not is_registered_pincode else "register_pincode"
            if require_action_mess == "verify_pincode":
                reset_pincode_token = self.service.hash_pre_access_token(
                    user_name, "reset_pincode")
            else:
                reset_pincode_token = ""
            auth_challenge_res = auth_messages.SocialLoginRes(
                user_name=user_name,
                require_action=require_action_mess,
                reset_pincode_token=reset_pincode_token)
            return auth_challenge_res
        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTH_USER_NOT_FOUND)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def login_office(self, request, context):
        try:
            user_name, user_id, is_registered_pincode = self.service.office_login(
                request.access_token)
            user_info = self.user_service.get_user_by_id(user_id)
            require_action_mess = "verify_pincode" if not is_registered_pincode else "register_pincode"
            if require_action_mess == "verify_pincode":
                reset_pincode_token = self.service.hash_pre_access_token(
                    user_name, "reset_pincode")
            else:
                reset_pincode_token = ""
            auth_challenge_res = auth_messages.SocialLoginRes(
                user_name=user_name,
                require_action=require_action_mess,
                reset_pincode_token=reset_pincode_token)
            return auth_challenge_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTH_USER_NOT_FOUND)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def login_facebook(self, request, context):
        try:
            user_name, user_id, is_registered_pincode = self.service.facebook_login(
                request.access_token)
            user_info = self.user_service.get_user_by_id(user_id)
            require_action_mess = "verify_pincode" if not is_registered_pincode else "register_pincode"
            if require_action_mess == "verify_pincode":
                reset_pincode_token = self.service.hash_pre_access_token(
                    user_name, "reset_pincode")
            else:
                reset_pincode_token = ""
            auth_challenge_res = auth_messages.SocialLoginRes(
                user_name=user_name,
                require_action=require_action_mess,
                reset_pincode_token=reset_pincode_token)
            return auth_challenge_res
        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTH_USER_NOT_FOUND)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def login_social_challange(self, request, context):
        try:
            user_name = request.user_name
            exists_user = self.service.get_user_by_email(user_name)
            user_info = self.user_service.get_user_by_id(exists_user["id"])
            if not user_info:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_public = bytes.fromhex(request.client_public)

            srv = srp.Verifier(user_name, salt, password_verifier,
                               client_public)
            s, B = srv.get_challenge()

            server_private = srv.get_ephemeral_secret().hex()
            logger.info(server_private)
            user_info.srp_server_private = server_private
            user_info.update()

            public_challenge_b = B.hex()
            auth_challenge_res = auth_messages.AuthChallengeRes(
                salt=user_info.salt, public_challenge_b=public_challenge_b)
            return auth_challenge_res

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTHENTICATION_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def register_srp(self, request, context):
        # check exist user
        try:
            email = request.email
            display_name = request.display_name
            password_verifier = request.password_verifier
            salt = request.salt
            iv_parameter = request.iv_parameter

            exists_user = self.service.get_user_by_email(email)
            if exists_user:
                raise Exception(Message.REGISTER_USER_ALREADY_EXISTS)

            # register new user
            new_user_id = self.service.register_srp_user(
                email, password_verifier, display_name)

            if new_user_id:
                # create new user in database
                UserService().create_new_user_srp(new_user_id, email,
                                                  password_verifier, salt,
                                                  iv_parameter, display_name,
                                                  'account')
            else:
                self.service.delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)
            try:
                SignalService().peer_register_client_key(
                    new_user_id, request.client_key_peer)
            except Exception:
                self.service.delete_user(new_user_id)
                UserService().delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)

            return auth_messages.RegisterSRPRes()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.REGISTER_USER_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def forgot_password(self, request, context):
        try:
            self.service.send_forgot_password(request.email)
            return auth_messages.BaseResponse()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTH_USER_NOT_FOUND)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def forgot_password_update(self, request, context):
        try:
            logger.info("from email {}".format(request.email))
            user_info = self.user_service.get_user_by_auth_source(
                request.email, "account")
            old_user_id = user_info.id
            self.service.verify_hash_pre_access_token(old_user_id,
                                                      request.pre_access_token,
                                                      "forgot_password")
            new_user_id = self.service.forgot_user(request.email,
                                                   request.password_verifier,
                                                   user_info.display_name)
            try:
                await GroupService().forgot_peer_groups_for_client(user_info)
            except Exception as e:
                logger.error("cannot send notify to other group")
                logger.error(e)
            SignalService().delete_client_peer_key(old_user_id)
            if new_user_id:
                # create new user in database
                UserService().forgot_user(user_info, new_user_id,
                                          request.password_verifier,
                                          request.salt, request.iv_parameter)
            else:
                self.service.delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)
            try:
                SignalService().peer_register_client_key(
                    new_user_id, request.client_key_peer)
            except Exception:
                self.service.delete_user(new_user_id)
                UserService().delete_user(new_user_id)
                raise Exception(Message.REGISTER_USER_FAILED)

            token = self.service.token(request.email,
                                       request.password_verifier)
            if token:
                client_key_obj = request.client_key_peer
                client_key_peer = auth_messages.PeerGetClientKeyResponse(
                    clientId=new_user_id,
                    workspace_domain=get_owner_workspace_domain(),
                    registrationId=client_key_obj.registrationId,
                    deviceId=client_key_obj.deviceId,
                    identityKeyPublic=client_key_obj.identityKeyPublic,
                    preKeyId=client_key_obj.preKeyId,
                    preKey=client_key_obj.preKey,
                    signedPreKeyId=client_key_obj.signedPreKeyId,
                    signedPreKey=client_key_obj.signedPreKey,
                    signedPreKeySignature=client_key_obj.signedPreKeySignature,
                    identityKeyEncrypted=client_key_obj.identityKeyEncrypted)
                self.user_service.update_last_login(user_id=new_user_id)
                auth_message = auth_messages.AuthRes(
                    workspace_domain=get_owner_workspace_domain(),
                    workspace_name=get_system_config()['server_name'],
                    access_token=token['access_token'],
                    expires_in=token['expires_in'],
                    refresh_expires_in=token['refresh_expires_in'],
                    refresh_token=token['refresh_token'],
                    token_type=token['token_type'],
                    session_state=token['session_state'],
                    scope=token['scope'],
                    salt=request.salt,
                    client_key_peer=client_key_peer,
                    iv_parameter=request.iv_parameter)
            else:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            return auth_message

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.CHANGE_PASSWORD_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @auth_required
    @request_logged
    async def logout(self, request, context):
        try:
            header_data = dict(context.invocation_metadata())
            introspect_token = KeyCloakUtils.introspect_token(
                header_data['access_token'])
            user_id = introspect_token['sub']
            device_id = request.device_id
            refresh_token = request.refresh_token
            self.service.remove_token(client_id=user_id, device_id=device_id)
            MessageService().un_subscribe(user_id, device_id)
            NotifyInAppService().un_subscribe(user_id, device_id)
            self.service.logout(refresh_token)
            return auth_messages.BaseResponse()

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.AUTH_USER_NOT_FOUND)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    async def validate_otp(self, request, context):
        try:
            success_status = self.service.verify_otp(request.user_id,
                                                     request.pre_access_token,
                                                     request.otp_code)
            if not success_status:
                raise Exception(Message.AUTH_USER_NOT_FOUND)

            user_info = self.user_service.get_user_by_id(request.user_id)
            introspect_token = KeyCloakUtils.introspect_token(
                token['access_token'])
            require_action = ""
            client_key_obj = SignalService().peer_get_client_key(
                request.user_id)
            client_key_peer = auth_messages.PeerGetClientKeyResponse(
                clientId=request.user_id,
                workspace_domain=get_owner_workspace_domain(),
                registrationId=client_key_obj.registration_id,
                deviceId=client_key_obj.device_id,
                identityKeyPublic=client_key_obj.identity_key_public,
                preKeyId=client_key_obj.prekey_id,
                preKey=client_key_obj.prekey,
                signedPreKeyId=client_key_obj.signed_prekey_id,
                signedPreKey=client_key_obj.signed_prekey,
                signedPreKeySignature=client_key_obj.signed_prekey_signature,
                identityKeyEncrypted=client_key_obj.identity_key_encrypted)
            token = self.service.token(user_info.email,
                                       user_info.password_verifier)
            self.user_service.update_last_login(user_id=request.user_id)
            return auth_messages.AuthRes(
                workspace_domain=get_owner_workspace_domain(),
                workspace_name=get_system_config()['server_name'],
                access_token=token["access_token"],
                expires_in=token['expires_in'],
                refresh_expires_in=token['refresh_expires_in'],
                refresh_token=token['refresh_token'],
                token_type=token['token_type'],
                session_state=token['session_state'],
                scope=token['scope'],
                require_action=require_action,
                salt=user_info.salt,
                client_key_peer=client_key_peer,
                iv_parameter=user_info.iv_parameter)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_MFA_STATE_FALED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    async def resend_otp(self, request, context):
        try:
            pre_access_token = self.service.resend_otp(
                request.user_id, request.pre_access_token)
            return auth_messages.MfaResendOtpRes(
                success=True, pre_access_token=pre_access_token)

        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.GET_MFA_STATE_FALED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    @request_logged
    async def register_pincode(self, request, context):
        try:
            exists_user = self.service.get_user_by_email(request.user_name)
            if not exists_user:
                raise Exception(Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
            user_info = self.user_service.get_user_by_id(exists_user["id"])
            if user_info.password_verifier is not None:
                raise Exception(Message.REGISTER_USER_ALREADY_EXISTS)
            salt = request.salt
            self.user_service.change_password(request, None,
                                              request.hash_pincode,
                                              exists_user['id'])
            # using hash_pincode as password for social user
            try:
                SignalService().peer_register_client_key(
                    exists_user['id'], request.client_key_peer)
            except Exception as e:
                logger.error(e)
            try:
                UserService().update_hash_pin(exists_user['id'],
                                              request.hash_pincode,
                                              request.salt,
                                              request.iv_parameter)
            except Exception as e:
                logger.error(e)
                ## TODO: revert change_password
                SignalService().delete_client_peer_key(exists_user['id'])
                raise Message.get_error_object(
                    Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
            require_action = ""
            client_key_obj = request.client_key_peer
            client_key_peer = auth_messages.PeerGetClientKeyResponse(
                clientId=exists_user['id'],
                workspace_domain=get_owner_workspace_domain(),
                registrationId=client_key_obj.registrationId,
                deviceId=client_key_obj.deviceId,
                identityKeyPublic=client_key_obj.identityKeyPublic,
                preKeyId=client_key_obj.preKeyId,
                preKey=client_key_obj.preKey,
                signedPreKeyId=client_key_obj.signedPreKeyId,
                signedPreKey=client_key_obj.signedPreKey,
                signedPreKeySignature=client_key_obj.signedPreKeySignature,
                identityKeyEncrypted=client_key_obj.identityKeyEncrypted)
            token = self.service.token(request.user_name, request.hash_pincode)
            introspect_token = KeyCloakUtils.introspect_token(
                token['access_token'])
            self.user_service.update_last_login(
                user_id=introspect_token['sub'])
            return auth_messages.AuthRes(
                workspace_domain=get_owner_workspace_domain(),
                workspace_name=get_system_config()['server_name'],
                access_token=token["access_token"],
                expires_in=token['expires_in'],
                refresh_expires_in=token['refresh_expires_in'],
                refresh_token=token['refresh_token'],
                token_type=token['token_type'],
                session_state=token['session_state'],
                scope=token['scope'],
                salt=request.salt,
                client_key_peer=client_key_peer,
                iv_parameter=request.iv_parameter)
        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(
                        Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)

    async def reset_pincode(self, request, context):
        try:
            success_status = self.service.verify_hash_pre_access_token(
                request.user_name, request.reset_pincode_token,
                "verify_pincode")
            exists_user = self.service.get_user_by_email(request.user_name)
            if not exists_user:
                raise Exception(Message.USER_NOT_FOUND)
            if not success_status:
                raise Exception(Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
            self.user_service.change_password(request, None,
                                              request.hash_pincode,
                                              exists_user["id"])
            old_client_key_peer = SignalService().peer_get_client_key(
                exists_user["id"])
            SignalService().client_update_peer_key(exists_user["id"],
                                                   request.client_key_peer)
            try:
                salt, iv_parameter = UserService().update_hash_pin(
                    exists_user["id"], request.hash_pincode, request.salt,
                    request.iv_parameter)
            except Exception as e:
                logger.error(e)
                SignalService().client_update_peer_key(exists_user["id"],
                                                       old_client_key_peer)
                raise Message.get_error_object(
                    Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
            client_key_obj = request.client_key_peer
            client_key_peer = auth_messages.PeerGetClientKeyResponse(
                clientId=exists_user["id"],
                workspace_domain=get_owner_workspace_domain(),
                registrationId=client_key_obj.registrationId,
                deviceId=client_key_obj.deviceId,
                identityKeyPublic=client_key_obj.identityKeyPublic,
                preKeyId=client_key_obj.preKeyId,
                preKey=client_key_obj.preKey,
                signedPreKeyId=client_key_obj.signedPreKeyId,
                signedPreKey=client_key_obj.signedPreKey,
                signedPreKeySignature=client_key_obj.signedPreKeySignature,
                identityKeyEncrypted=client_key_obj.identityKeyEncrypted)
            # logout all device before get new token for user after updated new key
            user_sessions = KeyCloakUtils.get_sessions(
                user_id=exists_user["id"])
            for user_session in user_sessions:
                KeyCloakUtils.remove_session(session_id=user_session['id'])
            token = self.service.token(request.user_name, request.hash_pincode)
            introspect_token = KeyCloakUtils.introspect_token(
                token['access_token'])
            return auth_messages.AuthRes(
                workspace_domain=get_owner_workspace_domain(),
                workspace_name=get_system_config()['server_name'],
                access_token=token["access_token"],
                expires_in=token['expires_in'],
                refresh_expires_in=token['refresh_expires_in'],
                refresh_token=token['refresh_token'],
                token_type=token['token_type'],
                session_state=token['session_state'],
                scope=token['scope'],
                salt=salt,
                client_key_peer=client_key_peer,
                iv_parameter=iv_parameter)
        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(
                        Message.REGISTER_CLIENT_SIGNAL_KEY_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
                context.set_details(
                    json.dumps(errors, default=lambda x: x.__dict__))
                context.set_code(grpc.StatusCode.INTERNAL)

    async def verify_pincode(self, request, context):
        try:
            exists_user = self.service.get_user_by_email(request.user_name)
            user_info = self.user_service.get_user_by_id(exists_user["id"])
            if not user_info:
                raise Exception(Message.AUTH_USER_NOT_FOUND)
            password_verifier = bytes.fromhex(user_info.password_verifier)
            salt = bytes.fromhex(user_info.salt)
            client_session_key_proof = request.client_session_key_proof
            client_session_key_proof_bytes = bytes.fromhex(
                client_session_key_proof)

            srv = srp.Verifier(username=request.user_name,
                               bytes_s=salt,
                               bytes_v=password_verifier,
                               bytes_A=bytes.fromhex(request.client_public),
                               bytes_b=bytes.fromhex(
                                   user_info.srp_server_private))
            srv.verify_session(client_session_key_proof_bytes)
            authenticated = srv.authenticated()

            if not authenticated:
                raise Exception(Message.AUTHENTICATION_FAILED)

            token = self.service.token(request.user_name,
                                       user_info.password_verifier)
            introspect_token = KeyCloakUtils.introspect_token(
                token['access_token'])
            if not token:
                raise Exception(Message.VERIFY_PINCODE_FAILED)

            client_key_obj = SignalService().peer_get_client_key(
                introspect_token['sub'])
            client_key_peer = auth_messages.PeerGetClientKeyResponse(
                clientId=introspect_token['sub'],
                workspace_domain=get_owner_workspace_domain(),
                registrationId=client_key_obj.registration_id,
                deviceId=client_key_obj.device_id,
                identityKeyPublic=client_key_obj.identity_key_public,
                preKeyId=client_key_obj.prekey_id,
                preKey=client_key_obj.prekey,
                signedPreKeyId=client_key_obj.signed_prekey_id,
                signedPreKey=client_key_obj.signed_prekey,
                signedPreKeySignature=client_key_obj.signed_prekey_signature,
                identityKeyEncrypted=client_key_obj.identity_key_encrypted)
            self.user_service.update_last_login(
                user_id=introspect_token['sub'])
            return auth_messages.AuthRes(
                workspace_domain=get_owner_workspace_domain(),
                workspace_name=get_system_config()['server_name'],
                access_token=token["access_token"],
                expires_in=token['expires_in'],
                refresh_expires_in=token['refresh_expires_in'],
                refresh_token=token['refresh_token'],
                token_type=token['token_type'],
                session_state=token['session_state'],
                scope=token['scope'],
                salt=user_info.salt,
                client_key_peer=client_key_peer,
                iv_parameter=user_info.iv_parameter)
        except Exception as e:
            logger.error(e)
            if not e.args or e.args[0] not in Message.msg_dict:
                errors = [
                    Message.get_error_object(Message.VERIFY_PINCODE_FAILED)
                ]
            else:
                errors = [Message.get_error_object(e.args[0])]
            context.set_details(
                json.dumps(errors, default=lambda x: x.__dict__))
            context.set_code(grpc.StatusCode.INTERNAL)