Skip to content

Commit

Permalink
Fix OIDC backchannel logout implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Encotric committed Mar 17, 2024
1 parent 9947c3e commit 1c92e02
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 14 deletions.
2 changes: 1 addition & 1 deletion core/admin/mailu/sso/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def logout():
@sso.route('/backchannel-logout', methods=['POST'])
def backchannel_logout():
if utils.oic_client.is_enabled():
utils.oic_client.backchannel_logout(flask.request, flask.request.args)
utils.oic_client.backchannel_logout(flask.request.form)
return {'code': 200, 'message': 'Backchannel logout successful.'}, 200
return flask.abort(404)

Expand Down
39 changes: 26 additions & 13 deletions core/admin/mailu/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from oic.utils.settings import OicClientSettings
from oic import rndstr
from oic.exception import MessageException, NotForMe
from oic.oauth2.message import ROPCAccessTokenRequest, AccessTokenResponse
from oic.oic.message import AuthorizationResponse, RegistrationResponse, EndSessionRequest
from oic.oic.message import AuthorizationResponse, RegistrationResponse, EndSessionRequest, BackChannelLogoutRequest
from oic.oauth2.grant import Token
from jwkest.jws import alg2keytype

Expand Down Expand Up @@ -140,7 +141,7 @@ def init_app(self, app):
proxy = PrefixMiddleware()

class OicClient:
"Redirects users to OpenID Provider if configured"
"Redirects user to OpenID Provider if configured"

def __init__(self):
self.app = None
Expand Down Expand Up @@ -241,7 +242,7 @@ def refresh_token(self, token):
"refresh_token": token['refresh_token']
}
response = self.client.do_access_token_refresh(request_args=args, token=Token(token))
if 'access_token' in response:
if isinstance(response, AccessTokenResponse):
return response
else:
return None
Expand All @@ -264,11 +265,24 @@ def logout(self, id_token):
uri, body, h_args, cis = self.client.uri_and_body(EndSessionRequest, method="GET", request_args=args, cis=request)
return uri

def backchannel_logout(self, req, args):
sub = self.client.backchannel_logout(req, args, self.app)
if sub != None and sub != '':
MailuSessionExtension.prune_sessions(None, None, self.app, sub)
def backchannel_logout(self, body):
req = BackChannelLogoutRequest().from_dict(body)

kwargs = {"aud": self.client.client_id, "iss": self.client.issuer, "keyjar": self.client.keyjar}

try:
req.verify(**kwargs)
except (MessageException, ValueError, NotForMe) as err:
self.app.logger.error(err)
return False

sub = req["logout_token"]["sub"]

if sub is not None and sub != '':
MailuSessionExtension.prune_sessions(None, None, self.app, sub)

return True

def is_enabled(self):
return self.app is not None and self.app.config['OIDC_ENABLED']

Expand Down Expand Up @@ -615,12 +629,11 @@ def prune_sessions(uid=None, keep=None, app=None,sub=None):
count = 0
for key in app.session_store.list(prefix):
if key not in keep and not key.startswith(b'token-'):
if sub != None:
if sessid := app.session_store.get(key):
session = MailuSession(sessid, app)
if session.get('openid_sub', '') == sub:
app.session_store.delete(key)
count += 1
if sub is not None:
session = MailuSession(key, app)
if 'openid_sub' in session and session['openid_sub'] == sub:
app.session_store.delete(key)
count += 1
else:
app.session_store.delete(key)
count += 1
Expand Down

0 comments on commit 1c92e02

Please sign in to comment.