-
-
Notifications
You must be signed in to change notification settings - Fork 280
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
Implementation of a functionality to integrate KeyCloak IDP provider #4107
Comments
After looking at the available libraries ready available in open-source, written in python/typescript and available in Debian/Ubuntu i consider that a very good option would be to base the client implementation on angular-oauth2-oidc and to implement a simple backend validator of the tokens based on requests-oauthlib that uses python3-oauthlib An advantage of angular-oauth2-oidc is also that it is openid certified so it would probably guarantee significant compatibility: https://openid.net/developers/certified-openid-connect-implementations; In particular with such a choice we could keep the backend implementation very small reducing both the footprint and the attack surface. The code in fact could be something like: import requests
from oauthlib.oauth2 import BackendApplicationClient
from requests.auth import HTTPBasicAuth
from requests_oauthlib import OAuth2Session
def validate_oauth_token(introspection_url, client_id, client_secret, token):
# Set up the client credentials
client = BackendApplicationClient(client_id=client_id)
oauth = OAuth2Session(client=client)
# Prepare the request to the introspection endpoint
auth = HTTPBasicAuth(client_id, client_secret)
introspection_response = oauth.post(
introspection_url,
data={'token': token},
auth=auth
)
if introspection_response.status_code == 200:
token_info = introspection_response.json()
return token_info
else:
# Handle the error or invalid response
introspection_response.raise_for_status()
introspection_url = 'https://authorization-server.com/oauth/introspect'
client_id = 'your-client-id'
client_secret = 'your-client-secret'
token = 'the-token-to-validate'
token_info = validate_oauth_token(introspection_url, client_id, client_secret, token)
print(token_info) |
i deeply agree, creating a common interface to any IAM software (keycloak, wso2) is a valuable solution. |
Now there are many open source projects on both client and server sides for integration with identity and access management, we at CNR having projects developed in Angular mainly use angular-oauth-oidc-client, while on the server side having the majority of projects in java with spring-boot we use an official spring plugin, in conclusion it is not advisable to write custom code or even use any middelware that would compromise the authorization part, but just find the plugin best suited to the GlobaLeaks architecture. |
Thank you @rglauco and @mspasiano , for your your valuable feedback. A plugin does not exist in python and specifically for twisted, but based on the very standard and complete python3-oauthlib library we could easily verify the tokens that we receive at the first time users provide them and automatically upon a certain timeout so to invalidate the tokens upon .expiration. The code i drafted above is an example of how to handle this simple part. |
I'm going to remodel this ticket to handle all at once OATUH2 and OpenID connect because actually i think it will be more simple to keep the discussions unified and target an implementation that eventually could support both a simple OAUTH2 integration or a full OpenID connect implementation. Regarding the server validation of the tokens i think it could be furtherly made more efficient if we could periodically fetch the signature keys from the OpenID connect server on the In this case the implementation the backend implementation can be ultimately simplified (as it would not require anyopenid connect library on the backend) but just the jose library (that we are already including due to lets'encrypt) and the code can be simplified to something like: import json
from twisted.internet import reactor, defer
from twisted.web.client import Agent, readBody
from twisted.web.http_headers import Headers
from jose import jwt, jwk
from jose.utils import base64url_decode
from twisted.internet.defer import inlineCallbacks, returnValue
from twisted.web.http_headers import Headers
# Define the Keycloak JWKS URL
jwks_url = 'https://<keycloak-domain>/auth/realms/<realm-name>/protocol/openid-connect/certs'
# Your JWT token to verify
token = '<your-jwt-token>'
def fetch_jwks(url):
agent = Agent(reactor)
d = agent.request(
b'GET',
url.encode('utf-8'),
Headers({'User-Agent': ['Twisted Web Client']}),
None)
d.addCallback(readBody)
return d
@inlineCallbacks
def verify_jwt(token):
# Fetch the JWKS
jwks_response = yield fetch_jwks(jwks_url)
jwks = json.loads(jwks_response)
# Decode the token header to get the key ID
headers = jwt.get_unverified_headers(token)
kid = headers['kid']
# Find the key in the JWKS
key = None
for jwk_key in jwks['keys']:
if jwk_key['kid'] == kid:
key = jwk_key
break
if key is None:
raise Exception("Public key not found in JWKS")
# Construct a key for verification
public_key = jwk.construct(key)
# Verify the token
message, encoded_signature = token.rsplit('.', 1)
decoded_signature = base64url_decode(encoded_signature.encode('utf-8'))
if not public_key.verify(message.encode('utf-8'), decoded_signature):
raise jwt.JWTError("Signature verification failed")
# Decode the token to get the payload
payload = jwt.decode(token, key, algorithms=['RS256'], audience='<your-expected-audience>', issuer='https://<keycloak-domain>/auth/realms/<realm-name>')
returnValue(payload)
@inlineCallbacks
def main():
try:
payload = yield verify_jwt(token)
print("Token is valid:", payload)
except Exception as e:
print("Failed to verify token:", e)
finally:
reactor.stop()
if __name__ == "__main__":
reactor.callWhenRunning(main)
reactor.run() |
I remodeled this ticket scope to evaluate the possible integration of the code published in #4314 Status of the current implementation:
Actions necessary to possibly integrate same functionality:
Tests for this feature are probably difficult to be achieved so we might need to proceed without implementing any test and demanding tests of the functional tests to manual testing. |
Changes: - Renamed user.fiscal_code in user.idp_id to abstract the variable name in international scope
I've proceeded with the revision of the of the proposed changes to database included in this implementation by renaming the variable used to store users' idp identier with a variable user.idp_id that is more proper in the international scope and in relation to an idp connector that could return other national identifiers. Seems still missing an enabler to activate the functionality and the variables necessary to configure the idp endpoint that appears currently not configurable. I'm going to elaborate a proposal on a dedicated commit using the direct names of the component angular-oauth2-oidc |
Proposal
This ticket is about tracking research and development to integrate Keycloak as an identity provider.
Motivation and context
Basic idea is to use the functionality to enable support for third party authentications via Keycloak and in general OpenID Connect providers to authorize to be used to implement internal users logins based on external corporate policies.
Requirement collected while working with:
The text was updated successfully, but these errors were encountered: