Skip to content

Commit

Permalink
Add support to skip the logout confirmation in the auth provider
Browse files Browse the repository at this point in the history
Add field to oauth provider to toggle skip logout confirmation

Added tests for the skip confirmation feature

Applied auto format changes

Removed unused line

Reduced long line
  • Loading branch information
wluyima committed Oct 14, 2024
1 parent c6a4462 commit 2db2173
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 1 deletion.
2 changes: 2 additions & 0 deletions auth_oidc/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ def logout(self, redirect="/web/login"):
params = parse_qs(components.query)
params["client_id"] = provider.client_id
params["post_logout_redirect_uri"] = redirect_url
if provider.skip_logout_confirmation and user.oauth_id_token:
params["id_token_hint"] = user.oauth_id_token
logout_url = components._replace(query=url_encode(params)).geturl()
return super().logout(redirect=logout_url)
# User has no account with any provider or no logout URL is configured for the provider
Expand Down
6 changes: 6 additions & 0 deletions auth_oidc/models/auth_oauth_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ class AuthOauthProvider(models.Model):
"in the client, should be the value of end_session_endpoint specified by "
"the authorization provider.",
)
skip_logout_confirmation = fields.Boolean(
default=False,
string="Skip Logout Confirmation",
help="If set to true, the logout confirmation is skipped in the "
"authorization provider.",
)

@tools.ormcache("self.jwks_uri", "kid")
def _get_keys(self, kid):
Expand Down
9 changes: 8 additions & 1 deletion auth_oidc/models/res_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import requests

from odoo import api, models
from odoo import api, fields, models
from odoo.exceptions import AccessDenied
from odoo.http import request

Expand All @@ -16,6 +16,8 @@
class ResUsers(models.Model):
_inherit = "res.users"

oauth_id_token = fields.Char(string="OAuth Id Token", readonly=True, copy=False)

def _auth_oauth_get_tokens_implicit_flow(self, oauth_provider, params):
# https://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthResponse
return params.get("access_token"), params.get("id_token")
Expand Down Expand Up @@ -74,7 +76,12 @@ def auth_oauth(self, provider, params):
raise AccessDenied()
# retrieve and sign in user
params["access_token"] = access_token
params["id_token"] = id_token
login = self._auth_oauth_signin(provider, validation, params)
oauth_user = self.search(
[("login", "=", login), ("oauth_access_token", "=", access_token)]
)
oauth_user.write({"oauth_id_token": params["id_token"]})
if not login:
raise AccessDenied()
# return user credentials
Expand Down
55 changes: 55 additions & 0 deletions auth_oidc/tests/test_auth_oidc_logout.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,58 @@ def test_oidc_logout_with_absolute_redirect_url(self):
actual_params = dict(parse_qsl(actual_components.query))
self.assertEqual(CLIENT_ID, actual_params["client_id"])
self.assertEqual(BASE_URL, actual_params["post_logout_redirect_uri"])

def test_oidc_logout_skip_confirmation(self):
"""Test that oidc logout skips confirmation"""
id_token = "test-id-token"
self._set_test_oidc_logout_url(urljoin(OIDC_BASE_LOGOUT_URL, OIDC_LOGOUT_PATH))
self.provider.write({"skip_logout_confirmation": True})
user = self._prepare_login_test_user(self.provider)
user.write({"oauth_id_token": id_token})
with create_request(self.env, user.id, self.mock_logout_user):
resp = OpenIDLogout().logout()
self.assertTrue(resp.location.startswith(OIDC_BASE_LOGOUT_URL))
actual_components = urlparse(resp.location)
self.assertEqual(OIDC_LOGOUT_PATH, actual_components.path)
actual_params = dict(parse_qsl(actual_components.query))
self.assertEqual(CLIENT_ID, actual_params["client_id"])
self.assertEqual(id_token, actual_params["id_token_hint"])
self.assertEqual(
urljoin(BASE_URL, LOGIN_PATH), actual_params["post_logout_redirect_uri"]
)

def test_oidc_logout_not_skip_confirmation_if_no_id_token(self):
"""Test that oidc logout does not skip confirmation if user has no oauth_id_token"""
self._set_test_oidc_logout_url(urljoin(OIDC_BASE_LOGOUT_URL, OIDC_LOGOUT_PATH))
self.provider.write({"skip_logout_confirmation": True})
user = self._prepare_login_test_user(self.provider)
with create_request(self.env, user.id, self.mock_logout_user):
resp = OpenIDLogout().logout()
self.assertTrue(resp.location.startswith(OIDC_BASE_LOGOUT_URL))
actual_components = urlparse(resp.location)
self.assertEqual(OIDC_LOGOUT_PATH, actual_components.path)
actual_params = dict(parse_qsl(actual_components.query))
self.assertEqual(CLIENT_ID, actual_params["client_id"])
self.assertIsNone(actual_params.get("id_token_hint"))
self.assertEqual(
urljoin(BASE_URL, LOGIN_PATH), actual_params["post_logout_redirect_uri"]
)

def test_oidc_logout_not_skip_confirmation_if_not_enabled(self):
"""Test that oidc logout skips confirmation"""
id_token = "test-id-token"
self._set_test_oidc_logout_url(urljoin(OIDC_BASE_LOGOUT_URL, OIDC_LOGOUT_PATH))
self.provider.write({"skip_logout_confirmation": False})
user = self._prepare_login_test_user(self.provider)
user.write({"oauth_id_token": id_token})
with create_request(self.env, user.id, self.mock_logout_user):
resp = OpenIDLogout().logout()
self.assertTrue(resp.location.startswith(OIDC_BASE_LOGOUT_URL))
actual_components = urlparse(resp.location)
self.assertEqual(OIDC_LOGOUT_PATH, actual_components.path)
actual_params = dict(parse_qsl(actual_components.query))
self.assertEqual(CLIENT_ID, actual_params["client_id"])
self.assertIsNone(actual_params.get("id_token_hint"))
self.assertEqual(
urljoin(BASE_URL, LOGIN_PATH), actual_params["post_logout_redirect_uri"]
)
1 change: 1 addition & 0 deletions auth_oidc/views/auth_oauth_provider.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<field name="token_endpoint" />
<field name="jwks_uri" />
<field name="end_session_endpoint" />
<field name="skip_logout_confirmation" />
</field>
</field>
</record>
Expand Down

0 comments on commit 2db2173

Please sign in to comment.