Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
138 changes: 138 additions & 0 deletions auth_oauth_code_flow/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
===============================
Authentication OAuth2 Code Flow
===============================

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

.. |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/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github
:target: https://github.com/OCA/server-auth/tree/18.0/auth_oauth_code_flow
: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-18-0/server-auth-18-0-auth_oauth_code_flow
: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=18.0
:alt: Try me on Runboat

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

This module provides a high-security implementation of the OAuth2
Authorization Code Flow for Odoo 18. It serves as the essential bridge
for modern identity providers (like GitHub) that have deprecated the
insecure Implicit Flow.

The Security Problem: Why Implicit Flow is Risky
------------------------------------------------

Standard Odoo and many older modules rely on the OAuth2 Implicit Flow.
In this flow, the access_token is sent directly to the user's browser in
the URL fragment

- Leakage: Tokens are visible in browser history, server logs, and can
be intercepted by malicious browser extensions.

- Exposure: Sensitive credentials "touch" the client side, increasing
the attack surface.

Authorization Code Flow
-----------------------

This module implements the Authorization Code Flow (access_token_code),
which is the industry standard for secure web applications.

- Server-to-Server: The access_token is exchanged in a secure backend
POST request between Odoo and the Provider.

- Invisible Tokens: Sensitive tokens never appear in the browser URL or
history.

- PKCE Ready: Supports Proof Key for Code Exchange (PKCE) to prevent
authorization code injection attacks.

Key Value for Developers

- Hybrid Support: Works in harmony with the OCA auth_oidc module. It
acts as a pre-processor for the token handshake, allowing strict OIDC
providers (Keycloak/Cognito) and standard OAuth2 providers (GitHub) to
coexist on the same login page.

**Table of contents**

.. contents::
:local:

Configuration
=============

Automatic System Parameters
---------------------------

Upon installation, this module automatically configures the following
system parameter:

- auth_oauth.authorization_header: Set to 1.

Purpose: This forces Odoo to send the access_token in the HTTP
Authorization Header (Bearer ) rather than as a query parameter in the
URL. GitHub and most modern providers have deprecated URL-based tokens
for security reasons.

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_oauth_code_flow%0Aversion:%2018.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
-------

* KOBROS-TECH LTD

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

- Mohamed Alkobrosli <mohamed@kobros-tech.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-kobros-tech| image:: https://github.com/kobros-tech.png?size=40px
:target: https://github.com/kobros-tech
:alt: kobros-tech

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

|maintainer-kobros-tech|

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

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
4 changes: 4 additions & 0 deletions auth_oauth_code_flow/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2026 KOBROS-TECH LTD <https://www.kobros-tech.com>
# License: AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from . import models
18 changes: 18 additions & 0 deletions auth_oauth_code_flow/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 KOBROS-TECH LTD <https://www.kobros-tech.com>
# License: AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

{
"name": "Authentication OAuth2 Code Flow",
"version": "18.0.1.0.0",
"license": "AGPL-3",
"author": ("KOBROS-TECH LTD, " "Odoo Community Association (OCA)"),
"maintainers": ["kobros-tech"],
"website": "https://github.com/OCA/server-auth",
"summary": """
Adds Authorization Code Flow support to OAuth2 (e.g., GitHub)
""",
"depends": ["auth_oauth", "auth_oidc"],
"data": [
"data/auth_oauth_data.xml",
],
}
12 changes: 12 additions & 0 deletions auth_oauth_code_flow/data/auth_oauth_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<!--
Force Odoo to use the 'Authorization: Bearer' header
instead of the URL query parameter for UserInfo validation.
This is a strict requirement for GitHub and modern OAuth2 providers.
-->
<record id="auth_oauth_authorization_header" model="ir.config_parameter">
<field name="key">auth_oauth.authorization_header</field>
<field name="value">1</field>
</record>
</odoo>
5 changes: 5 additions & 0 deletions auth_oauth_code_flow/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright 2026 KOBROS-TECH LTD <https://www.kobros-tech.com>
# License: AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)

from . import auth_oauth_provider
from . import res_users
18 changes: 18 additions & 0 deletions auth_oauth_code_flow/models/auth_oauth_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2026 KOBROS-TECH LTD <https://www.kobros-tech.com>
# License: AGPL-3.0 or later (http://www.gnu.org)

from odoo import fields, models


class AuthOauthProvider(models.Model):
_inherit = "auth.oauth.provider"

flow = fields.Selection(
selection_add=[
("access_token_code", "OAuth2 (Authorization Code Flow)"),
],
ondelete={"access_token_code": "set default"},
string="Auth Flow",
required=True,
default="access_token",
)
44 changes: 44 additions & 0 deletions auth_oauth_code_flow/models/res_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright 2026 KOBROS-TECH LTD <https://www.kobros-tech.com>
# License: AGPL-3.0 or later (http://www.gnu.org)

import logging

from odoo import api, models
from odoo.exceptions import AccessDenied

_logger = logging.getLogger(__name__)


class ResUsers(models.Model):
_inherit = "res.users"

@api.model
def auth_oauth(self, provider, params):
oauth_provider = self.env["auth.oauth.provider"].browse(provider)
# 1. Handle specific flow (OAuth2 Code Flow)
if oauth_provider.flow == "access_token_code":
# Perform the handshake (POST exchange)
access_token, id_token = self._auth_oauth_get_tokens_auth_code_flow(
oauth_provider, params
)
if not access_token:
_logger.error("No access_token in response.")
raise AccessDenied()
# 2. THE KEY:
# If it's GitHub (no id_token), bypass OIDC and use Odoo core
if not id_token:
params["access_token"] = access_token
# By returning super()
# we let base Odoo handle UserInfo validation
return super().auth_oauth(provider, params)
# 3. For everything else (OpenID)
# let the chain continue
return super().auth_oauth(provider, params)

@api.model
def _auth_oauth_validate(self, provider, access_token):
validation = super()._auth_oauth_validate(provider, access_token)
# If Odoo couldn't find an email, use the login/username
if not validation.get("email") and validation.get("login"):
validation["email"] = validation["login"]
return validation
3 changes: 3 additions & 0 deletions auth_oauth_code_flow/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
8 changes: 8 additions & 0 deletions auth_oauth_code_flow/readme/CONFIGURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Automatic System Parameters

Upon installation, this module automatically configures the following system parameter:

- auth_oauth.authorization_header: Set to 1.

Purpose: This forces Odoo to send the access_token in the HTTP Authorization Header (Bearer <token>) rather than as a query parameter in the URL.
GitHub and most modern providers have deprecated URL-based tokens for security reasons.
1 change: 1 addition & 0 deletions auth_oauth_code_flow/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Mohamed Alkobrosli \<<mohamed@kobros-tech.com>\>
23 changes: 23 additions & 0 deletions auth_oauth_code_flow/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
This module provides a high-security implementation of the OAuth2 Authorization Code Flow for Odoo 18. It serves as the essential bridge for modern identity providers (like GitHub) that have deprecated the insecure Implicit Flow.

## The Security Problem: Why Implicit Flow is Risky

Standard Odoo and many older modules rely on the OAuth2 Implicit Flow. In this flow, the access_token is sent directly to the user's browser in the URL fragment

- Leakage: Tokens are visible in browser history, server logs, and can be intercepted by malicious browser extensions.

- Exposure: Sensitive credentials "touch" the client side, increasing the attack surface.

## Authorization Code Flow

This module implements the Authorization Code Flow (access_token_code), which is the industry standard for secure web applications.

- Server-to-Server: The access_token is exchanged in a secure backend POST request between Odoo and the Provider.

- Invisible Tokens: Sensitive tokens never appear in the browser URL or history.

- PKCE Ready: Supports Proof Key for Code Exchange (PKCE) to prevent authorization code injection attacks.

Key Value for Developers

- Hybrid Support: Works in harmony with the OCA auth_oidc module. It acts as a pre-processor for the token handshake, allowing strict OIDC providers (Keycloak/Cognito) and standard OAuth2 providers (GitHub) to coexist on the same login page.
5 changes: 5 additions & 0 deletions auth_oauth_code_flow/readme/USUAGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- Install the module.
- In OAuth Providers, select the new flow: OAuth2 (Authorization Code Flow).
- Provide your Client Secret (now visible in the provider form).
- Add concerning scopes based on the provider.
- Map your Login to login or email in the Token Map for a seamless experience.
Loading
Loading