From 5fbb3f7a41762006fa22e10ca01f79e1eafe4bbc Mon Sep 17 00:00:00 2001 From: miguelpadin Date: Sun, 26 Dec 2021 12:07:29 +0100 Subject: [PATCH 1/5] [IMP] auth jwt with user credentials --- auth_jwt_login/__init__.py | 1 + auth_jwt_login/__manifest__.py | 9 +++++++ auth_jwt_login/models/__init__.py | 1 + auth_jwt_login/models/auth_jwt_validator.py | 28 +++++++++++++++++++++ 4 files changed, 39 insertions(+) create mode 100644 auth_jwt_login/__init__.py create mode 100644 auth_jwt_login/__manifest__.py create mode 100644 auth_jwt_login/models/__init__.py create mode 100644 auth_jwt_login/models/auth_jwt_validator.py diff --git a/auth_jwt_login/__init__.py b/auth_jwt_login/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/auth_jwt_login/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/auth_jwt_login/__manifest__.py b/auth_jwt_login/__manifest__.py new file mode 100644 index 0000000000..d05ecf8c5e --- /dev/null +++ b/auth_jwt_login/__manifest__.py @@ -0,0 +1,9 @@ +{ + "name": "Auth JWT Login Base", + "summary": """ + JWT bearer token authentication with user and password.""", + "version": "14.0.1.1.0", + "website": "https://github.com/OCA/server-auth", + "depends": ["auth_jwt"], + "external_dependencies": {"python": ["pyjwt", "cryptography"]}, +} diff --git a/auth_jwt_login/models/__init__.py b/auth_jwt_login/models/__init__.py new file mode 100644 index 0000000000..49c30eb077 --- /dev/null +++ b/auth_jwt_login/models/__init__.py @@ -0,0 +1 @@ +from . import auth_jwt_validator diff --git a/auth_jwt_login/models/auth_jwt_validator.py b/auth_jwt_login/models/auth_jwt_validator.py new file mode 100644 index 0000000000..6828fac80a --- /dev/null +++ b/auth_jwt_login/models/auth_jwt_validator.py @@ -0,0 +1,28 @@ +from odoo import _, api, fields, models, tools +from odoo.exceptions import ValidationError + + +class AuthJwtValidator(models.Model): + _inherit = "auth.jwt.validator" + + user_id_strategy = fields.Selection( + selection_add=[("login", "Login")], + ondelete={'login': 'cascade'}, + ) + + def _get_uid(self, payload): + if self.user_id_strategy == 'login': + if 'username' in payload and 'password' in payload: + user = self.env['res.users'].search( + [ + ("login", "=", payload['username']) + ] + ) + if not user: + raise ValidationError + user.with_user(user)._check_credentials(payload['password'], None) + return user.id + else: + raise ValidationError + else: + return super()._get_uid(payload) From 2f845d6e478a175b42abb9e1d20d39f23c88e70a Mon Sep 17 00:00:00 2001 From: miguelpadin Date: Mon, 11 Apr 2022 15:38:34 +0100 Subject: [PATCH 2/5] [imp] auth jwt with exp. date --- auth_jwt_login/models/auth_jwt_validator.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/auth_jwt_login/models/auth_jwt_validator.py b/auth_jwt_login/models/auth_jwt_validator.py index 6828fac80a..444d6a7324 100644 --- a/auth_jwt_login/models/auth_jwt_validator.py +++ b/auth_jwt_login/models/auth_jwt_validator.py @@ -1,3 +1,4 @@ +import time from odoo import _, api, fields, models, tools from odoo.exceptions import ValidationError @@ -12,6 +13,11 @@ class AuthJwtValidator(models.Model): def _get_uid(self, payload): if self.user_id_strategy == 'login': + timestamp_expiration_date = payload['exp'] + if timestamp_expiration_date: + timestamp_now = int(time.time() * 1000.0) + if (timestamp_expiration_date - timestamp_now) < 0: + raise ValidationError if 'username' in payload and 'password' in payload: user = self.env['res.users'].search( [ From a5b4d8b6f2533fb73942db8c377f6b6146309a46 Mon Sep 17 00:00:00 2001 From: miguelpadin Date: Thu, 19 May 2022 14:23:08 +0100 Subject: [PATCH 3/5] [FIX] change response status code when user and/or password is wrong --- auth_jwt_login/models/auth_jwt_validator.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/auth_jwt_login/models/auth_jwt_validator.py b/auth_jwt_login/models/auth_jwt_validator.py index 444d6a7324..75bf257e7d 100644 --- a/auth_jwt_login/models/auth_jwt_validator.py +++ b/auth_jwt_login/models/auth_jwt_validator.py @@ -1,4 +1,7 @@ import time + +import werkzeug + from odoo import _, api, fields, models, tools from odoo.exceptions import ValidationError @@ -17,7 +20,7 @@ def _get_uid(self, payload): if timestamp_expiration_date: timestamp_now = int(time.time() * 1000.0) if (timestamp_expiration_date - timestamp_now) < 0: - raise ValidationError + raise werkzeug.exceptions.Forbidden(_("Token not valid.")) if 'username' in payload and 'password' in payload: user = self.env['res.users'].search( [ From 3eb9d20a8e94a3d9390ff2cf1915c0d5c470b434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Lodeiros?= Date: Wed, 14 Dec 2022 11:22:14 +0100 Subject: [PATCH 4/5] [IMP]auth_kwt_validator: Add interactive loging key --- auth_jwt_login/models/auth_jwt_validator.py | 20 +++++++++---------- .../auth_jwt_login/odoo/addons/auth_jwt_login | 1 + setup/auth_jwt_login/setup.py | 6 ++++++ 3 files changed, 17 insertions(+), 10 deletions(-) create mode 120000 setup/auth_jwt_login/odoo/addons/auth_jwt_login create mode 100644 setup/auth_jwt_login/setup.py diff --git a/auth_jwt_login/models/auth_jwt_validator.py b/auth_jwt_login/models/auth_jwt_validator.py index 75bf257e7d..5935d82acb 100644 --- a/auth_jwt_login/models/auth_jwt_validator.py +++ b/auth_jwt_login/models/auth_jwt_validator.py @@ -2,7 +2,7 @@ import werkzeug -from odoo import _, api, fields, models, tools +from odoo import _, fields, models from odoo.exceptions import ValidationError @@ -11,25 +11,25 @@ class AuthJwtValidator(models.Model): user_id_strategy = fields.Selection( selection_add=[("login", "Login")], - ondelete={'login': 'cascade'}, + ondelete={"login": "cascade"}, ) def _get_uid(self, payload): - if self.user_id_strategy == 'login': - timestamp_expiration_date = payload['exp'] + if self.user_id_strategy == "login": + timestamp_expiration_date = payload["exp"] if timestamp_expiration_date: timestamp_now = int(time.time() * 1000.0) if (timestamp_expiration_date - timestamp_now) < 0: raise werkzeug.exceptions.Forbidden(_("Token not valid.")) - if 'username' in payload and 'password' in payload: - user = self.env['res.users'].search( - [ - ("login", "=", payload['username']) - ] + if "username" in payload and "password" in payload: + user = self.env["res.users"].search( + [("login", "=", payload["username"])] ) if not user: raise ValidationError - user.with_user(user)._check_credentials(payload['password'], None) + user.with_user(user)._check_credentials( + payload["password"], {"interactive": True} + ) return user.id else: raise ValidationError diff --git a/setup/auth_jwt_login/odoo/addons/auth_jwt_login b/setup/auth_jwt_login/odoo/addons/auth_jwt_login new file mode 120000 index 0000000000..5664d010a3 --- /dev/null +++ b/setup/auth_jwt_login/odoo/addons/auth_jwt_login @@ -0,0 +1 @@ +../../../../auth_jwt_login \ No newline at end of file diff --git a/setup/auth_jwt_login/setup.py b/setup/auth_jwt_login/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/auth_jwt_login/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 81f68db16e55e7e38ece424b44ce9e62b31e643a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dar=C3=ADo=20Lodeiros?= Date: Fri, 26 Jan 2024 11:46:35 +0100 Subject: [PATCH 5/5] [IMP]auth_jwt_login: avoid send innecesary pwd param in tokens payload and set timestamp in seconds --- auth_jwt_login/models/auth_jwt_validator.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/auth_jwt_login/models/auth_jwt_validator.py b/auth_jwt_login/models/auth_jwt_validator.py index 5935d82acb..5c07c3b938 100644 --- a/auth_jwt_login/models/auth_jwt_validator.py +++ b/auth_jwt_login/models/auth_jwt_validator.py @@ -18,18 +18,15 @@ def _get_uid(self, payload): if self.user_id_strategy == "login": timestamp_expiration_date = payload["exp"] if timestamp_expiration_date: - timestamp_now = int(time.time() * 1000.0) + timestamp_now = int(time.time()) if (timestamp_expiration_date - timestamp_now) < 0: raise werkzeug.exceptions.Forbidden(_("Token not valid.")) - if "username" in payload and "password" in payload: + if "username" in payload: user = self.env["res.users"].search( [("login", "=", payload["username"])] ) if not user: raise ValidationError - user.with_user(user)._check_credentials( - payload["password"], {"interactive": True} - ) return user.id else: raise ValidationError