-
Notifications
You must be signed in to change notification settings - Fork 258
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
Consumer.backchannel_logout and handling state #853
Comments
The tests seem to suggest that everything is working... I personally do not have any experience with implementing a logout. Could you please provide a MWE of the failing code? |
Sure ! Here is a MWE of the failing code, as a Since testing this logic involves first login the user in and then processing a backchannel logout request I decided to manually fill the I also choose to mock To run this sample, please first install from unittest import TestCase
from unittest.mock import MagicMock, patch
from jwt import JWT
from oic.oic.consumer import Consumer
from oic.utils.authn.client import CLIENT_AUTHN_METHOD
from oic.utils.session_backend import DictSessionBackend
class Issue853TestCase(TestCase):
@classmethod
def setUpClass(cls) -> None:
# Persistent session backend
cls.session_backend = DictSessionBackend()
# real JWT payload from a captured keycloak backchannel-logout request
cls.body = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkRVl0UnRmVHpBbXpNZGxlWU5aSWhvQnI3bFNieHBQU3Z4N3Y1eWVCUlU4In0.eyJpYXQiOjE2ODAwOTA5NDUsImp0aSI6ImIzMGFjOTEyLWRhYjctNDkzZC04MGQxLTM2NWU0NmEwOWUyNyIsImlzcyI6Imh0dHA6Ly9rZXljbG9hay5sb2NhbDo4MDgwL2F1dGgvcmVhbG1zL0RlbW8iLCJhdWQiOiJmdWxsIiwic3ViIjoiYWJlYzcwZjgtYTJhMC00YmYwLTg2NjUtYWI5Mzg3YTRkZTAyIiwidHlwIjoiTG9nb3V0Iiwic2lkIjoiNDRlNTliOTYtYTVhMy00NWEwLWI0ZWYtNzY3NzdmNGI3YzI1IiwiZXZlbnRzIjp7Imh0dHA6Ly9zY2hlbWFzLm9wZW5pZC5uZXQvZXZlbnQvYmFja2NoYW5uZWwtbG9nb3V0Ijp7fX19.D4XFSfVp8_T4TwDWLvHx--rs9-aLS8ZbZNPMNWIanoil9gc3N8UczsHJqqTQVQU7BNDQKeMVZQn47I3A1gW9_5WhQa5Si5xgKUmBTs-BoUjLo9Avr7lqAc7zOcGD4ehVLX6gv3PxAlD04snqjEBBW2PZYOZ04u0E--Ssbqd_LAha7ArbgMDG8dIBmJUHvJNMhWERX3QKw5cc3TXcY1TbZ-xDdkBf28DJ19ryXMHn0PybH927ZsDGX-2vxltDFRbIhotPXfoAbfZl8_TA84tn58zKcWKNd5aMtZ5Mu0D_SHPcNNpbYR3WzMlQZ6E0_8io5_buUBehaKZTryL30rK56w"
def test_issue853(self):
consumer_config = {
# "debug": True,
"response_type": "code",
}
client_config = {
"client_id": "test",
"client_authn_method": CLIENT_AUTHN_METHOD,
}
consumer = Consumer(
consumer_config=consumer_config,
client_config=client_config,
session_db=self.session_backend,
)
with patch("oic.oic.consumer.BackChannelLogoutRequest") as mock:
# Load jwt as python dict
decoded = {"logout_token": JWT().decode(self.body, do_verify=False)}
# Simulate previously made login : our session id is 0000
real_sid = "0000"
self.session_backend.update(
real_sid, "smid", decoded["logout_token"]["sid"]
)
self.session_backend.update(real_sid, "sub", decoded["logout_token"]["sub"])
self.session_backend.update(
real_sid, "issuer", decoded["logout_token"]["iss"]
)
# Mock 'BackChannelLogoutRequest' as we don't want to check signature and stuff
mocked_logout_request = MagicMock()
mocked_logout_request.__getitem__.side_effect = decoded.__getitem__
mock.return_value = mocked_logout_request
# Uncomment the following line to have the test pass :
# consumer.sso_db = consumer.sdb
sid = consumer.backchannel_logout(request_args={"logout_token": self.body})
self.assertIsNotNone(sid)
self.assertEqual(sid, real_sid) |
OK, not sure what to make out of this... The split between What flow are you using in your consumer? Could you verify that the logout is working correctly if you use |
Ok, I think I might get what is going on. I start from a fresh I could try to restore an existing consumer, however to call Maybe I should process myself the JWT first, call |
I am not sure how one is supposed to handle Logout JWT from an Authorization server using this library. On one side, in an authorization code flow, the On the other side, when I receive a Logout JWT I need to find back the consumer instance since the session details where stored in Howevere I don't have any to find back the I could rely on the fact that my Keycloak server sends a But it seems that this behaviour is in the grey zone of the spec. |
Well, the The |
Well, if we receive a Logout JWT with However for a Logout JWT with
Would you be open to a PR that uses
|
Hm, not sure if I completely follow... If that is what you were suggesting, than please go ahead. If not, than I might need more info :) |
Not really, I was thinking about patching this so that the client is either saved using I'll start a quick MR to show you. EDIT : Here is a draft PR that shows what I'd like to do. |
OK, sounds reasonable. Please move the kwarg to the end as not to change the order for existing uses. |
Closed via #854. |
Hi there,
I am working on an integration of pyoidc with Django.
While writing a backchannel-logout view, I struggled to have the Consumer find the session ID through my session back-end.
My consumer is initialized like this :
Which sets
Consumer.sdb
tomy_cache_backend
.However it seems that the implementation of
Consumer.backchannel_logout
usesConsumer.sso_db
instead ofConsumer.sdb
.This makes the consumer unable to find the session id since it's store in sdb.
I tried initializing my consumer like this :
But then it breaks the alredy working login mechanism.
I ended up implementing backchannel-logout by setting
Consumer.sso_db
toConsumer.sdb
just for this feature, like this :I found a test case that seems related : https://github.com/CZ-NIC/pyoidc/blob/f6c590cd8d5834f7e2a2d746ded934549e1fd5f8/tests/test_oic_consumer_logout.py
Could you please explain what are the use-cases for those two
SessionBackend
?The text was updated successfully, but these errors were encountered: