Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
c0fd9d4
[ADD] auth_jwt
sbidoul Apr 28, 2021
7524e3a
auth_jwt: use PyJWT instead of python-jose
sbidoul Apr 28, 2021
d1704ff
auth_jwt: add signature algorithms
sbidoul Apr 28, 2021
1de7a19
auth_jwt: support multiple audiences
sbidoul Apr 28, 2021
685cb9a
auth_jwt: add nbf validation test
sbidoul Apr 28, 2021
f272fc0
auth_jwt: docs clarification and fixes
sbidoul Apr 29, 2021
e1f8153
auth_jwt: fix jwks URI support
sbidoul Jun 25, 2021
9144a6c
auth_jwt: mock instead of committing in tests
sbidoul Jul 25, 2021
66c575e
auth_jwt: more precise precondition check
sbidoul Jul 26, 2021
1dd5493
Rename auth_jwt_test to auth_jwt_demo
sbidoul Jul 26, 2021
f03d093
[MIG] auth_jwt
sbidoul Jun 27, 2021
5a64b05
[UPD] Update auth_jwt.pot
oca-travis Jul 28, 2021
26983a1
[IMP] auth_jwt: add public_or_jwt auth method
sbidoul Oct 5, 2021
3cf0689
auth_jwt: Relicence under LGPL
yankinmax Dec 29, 2021
693adc4
[IMP] auth_jwt: Add validator.next_validator_id to allow validator ch…
paradoxxxzero Feb 17, 2022
69fed48
[MIG] auth_jwt from 14 to 16
sbidoul Jun 6, 2023
09804a9
[MIG] auth_jwt: convert unit tests to integration tests
sbidoul Jun 6, 2023
271eea6
auth_jwt: add cookie mode
sbidoul Jun 7, 2023
1737483
auth_jwt: clarify exceptions
sbidoul Jun 8, 2023
688ef46
auth_jwt: minor refactoring
sbidoul Jun 8, 2023
93960f6
[IMP] auth_jwt: refactor
sbidoul Jun 8, 2023
5f55f23
[FIX] auth_jwt: don't use public mode if a cookie is present
sbidoul Jun 8, 2023
4656e78
[IMP] auth_jwt: check cookie_name is present in cookie mode
sbidoul Jun 16, 2023
7376452
Added translation using Weblate (Spanish)
Ivorra78 Aug 25, 2023
db4ec28
Added translation using Weblate (Italian)
rbellanova Dec 15, 2023
1485860
Translated using Weblate (Italian)
mymage Jan 3, 2024
52491b3
Translated using Weblate (Italian)
francesco-ooops Jan 29, 2024
6a8ddba
[MIG] auth_jwt: Migration to 17.0
MikeAelbrecht May 30, 2024
1f3d3be
[IMP] auth_jwt: pre-commit auto fixes
dnplkndll Jan 18, 2025
8f388c5
[MIG] auth_jwt: Migration to 18.0
dnplkndll Jan 16, 2025
63dc65e
[IMP] auth_jwt: pre-commit auto fixes
pablo-cort-s73 Oct 2, 2025
8f2fddb
[MIG] auth_jwt: Migration to 19.0
pablo-cort-s73 Oct 13, 2025
b1dceb2
Rename auth_jwt_test to auth_jwt_demo
sbidoul Jul 26, 2021
28e2868
[MIG] auth_jwt
sbidoul Jun 27, 2021
cae1006
[UPD] Update auth_jwt_demo.pot
oca-travis Jul 28, 2021
5689c4d
[IMP] auth_jwt: add public_or_jwt auth method
sbidoul Oct 5, 2021
85a6bac
auth_jwt_demo: Relicence under LGPL
yankinmax Dec 29, 2021
ad7d6a0
[MIG] auth_jwt_demo from 14 to 16
sbidoul Jun 6, 2023
b5f2f3d
[MIG] auth_jwt: convert unit tests to integration tests
sbidoul Jun 6, 2023
bec647e
auth_jwt: add cookie mode
sbidoul Jun 7, 2023
fe63083
[FIX] auth_jwt: don't use public mode if a cookie is present
sbidoul Jun 8, 2023
cfaae2b
[IMP] auth_jwt: split test class
sbidoul Jun 16, 2023
280625c
[IMP] auth_jwt_demo: add tests
sbidoul Nov 29, 2023
48e3c1a
Added translation using Weblate (Italian)
mymage Dec 28, 2023
405c81c
[MIG] auth_jwt_demo: pre-commit auto fixes
sbidoul Oct 9, 2025
b7bd507
[MIG] auth_jwt_demo: migrate from 16 to 18
sbidoul Oct 9, 2025
b810447
[MIG] auth_jwt_demo: capture log warning and assert expected warning
sbidoul Oct 9, 2025
489faaf
[IMP] auth_jwt_demo: pre-commit auto fixes
pablo-cort-s73 Oct 10, 2025
7a267ba
[MIG] auth_jwt_demo: Migration to 19.0
pablo-cort-s73 Oct 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ exclude: |
/build/|/dist/|
# Ignore test files in addons
/tests/samples/.*|
^auth_jwt_demo/tests/spa.*|
# You don't usually want a bot to modify your legal texts
(LICENSE.*|COPYING.*)
default_language_version:
Expand Down
168 changes: 168 additions & 0 deletions auth_jwt/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
.. image:: https://odoo-community.org/readme-banner-image
:target: https://odoo-community.org/get-involved?utm_source=readme
:alt: Odoo Community Association

========
Auth JWT
========

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0257cb75b9a02ab9b3f1aeebe8e0c5aee0b983f8b5ac1692132897dfb1986d02
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/license-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github
:target: https://github.com/OCA/server-auth/tree/19.0/auth_jwt
:alt: OCA/server-auth
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/server-auth-19-0/server-auth-19-0-auth_jwt
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-auth&target_branch=19.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

