diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv
index 77661d7fe861f8eb42b61ed6a8b475b1529a71c3..f7b609edbde0253e02461b566e05047033216d98 100644
--- a/security/ir.model.access.csv
+++ b/security/ir.model.access.csv
@@ -5,3 +5,4 @@ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
 "access_acc_actu_group_portal","acc_actu group_portal","acc_actus.model_acc_actu","base.group_portal",1,0,0,0
 "access_acc_account_group_portal","acc_account group_portal","acc_account.model_acc_account","base.group_portal",1,0,0,0
 "access_acc_contract_group_portal","acc_contract group_portal","acc_operation.model_acc_contract","base.group_portal",1,0,0,0
+"access_mail_template_group_portal","mail_template group_portal","mail.model_mail_template","base.group_portal",1,0,0,0
diff --git a/services/auth_services.py b/services/auth_services.py
index 85bab21033c0654fd1bac4350f17ed77dafffc93..b4e5e1d85c8c0a661a72e1aaf7af31b81944e1b1 100644
--- a/services/auth_services.py
+++ b/services/auth_services.py
@@ -1,6 +1,9 @@
 # © 2021 Le Filament (<http://www.le-filament.com>)
 # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
 
+import logging
+import werkzeug
+
 from datetime import datetime, timedelta
 
 import jwt
@@ -8,6 +11,8 @@ import jwt
 from odoo.addons.base_rest import restapi
 from odoo.addons.component.core import Component
 
+_logger = logging.getLogger(__name__)
+
 
 class AuthService(Component):
     _inherit = "base.rest.service"
@@ -68,6 +73,187 @@ class AuthService(Component):
         }
         return datas
 
+    # A faire pour gestion User
+    @restapi.method(
+        [(["/reset-password"], "POST")],
+        input_param=restapi.CerberusValidator("_validator_reset"),
+        output_param=restapi.CerberusValidator("_validator_return_reset"),
+        auth="none",
+        save_session=True,
+        cors="*",
+        crsf=False,
+    )
+    def reset_password(self, **params):
+        """
+        Log user and return user data & JWT token
+        """
+        User = self.env["res.users"].sudo()
+        login = params.get("login", False)
+        datas = {}
+        if login:
+            user = User.search([("login", "=", login)])
+            if user:
+                jwt_validator = self.env.ref("acc_rest_api.elo_validator").sudo()
+                exp = datetime.now() + timedelta(
+                    hours=(jwt_validator.token_expiration * 24))
+                payload = {
+                    "aud": jwt_validator.audience,
+                    "iss": jwt_validator.issuer,
+                    "exp": exp,
+                    "email": user.login,
+                    "id": user.id,
+                    "partner_id": user.partner_id.id,
+                }
+                token = jwt.encode(
+                    payload,
+                    key=jwt_validator.secret_key,
+                    algorithm=jwt_validator.secret_algorithm,
+                )
+                datas = {
+                    # "user": user_datas,
+                    "token": {"access_token": token,
+                              "expiration_date": payload.get("exp")},
+                }
+                # send email to users with their signup url
+                template = False
+                if not template:
+                    template = self.env.ref('acc_portal.acc_reset_password_email')
+                assert template._name == 'mail.template'
+
+                # template.sudo().write(template_values)
+                try:
+
+                    lang = user.lang
+
+                    query = dict(db=self.request.env.cr.dbname)
+                    query['login'] = user.login
+                    route = 'signup'
+                    signup_url = "/%s?%s" % (route, werkzeug.urls.url_encode(query))
+                    signup_url = werkzeug.urls.url_join(user.company_id.url_app, signup_url)
+
+                    user.partner_id.sudo().signup_prepare()
+
+                    template.sudo().with_context(
+                        portal_url=signup_url,
+                        lang=lang
+                    ).send_mail(
+                        user.id,
+                        force_send=True,
+                        raise_exception=True)
+                except Exception as e:
+                    datas['error'] = str(e)
+                _logger.info("Password reset email sent for user <%s> to <%s>",
+                                 user.login, user.email)
+            else:
+                datas['info'] = "Veuillez réinitialiser votre mot de passe: adresse email incorrecte"
+        return datas
+
+    @restapi.method(
+        [(["/get-password"], "GET")],
+        input_param=restapi.CerberusValidator("_validator_get_password"),
+        output_param=restapi.CerberusValidator("_validator_return_password"),
+        cors="*",
+        crsf=False,
+    )
+    def get_password(self):
+        user_id = self.env["res.users"].browse(self.request.uid)
+        user = {
+            "login": user_id.login,
+        }
+        return user
+
+    @restapi.method(
+        [(["/get-signup"], "GET")],
+        input_param=restapi.CerberusValidator("_validator_get_password"),
+        output_param=restapi.CerberusValidator("_validator_return_password"),
+        cors="*",
+        crsf=False,
+    )
+    def get_signup(self, **params):
+        user_id = self.env["res.users"].browse(self.request.uid)
+        user = {
+            "login": user_id.login,
+        }
+        return user
+
+    @restapi.method(
+        [(["/set-password"], "POST")],
+        input_param=restapi.CerberusValidator("_validator_set_password"),
+        output_param=restapi.CerberusValidator("_validator_return_password"),
+        auth="none",
+        save_session=True,
+        cors="*",
+        crsf=False,
+    )
+    def set_password(self, **params):
+        User = self.env["res.users"].sudo()
+        login = params.get("login", False)
+        password = params.get("password", False)
+        confirm_password = params.get("confirm_password", False)
+        datas = {}
+        if login:
+            user = User.search([("login", "=", login)])
+            if user:
+                if password == confirm_password:
+                    user.write({'password': password})
+                else:
+                    datas['error'] = "Les mots de passe ne correspondent pas, veuillez les saisir à nouveau."
+        return datas
+
+    @restapi.method(
+        [(["/signup"], "POST")],
+        input_param=restapi.CerberusValidator("_validator_signup"),
+        output_param=restapi.CerberusValidator("_validator_return_signup"),
+        auth="none",
+        save_session=True,
+        cors="*",
+        crsf=False,
+    )
+    def signup(self, **params):
+        User = self.env["res.users"].sudo()
+        login = params.get("login", False)
+        password = params.get("password", False)
+        confirm_password = params.get("confirm_password", False)
+        datas = {}
+        if login:
+            user = User.search([("login", "=", login)])
+            if user:
+                user_datas = user.mapped(
+                    lambda u: {
+                        "userId": u.id,
+                        "userEmail": u.login,
+                        "userName": u.name,
+                        "userCompany": u.parent_id.name if u.parent_id else None,
+                    }
+                )[0]
+                if password == confirm_password:
+                    jwt_validator = self.env.ref("acc_rest_api.elo_validator").sudo()
+                    exp = datetime.now() + timedelta(
+                        hours=(jwt_validator.token_expiration * 24))
+                    payload = {
+                        "aud": jwt_validator.audience,
+                        "iss": jwt_validator.issuer,
+                        "exp": exp,
+                        "email": user.login,
+                        "id": user.id,
+                        "partner_id": user.partner_id.id,
+                    }
+                    token = jwt.encode(
+                        payload,
+                        key=jwt_validator.secret_key,
+                        algorithm=jwt_validator.secret_algorithm,
+                    )
+                    datas = {
+                        "user": user_datas,
+                        "token": {"access_token": token,
+                                  "expiration_date": payload.get("exp")},
+                    }
+                    user.write({'password': password})
+                else:
+                    datas["error"] = "Les mots de passe ne correspondent pas, veuillez les saisir à nouveau."
+                    datas["user"] = user_datas
+        return datas
+
     @restapi.method(
         [(["/logout"], "GET")],
         cors="*",
@@ -150,6 +336,31 @@ class AuthService(Component):
             },
         }
 
