suchorski / springboot-keycloak-server

Embeded Keycloak on Spring Boot Server
Apache License 2.0
26 stars 12 forks source link

Redirecting using embeded keyclock to superset #13

Closed ChiragsinhCW closed 3 weeks ago

ChiragsinhCW commented 1 month ago

i have user management service i want to configure keyclocak for authentication in superset can we uses keycloak token in superset for redirect in dashboard

suchorski commented 1 month ago

Is this an issue?

ChiragsinhCW commented 1 month ago

no i want your suggestion how can we do it in superset if you know about it

suchorski commented 1 month ago

Yes, you can integrate Keycloak with Apache Superset for authentication and use Keycloak tokens to control access to dashboards. Here's a general guide on how to configure this integration:

Prerequisites

  1. Keycloak server: Ensure that you have a running Keycloak server.
  2. Apache Superset: Ensure that Superset is installed and running.

Steps to Integrate Keycloak with Superset

  1. Configure Keycloak:

    • Create a Realm: In Keycloak, create a new realm or use an existing one.
    • Create a Client: In the realm, create a new client for Superset.
      • Set the Client ID to something descriptive like superset.
      • Set Client Protocol to openid-connect.
      • Set Access Type to confidential and configure Valid Redirect URIs to point to your Superset instance, e.g., http://localhost:8088/*.
      • Save the client and note down the Client Secret.
  2. Configure Superset:

    • Install necessary packages: Make sure you have the necessary OAuth libraries installed. You can install them using pip:
      pip install authlib
    • Modify superset_config.py: Configure Superset to use Keycloak for OAuth authentication. Edit the superset_config.py file (usually located in the root directory of your Superset installation) to include the following configuration:

      from authlib.integrations.flask_client import OAuth
      
      # Keycloak Configuration
      KEYCLOAK_BASE_URL = 'http://<KEYCLOAK_SERVER>/auth/realms/<REALM>'
      KEYCLOAK_CLIENT_ID = '<CLIENT_ID>'
      KEYCLOAK_CLIENT_SECRET = '<CLIENT_SECRET>'
      KEYCLOAK_DISCOVERY_URL = f'{KEYCLOAK_BASE_URL}/.well-known/openid-configuration'
      
      # Configure the OAuth object
      oauth = OAuth(app)
      oauth.register(
       name='keycloak',
       client_id=KEYCLOAK_CLIENT_ID,
       client_secret=KEYCLOAK_CLIENT_SECRET,
       server_metadata_url=KEYCLOAK_DISCOVERY_URL,
       client_kwargs={'scope': 'openid profile email'},
      )
      
      # Authentication Providers
      AUTH_TYPE = AUTH_OAUTH
      OAUTH_PROVIDERS = [
       {
           'name': 'keycloak',
           'token_key': 'access_token',
           'icon': 'fa-address-card',
           'remote_app': oauth.keycloak,
       }
      ]
      
      # Other required configurations
      OAUTH_REDIRECT_URI = 'http://<YOUR_SUPERSET_INSTANCE>/oauth-authorized/keycloak'
  3. Restart Superset: After configuring superset_config.py, restart your Superset server to apply the changes.

  4. Access Superset: When you navigate to Superset, you should now see an option to log in using Keycloak. Upon successful authentication with Keycloak, you should be redirected back to Superset and logged in.

Notes:

This configuration allows users authenticated via Keycloak to access Superset dashboards based on the tokens issued by Keycloak.

ChiragsinhCW commented 1 month ago

yes i do it but i want to by pass login page login process do in backend side not want key cloak login page

suchorski commented 1 month ago

To bypass the Keycloak login page and handle the login process on the backend side, you can use Keycloak's Direct Access Grants (Resource Owner Password Credentials Grant) flow. This involves sending the user's credentials directly to Keycloak to obtain an access token, which you can then use to authenticate with Superset.

Steps to Implement Backend Login:

  1. Obtain Access Token Directly from Keycloak:

    You need to create an endpoint in your backend that handles user login by sending their credentials to Keycloak and obtaining an access token.

    import requests
    
    KEYCLOAK_BASE_URL = 'http://<KEYCLOAK_SERVER>/auth/realms/<REALM>'
    KEYCLOAK_CLIENT_ID = '<CLIENT_ID>'
    KEYCLOAK_CLIENT_SECRET = '<CLIENT_SECRET>'
    
    def get_keycloak_token(username, password):
       url = f"{KEYCLOAK_BASE_URL}/protocol/openid-connect/token"
       data = {
           'client_id': KEYCLOAK_CLIENT_ID,
           'client_secret': KEYCLOAK_CLIENT_SECRET,
           'grant_type': 'password',
           'username': username,
           'password': password
       }
       response = requests.post(url, data=data)
       if response.status_code == 200:
           return response.json()
       else:
           response.raise_for_status()
  2. Configure Superset to Use the Token:

    Modify superset_config.py to authenticate users using the token obtained from the backend endpoint.

    from flask import request, redirect, url_for
    from flask_appbuilder.security.views import AuthDBView
    from flask_appbuilder.security.sqla.models import User
    from flask_appbuilder.security.manager import AUTH_OAUTH
    
    class CustomAuthDBView(AuthDBView):
       login_template = ''  # Remove login template to bypass login page
    
       def login(self):
           # Extract username and password from request
           username = request.form.get('username')
           password = request.form.get('password')
    
           # Get token from Keycloak
           token = get_keycloak_token(username, password)
    
           if 'access_token' in token:
               user = self.appbuilder.sm.find_user(username=username)
               if not user:
                   # Create user if not exists
                   user = User()
                   user.username = username
                   user.active = True
                   self.appbuilder.sm.add_user(
                       username=username,
                       first_name=username,
                       last_name='',
                       email='',
                       role=self.appbuilder.sm.find_role('Public')
                   )
    
               login_user(user, remember=False)
               return redirect(url_for('Superset.index'))
           else:
               return redirect(url_for('AuthDBView.login'))
    
    AUTH_TYPE = AUTH_OAUTH
    AUTH_USER_REGISTRATION = True
    AUTH_USER_REGISTRATION_ROLE = 'Public'
    
    # Use custom auth view
    CUSTOM_SECURITY_MANAGER = CustomAuthDBView
  3. Handle User Login Request in Backend:

    Create a route in your backend to handle login requests. This route should call the get_keycloak_token function and handle the response accordingly.

    from flask import Flask, request, jsonify
    
    app = Flask(__name__)
    
    @app.route('/login', methods=['POST'])
    def login():
       username = request.json.get('username')
       password = request.json.get('password')
       try:
           token = get_keycloak_token(username, password)
           return jsonify(token)
       except requests.HTTPError as e:
           return jsonify({'error': str(e)}), 400
    
    if __name__ == '__main__':
       app.run(debug=True)
  4. Authenticate Requests to Superset:

    When making requests to Superset, include the access token in the headers for authentication.

    import requests
    
    def access_superset_dashboard(token):
       headers = {
           'Authorization': f"Bearer {token['access_token']}"
       }
       superset_url = "http://<SUPERSET_SERVER>/superset/dashboard/1/"
       response = requests.get(superset_url, headers=headers)
       if response.status_code == 200:
           print("Accessed Superset Dashboard")
       else:
           print("Failed to access Superset Dashboard")
    
    # Example usage:
    token = get_keycloak_token('username', 'password')
    access_superset_dashboard(token)

Notes:

This approach bypasses the Keycloak login page by handling authentication in the backend and using tokens to access Superset.