Skip to content
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

rework eda auth flow to use keycloak #17

Closed
hellt opened this issue Jan 6, 2025 · 1 comment
Closed

rework eda auth flow to use keycloak #17

hellt opened this issue Jan 6, 2025 · 1 comment

Comments

@hellt
Copy link
Contributor

hellt commented Jan 6, 2025

https://eda/auth/login endpoint will be deprecated. To get bearer token use the keycloack directly as documented here https://docs.eda.dev/development/api/#authentication

To authenticate any api client with eda the workflow should acquiring the access token from the keycloak service that runs alongside EDA.

To acquire the token, the api client should authenticate with a known client id and client secret. As of 24.12.1, keycloak comes preconfigured with the following data

  1. realm: eda
  2. client: eda

To acquire the token for the eda client we need to get the client secret, which is a random value generated at keycloak creation time. Since these secrets are not hardcoded, clab connector should fetch the secret from keycloak.

We should assume that two workflows are possible:

  1. The user already knows the client secret, they may get it from their EDA admin (the production workflow). In this case, the secret should be passed via the cli flag client-secret
  2. The user does not know the client secret. In this case we fetch the secret from the keycloak by authenticating against the keycloak admin api as shown below

We assume that the keycloak admin credentials are admin:admin, we might want to expose these via CLI flags as well (kc-user, kc-password).

To fetch the eda client secret we should do smth like this

import httpx

# Keycloak configuration
keycloak_url = "http://<keycloak-host>/auth"  # Replace with your Keycloak URL
realm = "master"  # Keycloak realm for admin users
client_id = "admin-cli"  # Default client for admin operations
username = "admin"
password = "admin"

# Step 1: Get an access token
token_url = f"{keycloak_url}/realms/{realm}/protocol/openid-connect/token"
token_data = {
    "grant_type": "password",
    "client_id": client_id,
    "username": username,
    "password": password,
}
headers = {"Content-Type": "application/x-www-form-urlencoded"}

def get_client_secret():
    with httpx.Client() as client:
        # Fetch access token
        token_response = client.post(token_url, data=token_data, headers=headers)
        token_response.raise_for_status()
        access_token = token_response.json()["access_token"]

        # Step 2: Fetch the `eda` client ID and secret
        admin_api_url = f"{keycloak_url}/admin/realms/eda-realm/clients"
        auth_headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json",
        }

        # Fetch clients
        clients_response = client.get(admin_api_url, headers=auth_headers)
        clients_response.raise_for_status()
        clients = clients_response.json()

        # Find the `eda` client
        eda_client = next((client for client in clients if client["clientId"] == "eda"), None)

        if not eda_client:
            raise Exception("Client `eda` not found in realm `eda-realm`")

        # Fetch the client secret
        client_id = eda_client["id"]
        client_secret_url = f"{admin_api_url}/{client_id}/client-secret"
        secret_response = client.get(client_secret_url, headers=auth_headers)
        secret_response.raise_for_status()
        client_secret = secret_response.json()["value"]

        print(f"Client ID: {client_id}")
        print(f"Client Secret: {client_secret}")

# Run the function
get_client_secret()

With the eda client secret known, the request to get the api token is:

curl -s https://eda.example.com:9443/core/httpproxy/v1/keycloak/realms/eda/protocol/openid-connect/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'client_id=eda' \
  --data-urlencode 'grant_type=password' \
  --data-urlencode 'scope=openid' \
  --data-urlencode 'username=admin' \
  --data-urlencode 'password=admin' \
  --data-urlencode 'client_secret={client_secret}'
@hellt hellt changed the title rework eda auth flow to use keycloack rework eda auth flow to use keycloak Jan 6, 2025
@FloSch62
Copy link
Collaborator

closed by #31

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants