Skip to content

Commit 2efdb3a

Browse files
committed
feat(auth_oauth_link_by_email): add new module to allow linking OAuth accounts by email
1 parent 954b063 commit 2efdb3a

16 files changed

Lines changed: 870 additions & 0 deletions
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
====================================
2+
OAuth - Link existing users by email
3+
====================================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:7b1f947b629d3f0ea59aca3c89d6656b6a1e8ae5c4378ec0650e9ca03cc54e9f
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github
20+
:target: https://github.com/OCA/server-auth/tree/17.0/auth_oauth_link_by_email
21+
:alt: OCA/server-auth
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/server-auth-17-0/server-auth-17-0-auth_oauth_link_by_email
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-auth&target_branch=17.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
When installed, this module automatically links existing Odoo users to
32+
an OAuth provider on their first login, by matching the email address
33+
from the OAuth token with the user's login (which is their email in
34+
Odoo).
35+
36+
This is useful when users already exist in Odoo (created manually or
37+
imported) and you want them to authenticate via an OAuth provider
38+
without having to recreate their accounts.
39+
40+
**Table of contents**
41+
42+
.. contents::
43+
:local:
44+
45+
Installation
46+
============
47+
48+
No additional installation steps are required beyond installing the
49+
module itself. It depends only on the standard ``auth_oauth`` module.
50+
51+
Configuration
52+
=============
53+
54+
No configuration is required. The auto-link feature is active as soon as
55+
the module is installed.
56+
57+
How it works
58+
------------
59+
60+
When a user attempts to log in through an OAuth provider and no Odoo
61+
user is found with a matching ``oauth_uid`` + ``oauth_provider_id``,
62+
this module will:
63+
64+
1. Extract the ``email`` claim from the OAuth token validation response.
65+
2. Search for an active Odoo user whose ``login`` matches that email.
66+
3. If found, write the ``oauth_provider_id``, ``oauth_uid``, and
67+
``oauth_access_token`` onto that user record and return their login.
68+
4. Subsequent logins will resolve directly via ``oauth_uid`` as usual.
69+
70+
If no matching user is found, or the email claim is absent, the standard
71+
``auth_oauth`` flow continues (raising ``AccessDenied`` for unknown
72+
accounts).
73+
74+
Changelog
75+
=========
76+
77+
17.0.1.0.0 (2026)
78+
-----------------
79+
80+
- Initial release. Auto-links existing Odoo users to OAuth providers by
81+
email on first login. The feature is active as soon as the module is
82+
installed.
83+
84+
Bug Tracker
85+
===========
86+
87+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-auth/issues>`_.
88+
In case of trouble, please check there if your issue has already been reported.
89+
If you spotted it first, help us to smash it by providing a detailed and welcomed
90+
`feedback <https://github.com/OCA/server-auth/issues/new?body=module:%20auth_oauth_link_by_email%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
91+
92+
Do not contact contributors directly about support or help with technical issues.
93+
94+
Credits
95+
=======
96+
97+
Authors
98+
-------
99+
100+
* Heligrafics Fotogrametria S.L.
101+
102+
Contributors
103+
------------
104+
105+
- `Heligrafics <https://www.heligrafics.net>`__
106+
107+
- Jose Zambudio Bernabeu <zamberjo@gmail.com>
108+
109+
Maintainers
110+
-----------
111+
112+
This module is maintained by the OCA.
113+
114+
.. image:: https://odoo-community.org/logo.png
115+
:alt: Odoo Community Association
116+
:target: https://odoo-community.org
117+
118+
OCA, or the Odoo Community Association, is a nonprofit organization whose
119+
mission is to support the collaborative development of Odoo features and
120+
promote its widespread use.
121+
122+
This module is part of the `OCA/server-auth <https://github.com/OCA/server-auth/tree/17.0/auth_oauth_link_by_email>`_ project on GitHub.
123+
124+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2026 Heligrafics <https://www.heligrafics.net>
2+
# License: AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
from . import models
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright 2026 Heligrafics <https://www.heligrafics.net>
2+
# License: AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
{
5+
"name": "OAuth - Link existing users by email",
6+
"version": "17.0.1.0.0",
7+
"license": "AGPL-3",
8+
"author": "Heligrafics Fotogrametria S.L., Odoo Community Association (OCA)",
9+
"website": "https://github.com/OCA/server-auth",
10+
"summary": (
11+
"Automatically link existing Odoo users to an OAuth provider "
12+
"on first login by matching their email address."
13+
),
14+
"depends": ["auth_oauth"],
15+
"installable": True,
16+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Translation of Odoo Server.
2+
# This file contains the translation of the following modules:
3+
# * auth_oauth_link_by_email
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Odoo Server 17.0\n"
8+
"Report-Msgid-Bugs-To: \n"
9+
"Last-Translator: \n"
10+
"Language-Team: \n"
11+
"MIME-Version: 1.0\n"
12+
"Content-Type: text/plain; charset=UTF-8\n"
13+
"Content-Transfer-Encoding: \n"
14+
"Plural-Forms: \n"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright 2026 Heligrafics <https://www.heligrafics.net>
2+
# License: AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
from . import res_users
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Copyright 2026 Heligrafics <https://www.heligrafics.net>
2+
# License: AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
3+
4+
import logging
5+
6+
from odoo import api, models
7+
8+
_logger = logging.getLogger(__name__)
9+
10+
11+
class ResUsers(models.Model):
12+
_inherit = "res.users"
13+
14+
@api.model
15+
def _oauth_link_user_by_email(self, provider, oauth_uid, email, access_token):
16+
user = self.search([("login", "=", email)], limit=1)
17+
if not user:
18+
_logger.warning(
19+
"OAuth link by email: no user found with login=%s, skipping.",
20+
email,
21+
)
22+
return None
23+
user.write(
24+
{
25+
"oauth_provider_id": provider,
26+
"oauth_uid": oauth_uid,
27+
"oauth_access_token": access_token,
28+
}
29+
)
30+
_logger.info(
31+
"OAuth link by email: user '%s' linked to provider %s with oauth_uid=%s.",
32+
user.login,
33+
provider,
34+
oauth_uid,
35+
)
36+
return user
37+
38+
@api.model
39+
def _auth_oauth_signin(self, provider, validation, params):
40+
oauth_uid = validation["user_id"]
41+
already_linked = self.search(
42+
[
43+
("oauth_uid", "=", oauth_uid),
44+
("oauth_provider_id", "=", provider),
45+
],
46+
limit=1,
47+
)
48+
if not already_linked:
49+
email = validation.get("email")
50+
if email:
51+
linked_user = self._oauth_link_user_by_email(
52+
provider, oauth_uid, email, params["access_token"]
53+
)
54+
if linked_user:
55+
return linked_user.login
56+
return super()._auth_oauth_signin(provider, validation, params)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[build-system]
2+
requires = ["whool"]
3+
build-backend = "whool.buildapi"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
No configuration is required. The auto-link feature is active as soon as the
2+
module is installed.
3+
4+
## How it works
5+
6+
When a user attempts to log in through an OAuth provider and no Odoo user is
7+
found with a matching ``oauth_uid`` + ``oauth_provider_id``, this module will:
8+
9+
1. Extract the ``email`` claim from the OAuth token validation response.
10+
2. Search for an active Odoo user whose ``login`` matches that email.
11+
3. If found, write the ``oauth_provider_id``, ``oauth_uid``, and
12+
``oauth_access_token`` onto that user record and return their login.
13+
4. Subsequent logins will resolve directly via ``oauth_uid`` as usual.
14+
15+
If no matching user is found, or the email claim is absent, the standard
16+
``auth_oauth`` flow continues (raising ``AccessDenied`` for unknown accounts).
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
* [Heligrafics](https://www.heligrafics.net)
2+
- Jose Zambudio Bernabeu \<<zamberjo@gmail.com>\>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
When installed, this module automatically links existing Odoo users to an
2+
OAuth provider on their first login, by matching the email address from the
3+
OAuth token with the user's login (which is their email in Odoo).
4+
5+
This is useful when users already exist in Odoo (created manually or imported)
6+
and you want them to authenticate via an OAuth provider without having to
7+
recreate their accounts.

0 commit comments

Comments
 (0)