Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to skip the logout confirmation in the auth provider #708

Open
wants to merge 1 commit into
base: 14.0
Choose a base branch
from
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
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
Loading