bleumink / streamlit-keycloak

User authentication and single sign-on in your Streamlit app using Keycloak
MIT License
59 stars 11 forks source link

Server side verification with Keycloak needed #27

Closed MatsBjerin closed 4 months ago

MatsBjerin commented 11 months ago

If I understand the process correctly, all communication with Keycloak is performed by the typescript code on the client side., Thus, the token and user details received by the server side must be verified against the keycloak realm cert and only then can they be trusted and used for further access. Any additional details about groups or roles assigned to the user must also be collected from the keycloak server.

If someone has a good verification algorithm implemented with the necessary call to the server it would be a useful addition. This library looks very helpful in this respect though I see no direct verification method. But the user info endpoint might be one way to get the info about the user: https://pypi.org/project/python-keycloak/

/Mats

CHerSun commented 11 months ago

all the info from auth is passed via JWT token, which you can access on Streamlit python side. If Keycloak is configured to add user info - you'll have JSON populated with roles along with the JWT token. Otherwise you can just parse JWT token to get all the same info.

MatsBjerin commented 11 months ago

Thanks! Yes, the point I wish to make is that the values received cannot be trusted. They must be verified using the public key for the same realm from the keycloak server.

/Mats

Skickat från Outlook för Androidhttps://aka.ms/AAb9ysg


From: Alexander Chernyshev @.> Sent: Friday, November 3, 2023 7:22:44 PM To: bleumink/streamlit-keycloak @.> Cc: Mats Bjerin @.>; Author @.> Subject: Re: [bleumink/streamlit-keycloak] Server side verification with Keycloak needed (Issue #27)

all the info from auth is passed via JWT token, which you can access on Streamlit python side. If Keycloak is configured to add user info - you'll have JSON populated with roles along with the JWT token. Otherwise you can just parse JWT token to get all the same info.

— Reply to this email directly, view it on GitHubhttps://github.com/bleumink/streamlit-keycloak/issues/27#issuecomment-1792930218, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ATZHR5AX5ZUCHQ3R7CYJJFTYCUY7JAVCNFSM6AAAAAA64S3766VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTOOJSHEZTAMRRHA. You are receiving this because you authored the thread.Message ID: @.***>

CHerSun commented 11 months ago

Could you elaborate what exactly you are trying to do or protect from? Client from your frontend (signed and encrypted?) is rerouted to your keycloak web-page, which also should be protected with your signed certificate. The process is quite secure, as I know. But you can always use the same token to recheck again, for example through fixed IP (or just your controlled DNS) or another network.

MatsBjerin commented 11 months ago

Yes, I need to use the token and verify I get the same results on the server side as the user obtained on the browser client side. Since the server side could be tricked into accepting data from the web browser that has a fake token or a valid token but for another user in the user details section.

This is simply because the client side data is open to modification or replacement. While the server side cannot be manipulated.

This is in fact the whole point. That the server side code in python cannot trust the data until it has been checked using the certificate in the bearer token.

Right now there is no such verification in the streamlit-keycloak module built in, as it is all type script code for the client side and just a "template" class that has its parameters filled in by the client side code.

Skickat från Outlook för Androidhttps://aka.ms/AAb9ysg


From: Alexander Chernyshev @.> Sent: Friday, November 3, 2023 7:39:09 PM To: bleumink/streamlit-keycloak @.> Cc: Mats Bjerin @.>; Author @.> Subject: Re: [bleumink/streamlit-keycloak] Server side verification with Keycloak needed (Issue #27)

Could you elaborate what exactly you are trying to do or protect from? Client from your frontend (signed and encrypted?) is rerouted to your keycloak web-page, which also should be protected with your signed certificate. The process is quite secure, as I know. But you can always use the same token to recheck again, for example through fixed IP or another network.

— Reply to this email directly, view it on GitHubhttps://github.com/bleumink/streamlit-keycloak/issues/27#issuecomment-1792952033, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ATZHR5CJRPVRVN3LDFMXANDYCU243AVCNFSM6AAAAAA64S3766VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTOOJSHE2TEMBTGM. You are receiving this because you authored the thread.Message ID: @.***>

CHerSun commented 11 months ago

Well, I didn't do it really, I'm running the service in internal perimeter with somewhat secure setup.

Examples from python-keycloak look to be simple enough. To me it looks like either this:

# Get Access Token With Code
access_token = keycloak_openid.token(
    grant_type='authorization_code',
    code='the_code_you_get_from_auth_url_callback',
    redirect_uri="your_call_back_url")

or this

# Get Userinfo
userinfo = keycloak_openid.userinfo(token['access_token'])

# Refresh token
token = keycloak_openid.refresh_token(token['refresh_token'])

should do what you want. Just rerequesting details through server-side using the same code through explicitly secure connection. It should either return some kind of error, if code is unknown to SSO, or it should return a safe-to-use result with no further verification required (as we'd trust our internal connection). Might need some work with session_state to not do that on each page redraw.

MatsBjerin commented 11 months ago

That's perfect!! Many warm thanks for solving this also. The module is indeed great so with this verification it is also really secure.

Skickat från Outlook för Androidhttps://aka.ms/AAb9ysg


From: Alexander Chernyshev @.> Sent: Friday, November 3, 2023 8:22:38 PM To: bleumink/streamlit-keycloak @.> Cc: Mats Bjerin @.>; Author @.> Subject: Re: [bleumink/streamlit-keycloak] Server side verification with Keycloak needed (Issue #27)

Well, I didn't do it really, using the service in internal perimeter with somewhat secure setup.

Examples from python-keycloak look to be simple enough. To me it looks like either this:

Get Access Token With Code

access_token = keycloak_openid.token( grant_type='authorization_code', code='the_code_you_get_from_auth_url_callback', redirect_uri="your_call_back_url")

or this

Get Userinfo

userinfo = keycloak_openid.userinfo(token['access_token'])

Refresh token

token = keycloak_openid.refresh_token(token['refresh_token'])

should do what you want. Just rerequesting details through server-side using the same code through explicitly secure connection. It should either return some kind of error, if code is unknown to SSO, or it should return a safe-to-use result with no further verification required (as we'd trust our internal connection). Might need some work with session_state to not do that on each page redraw.

— Reply to this email directly, view it on GitHubhttps://github.com/bleumink/streamlit-keycloak/issues/27#issuecomment-1792979742, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ATZHR5FMSWHROUJ5UAJIBJDYCU775AVCNFSM6AAAAAA64S3766VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTOOJSHE3TSNZUGI. You are receiving this because you authored the thread.Message ID: @.***>

balazsrewe commented 4 months ago

I think something like this should be done:

        self.cached_key= self.keycloak_openid.public_key()
        ...
        options = {"key": self.cached_key, "verify_signature": True,"verify_aud": True, "verify_exp": True}
        result=self.keycloak_openid.decode_token(token, options)

You want to reload the cached key from time to time because it will be rotated on the auth server.

MatsBjerin commented 4 months ago

Nice one! Thanks @balazsrewe ! :-)

MatsBjerin commented 4 months ago

I feel good about the solutions suggested. I decided to close this thread. Thanks all who contributed! /Mats