brian-bh commented on issue #25740:
URL: https://github.com/apache/superset/issues/25740#issuecomment-3336907826

   Maybe this issue is inactive and is oriented toward 'Guest Token', but I 
also ran into it when primarily using Keycloak as AUTH_OAUTH. It turns out that 
the JWT token from login only have 'sub' field, which is user id value itself. 
When calling /api/v1/me or other APIs, somehow this 'sub' based user lookup 
method does not work properly.
   When you call the API and check the logs in the WebUI, the API calls may 
show a 'None' user, meaning that fetching user from access token failed.
   With the help of GPT and inspecting the codebase, adding custom security 
manager did the trick. Now I can finally maintain Keycloak login session, but 
if I need to use DB login for the API, that still works as well.
   
   I'm currently using 4.1.2 version, and it works.
   Be sure that you turned on AUTH_API_LOGIN_ALLOW_MULTIPLE_PROVIDERS option as 
True, just in case of preventing collision of providers.
   
   ```
   import re, jwt
   from flask import current_app
   from superset.security import SupersetSecurityManager
   
   class ApiFirstSecurityManager(SupersetSecurityManager):
       def __init__(self, appbuilder):
           super().__init__(appbuilder)
   
           lm = self.lm
   
           @lm.request_loader
           def bearer_request_loader(req):
               """
               1) Authorization: Find jwt token with regex in Bearer <jwt> from 
authorization header and load user
               2) If user is empty or fail, return None → Flask-Login uses 
default location such as user_loader
               """
               auth = req.headers.get("Authorization", "")
               m = re.match(r"^\\s*Bearer\\s+(.+)$", auth, re.I)
               if not m:
                   return None
   
               token = m.group(1)
               secret = (current_app.config.get("SECRET_KEY")
                         or current_app.config.get("SUPERSET_SECRET_KEY"))
               alg = current_app.config.get("JWT_ALGORITHM", "HS256") # this 
may fallback to HS256 in default, 4.1.2 doesn't have 'JWT_ALGORITHM' config 
value
   
               try:
                   payload = jwt.decode(token, secret, algorithms=[alg])
               except Exception:
                   return None
   
               uid = payload.get("sub")
               username = payload.get("username")
   
               user = self.get_user_by_id(uid) if uid is not None else None
               if user is None and username:  # jwt token only have 'sub' as 
uid but just in case
                   user = self.find_user(username=username)
               return user
   
   ```
   
   Add this code to superset_config.py (you can separate code as another python 
file of course)
   and set CUSTOM_SECURITY_MANAGER = ApiFirstSecurityManager and re-deploy.
   Now the API using access token can search user itself.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to