Skip to content

Commit cc1ae94

Browse files
committed
feat(auth_oidc): allow optional linking by email
1 parent 954b063 commit cc1ae94

8 files changed

Lines changed: 374 additions & 61 deletions

File tree

auth_oidc/README.rst

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
.. image:: https://odoo-community.org/readme-banner-image
2-
:target: https://odoo-community.org/get-involved?utm_source=readme
3-
:alt: Odoo Community Association
4-
51
=============================
62
Authentication OpenID Connect
73
=============================
@@ -17,7 +13,7 @@ Authentication OpenID Connect
1713
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
1814
:target: https://odoo-community.org/page/development-status
1915
:alt: Beta
20-
.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
2117
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
2218
:alt: License: AGPL-3
2319
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github
@@ -130,6 +126,26 @@ In Odoo, create a new Oauth Provider with the following parameters:
130126
- JWKS URL: The "jwks_uri" URL found in the OpenID Endpoint
131127
Configuration of your Keycloak realm
132128

129+
Auto-link existing users by email
130+
---------------------------------
131+
132+
By default, a user must already have ``oauth_uid`` set to be recognised
133+
on login. To automatically link **existing** Odoo users on their first
134+
OIDC login (matching by ``login = email`` from the token), enable the
135+
system parameter:
136+
137+
=========================== ========
138+
Key Value
139+
=========================== ========
140+
``auth_oidc.link_by_email`` ``True``
141+
=========================== ========
142+
143+
The link is performed only when **exactly one** active user matches the
144+
email. If zero or more than one match is found the request falls through
145+
to the standard behaviour (signup or ``AccessDenied``). Once linked, the
146+
user's ``oauth_uid`` is stored and subsequent logins follow the normal
147+
path.
148+
133149
.. |image| image:: https://raw.githubusercontent.com/OCA/server-auth/17.0/auth_oidc/static/description/oauth-microsoft_azure-api_permissions.png
134150
.. |image1| image:: https://raw.githubusercontent.com/OCA/server-auth/17.0/auth_oidc/static/description/oauth-microsoft_azure-optional_claims.png
135151
.. |image2| image:: https://raw.githubusercontent.com/OCA/server-auth/17.0/auth_oidc/static/description/odoo-azure_ad_multitenant.png
@@ -151,6 +167,12 @@ Known issues / Roadmap
151167
Changelog
152168
=========
153169

170+
17.0.1.3.0 2026-05-18
171+
---------------------
172+
173+
- Add optional auto-link of existing users by email on first OIDC login
174+
(``auth_oidc.link_by_email`` system parameter, disabled by default).
175+
154176
17.0.1.0.0 2024-03-20
155177
---------------------
156178

@@ -223,6 +245,7 @@ Contributors
223245
- Stéphane Bidoul <stephane.bidoul@acsone.eu>
224246
- David Jaen <david.jaen.revert@gmail.com>
225247
- Andreas Perhab <andreas.perhab@wt-io-it.at>
248+
- Jose Zambudio Bernabeu <zamberjo@gmail.com>
226249

227250
Maintainers
228251
-----------

auth_oidc/models/res_users.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
_logger = logging.getLogger(__name__)
1414

15+
_PARAM_LINK_BY_EMAIL = "auth_oidc.link_by_email"
16+
1517

1618
class ResUsers(models.Model):
1719
_inherit = "res.users"
@@ -80,3 +82,57 @@ def auth_oauth(self, provider, params):
8082
raise AccessDenied()
8183
# return user credentials
8284
return (self.env.cr.dbname, login, access_token)
85+
86+
@api.model
87+
def _is_oidc_link_by_email_enabled(self):
88+
return (
89+
self.env["ir.config_parameter"]
90+
.sudo()
91+
.get_param(_PARAM_LINK_BY_EMAIL, default="False")
92+
== "True"
93+
)
94+
95+
@api.model
96+
def _oidc_link_user_by_email(self, provider, oauth_uid, email, access_token):
97+
user = self.search([("login", "=", email)], limit=1)
98+
if not user:
99+
_logger.warning(
100+
"OIDC link by email: found %d user(s) with login=%s, skipping.",
101+
len(user),
102+
email,
103+
)
104+
return None
105+
user.write(
106+
{
107+
"oauth_provider_id": provider,
108+
"oauth_uid": oauth_uid,
109+
"oauth_access_token": access_token,
110+
}
111+
)
112+
_logger.info(
113+
"OIDC link by email: user '%s' linked to provider %s with oauth_uid=%s.",
114+
user.login,
115+
provider,
116+
oauth_uid,
117+
)
118+
return user
119+
120+
@api.model
121+
def _auth_oauth_signin(self, provider, validation, params):
122+
oauth_uid = validation["user_id"]
123+
already_linked = self.search(
124+
[
125+
("oauth_uid", "=", oauth_uid),
126+
("oauth_provider_id", "=", provider),
127+
],
128+
limit=1,
129+
)
130+
if not already_linked and self._is_oidc_link_by_email_enabled():
131+
email = validation.get("email")
132+
if email:
133+
linked_user = self._oidc_link_user_by_email(
134+
provider, oauth_uid, email, params["access_token"]
135+
)
136+
if linked_user:
137+
return linked_user.login
138+
return super()._auth_oauth_signin(provider, validation, params)

auth_oidc/readme/CONFIGURE.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,19 @@ In Odoo, create a new Oauth Provider with the following parameters:
7474
Configuration of your Keycloak realm
7575
- JWKS URL: The "jwks_uri" URL found in the OpenID Endpoint
7676
Configuration of your Keycloak realm
77+
78+
## Auto-link existing users by email
79+
80+
By default, a user must already have `oauth_uid` set to be recognised on
81+
login. To automatically link **existing** Odoo users on their first OIDC
82+
login (matching by `login = email` from the token), enable the system
83+
parameter:
84+
85+
| Key | Value |
86+
|-----|-------|
87+
| `auth_oidc.link_by_email` | `True` |
88+
89+
The link is performed only when **exactly one** active user matches the
90+
email. If zero or more than one match is found the request falls through
91+
to the standard behaviour (signup or `AccessDenied`). Once linked, the
92+
user's `oauth_uid` is stored and subsequent logins follow the normal path.

auth_oidc/readme/CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
- Stéphane Bidoul \<<stephane.bidoul@acsone.eu>\>
33
- David Jaen \<<david.jaen.revert@gmail.com>\>
44
- Andreas Perhab \<<andreas.perhab@wt-io-it.at>\>
5+
- Jose Zambudio Bernabeu \<<zamberjo@gmail.com>\>

auth_oidc/readme/HISTORY.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 17.0.1.3.0 2026-05-18
2+
3+
- Add optional auto-link of existing users by email on first OIDC login
4+
(`auth_oidc.link_by_email` system parameter, disabled by default).
5+
16
## 17.0.1.0.0 2024-03-20
27

38
- Odoo 17 migration

0 commit comments

Comments
 (0)