+    def _validator_reset(self):
+        return {
+            "login": {"type": "string"},
+        }
+
+    def _validator_return_reset(self):
+        return {
+            # "user": {
+            #     "type": "dict",
+            #     "schema": {
+            #         "userId": {"type": "integer"},
+            #         "userEmail": {"type": "string"},
+            #         "userName": {"type": "string"},
+            #         "userCompany": {"type": "string", "nullable": True},
+            #     },
+            # },
+            "token": {
+                "type": "dict",
+                "schema": {
+                    "access_token": {"type": "string", "nullable": True},
+                    "expiration_date": {"type": "datetime", "nullable": True},
+                },
+            },
+        }
+
     def _validator_logout(self):
         return {}
 
@@ -162,15 +373,60 @@ class AuthService(Component):
     def _validator_set_my_account(self):
         return {
             "login": {"type": "string"},
-            "firstname": {"type": "string"},
-            "lastname": {"type": "string"},
+            "firstname": {"type": "string", "nullable": True},
+            "lastname": {"type": "string", "nullable": True},
+        }
+
+    def _validator_get_password(self):
+        return {}
+
+    def _validator_set_password(self):
+        return {
+            "login": {"type": "string"},
+            "password": {"type": "string", "nullable": True},
+            "confirm_password": {"type": "string", "nullable": True},
+        }
+
+    def _validator_signup(self):
+        return {
+            "login": {"type": "string"},
+            "password": {"type": "string", "nullable": True},
+            "confirm_password": {"type": "string", "nullable": True},
         }
 
     def _validator_return_my_account(self):
         return {
             "login": {"type": "string"},
-            "firstname": {"type": "string"},
-            "lastname": {"type": "string"},
+            "firstname": {"type": "string", "nullable": True},
+            "lastname": {"type": "string", "nullable": True},
             "name": {"type": "string"},
             "company": {"type": "string", "nullable": True},
         }
+
+    def _validator_return_password(self):
+        return {
+            "login": {"type": "string"},
+        }
+
+    def _validator_return_signup(self):
+        return {
+            "user": {
+                "type": "dict",
+                "schema": {
+                    "userId": {"type": "integer"},
+                    "userEmail": {"type": "string"},
+                    "userName": {"type": "string"},
+                    "userCompany": {"type": "string", "nullable": True},
+                },
+            },
+            "login": {"type": "string"},
+            "error": {"type": "string"},
+            "token": {
+                "type": "dict",
+                "schema": {
+                    "access_token": {"type": "string", "nullable": True},
+                    "expiration_date": {"type": "datetime", "nullable": True},
+                },
+                "nullable": True
+            },
+        }