JWT bearer token authentication.

**Table of contents**

.. contents::
:local:

Installation
============

This module requires the ``pyjwt`` library to be installed.

Usage
=====

This module lets developpers add a new ``jwt`` authentication method on
Odoo controller routes.

To use it, you must:

- Create an ``auth.jwt.validator`` record to configure how the JWT
token will be validated.
- Add an ``auth="jwt_{validator-name}"`` or
``auth="public_or_jwt_{validator-name}"`` attribute to the routes you
want to protect where ``{validator-name}`` corresponds to the name
attribute of the JWT validator record.

The ``auth_jwt_demo`` module provides examples.

The JWT validator can be configured with the following properties:

- ``name``: the validator name, to match the
``auth="jwt_{validator-name}"`` route property.
- ``audience``: a comma-separated list of allowed audiences, used to
validate the ``aud`` claim.
- ``issuer``: used to validate the ``iss`` claim.
- Signature type (secret or public key), algorithm, secret and JWK URI
are used to validate the token signature.

In addition, the ``exp`` claim is validated to reject expired tokens.

If the ``Authorization`` HTTP header is missing, malformed, or contains
an invalid token, the request is rejected with a 401 (Unauthorized)
code, unless the cookie mode is enabled (see below).

If the token is valid, the request executes with the configured user id.
By default the user id selection strategy is ``static`` (i.e. the same
for all requests) and the selected user is configured on the JWT
validator. Additional strategies can be provided by overriding the
``_get_uid()`` method and extending the ``user_id_strategy`` selection
field.

The selected user is *not* stored in the session. It is only available
in ``request.uid`` (and thus it is the one used in ``request.env``). To
avoid any confusion and mismatches between the bearer token and the
session, this module rejects requests made with an authenticated user
session.

Additionally, if a ``partner_id_strategy`` is configured, a partner is
searched and if found, its id is stored in the
``request.jwt_partner_id`` attribute. If ``partner_id_required`` is set,
a 401 (Unauthorized) is returned if no partner was found. Otherwise
``request.jwt_partner_id`` is left falsy. Additional strategies can be
provided by overriding the ``_get_partner_id()`` method and extending
the ``partner_id_strategy`` selection field.

The decoded JWT payload is stored in ``request.jwt_payload``.

The ``public_auth_jwt`` method delegates authentication to the standard
Odoo ``public`` method when the Authorization header is not set. If it
is set, the regular JWT authentication is performed as described above.
This method is useful for public endpoints that need to work for
anonymous users, but can be enhanced when an authenticated user is know.
A typical use case is a "add to cart" endpoint that can work for
anonymous users, but can be enhanced by binding the cart to a known
customer when the authenticated user is known.

You can enable a cookie mode on JWT validators. In this case, the JWT
payload obtained from the ``Authorization`` header is returned as a
Http-Only cookie. This mode is sometimes simpler for front-end
applications which do not then need to store and protect the JWT token
across requests and can simply rely on the cookie management mechanisms
of browsers. When both the ``Authorization`` header and a cookie are
provided, the cookie is ignored in order to let clients authenticate
with a different user by providing a new JWT token.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-auth/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/server-auth/issues/new?body=module:%20auth_jwt%0Aversion:%2019.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* ACSONE SA/NV

Contributors
------------

- Stéphane Bidoul <stephane.bidoul@acsone.eu>
- Mohamed Alkobrosli <malkobrosly@kencove.com>

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

.. |maintainer-sbidoul| image:: https://github.com/sbidoul.png?size=40px
:target: https://github.com/sbidoul
:alt: sbidoul

Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:

|maintainer-sbidoul|

This module is part of the `OCA/server-auth <https://github.com/OCA/server-auth/tree/19.0/auth_jwt>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
1 change: 1 addition & 0 deletions auth_jwt/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
20 changes: 20 additions & 0 deletions auth_jwt/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2021 ACSONE SA/NV
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

{
"name": "Auth JWT",
"summary": """
JWT bearer token authentication.""",
"version": "19.0.1.0.0",
"license": "LGPL-3",
"author": "ACSONE SA/NV,Odoo Community Association (OCA)",
"maintainers": ["sbidoul"],
"website": "https://github.com/OCA/server-auth",
"depends": ["base"],
"external_dependencies": {"python": ["pyjwt", "cryptography"]},
"data": ["security/ir.model.access.csv", "views/auth_jwt_validator_views.xml"],
"demo": [],
"installable": True,
"application": False,
"auto_install": False,
}
54 changes: 54 additions & 0 deletions auth_jwt/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Copyright 2021 ACSONE SA/NV
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl)

from werkzeug.exceptions import InternalServerError, Unauthorized


class UnauthorizedMissingAuthorizationHeader(Unauthorized):
pass


class UnauthorizedMissingCookie(Unauthorized):
pass


class UnauthorizedMalformedAuthorizationHeader(Unauthorized):
pass


class UnauthorizedSessionMismatch(Unauthorized):
pass


class AmbiguousJwtValidator(InternalServerError):
pass


class JwtValidatorNotFound(InternalServerError):
pass


class UnauthorizedInvalidToken(Unauthorized):
pass


class UnauthorizedPartnerNotFound(Unauthorized):
pass


class UnauthorizedCompositeJwtError(Unauthorized):
"""Indicate that multiple errors occurred during JWT chain validation."""

def __init__(self, errors):
self.errors = errors
super().__init__(
"Multiple errors occurred during JWT chain validation:\n"
+ "\n".join(
f"{validator_name}: {error}"
for validator_name, error in self.errors.items()
)
)


class ConfigurationError(InternalServerError):
pass
Loading
Loading