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]