-
Notifications
You must be signed in to change notification settings - Fork 325
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
Adds support for the ExcludeIssuerFromAuthResponse option on OpenIdClient #934
base: main
Are you sure you want to change the base?
Adds support for the ExcludeIssuerFromAuthResponse option on OpenIdClient #934
Conversation
I've been struggling with this exat configuration. Thanks for the PR ! |
My tests have led me to think that the option is changed to |
Nevermind, I did more precise tests and they prove that the option is not overwritten every |
Hi @sebght ! Thanks for working on adding support for this option |
Good job @sebght, can't wait to see that released! 🚀 |
Well the repository is quite on pause currently, but I hope that this will change and that this PR will move on ! Follow the news here : #964 |
Hello @sebght, Thank you for the merge request. We're currently encountering this issue after upgrading Keycloak to the latest version. Is there any chance this could be merged soon? In the meantime, we've created a script as a workaround until an official release is available. import requests
import argparse
import logging
from typing import List, Optional
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger(__name__)
def get_token(idp_host: str, username: str, password: str) -> Optional[str]:
"""Get access token from the Identity Provider"""
url = f"{idp_host}/realms/master/protocol/openid-connect/token"
payload = {
"username": username,
"password": password,
"grant_type": "password",
"client_id": "admin-cli",
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}
response = requests.post(url, data=payload, headers=headers)
if response.status_code == 200:
logger.info("Successfully obtained token")
return response.json().get("access_token")
else:
logger.error(f"Failed to get token: {response.status_code}, {response.text}")
return None
def get_realms(idp_host: str, token: str) -> List[str]:
"""Fetch a list of realms"""
url = f"{idp_host}/admin/realms"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
logger.info("Successfully fetched realms")
realms = response.json()
return [realm["realm"] for realm in realms]
else:
logger.error(f"Failed to fetch realms: {response.status_code}, {response.text}")
return []
def get_client_ids(idp_host: str, realm: str, token: str) -> List[str]:
"""Fetch client IDs that contain 'ui' in their clientId"""
url = f"{idp_host}/admin/realms/{realm}/clients"
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(url, headers=headers)
if response.status_code == 200:
logger.info(f"Successfully fetched clients for realm {realm}")
clients = response.json()
return [client["id"] for client in clients if "ui" in client["clientId"]]
else:
logger.error(f"Failed to fetch clients for realm {realm}: {response.status_code}, {response.text}")
return []
def update_client(idp_host: str, realm: str, client_id: str, token: str) -> None:
"""Update the client's attribute to exclude issuer from the URL"""
url = f"{idp_host}/admin/realms/{realm}/clients/{client_id}"
headers = {"Authorization": f"Bearer {token}"}
# Fetch client details
response = requests.get(url, headers=headers)
if response.status_code == 200:
client_details = response.json()
client_name = client_details["clientId"]
logger.info(f"Updating client {client_name} in realm {realm}...")
# Update client attribute
client_details["attributes"]["exclude.issuer.from.auth.response"] = "true"
# Send the updated client details
update_response = requests.put(
url, headers=headers, json=client_details
)
if update_response.status_code == 204:
logger.info(f"Client {client_name} updated successfully.")
else:
logger.error(
f"Failed to update client {client_name}: {update_response.status_code}, {update_response.text}")
else:
logger.error(f"Failed to fetch client details: {response.status_code}, {response.text}")
def main(idp_host: str, username: str, password: str) -> None:
"""Main function to handle the logic of fetching realms and updating clients"""
token = get_token(idp_host, username, password)
if not token:
logger.error("Failed to retrieve token. Exiting.")
return
realms = get_realms(idp_host, token)
if not realms:
logger.error("No realms found. Exiting.")
return
for realm in realms:
logger.info(f"Processing realm: {realm}")
client_ids = get_client_ids(idp_host, realm, token)
for client_id in client_ids:
update_client(idp_host, realm, client_id, token)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Keycloak Client Attribute Updater")
parser.add_argument("--host", required=True, help="Identity Provider host URL")
parser.add_argument("-u", "--username", required=True, help="Username for authentication")
parser.add_argument("-p", "--password", required=True, help="Password for authentication")
args = parser.parse_args()
main(args.host, args.username, args.password) |
Solves #928
What has been changed :
ExcludeIssuerFromAuthResponse
attribute in the clientExcludeIssuerFromAuthResponse
attributeopenid_client
also returns this attribute