Endpoint /api/me/roles returns 401 "Not authorized" despite valid access token
I am running Superset 3.0.0 with Docker Compose. Trying to access the following API endpoint:
/api/me/roles
I have created an access token from /api/v1/security/login for a user with the Admin, Public and Gamma roles. I make a request for the mentioned API endpoint with the appropriate header.
Authorization: Bearer {access-token}
Accept: application/json
Various endpoints return 200 and a valid JSON payload, such as /api/v1/dashboard and /api/v1/chart. However, the
/api/me/roles endpoint returns 401 "Not authorized". This blocks the embedded dashboard feature. Could this be a bug, or am I doing something wrong? I sense there is something special with this endpoint and authentication as it relates to the currently authenticated user.
The /api/me/roles endpoint returns the roles when I log in through the UI and load the endpoint in a web browser.
Expected results
I expect the roles to be returned from the API with 200 OK status.
Actual results
The endpoint returns 401 "Not authorized" despite the access token seemingly being valid.
Environment
(please complete the following information):
- Chrome latest.
- Linux Ubuntu 22.04.
- Superset 3.0.0 on Docker Compose in production mode
Flags
WTF_CSRF_ENABLED = False
TALISMAN_ENABLED = False
ENABLE_CORS = True
Still happening in 3.0.1
You can try a fix around by hitting a get request to http://localhost:8088/login endpoint and sending the csrf_token obtained along with username and password as formData and then get the access token to request http://localhost:8088/api/v1/me/roles api
Issue addressed here #25876
Still happening in 3.1.1, also blocking usage of embedded dashboards. Unfortunately the workaround above won't work because the embed SDK won't do that for me
Digging into this more, it seems /api/v1/security/login does not set a session cookie; hence, the /api/v1/me and underlying calls fail b/c there's no session cookie
Digging into this more, it seems
/api/v1/security/logindoes not set a session cookie; hence, the/api/v1/meand underlying calls fail b/c there's no session cookie
I am facing the same issue
Normally, how can I get the session cookie? if /api/v1/security/login doesn't return it, is there any other way to login and get cookie? how did superset work if there is no session cookie?
Still happening in 3.1.1, also blocking usage of embedded dashboards. Unfortunately the workaround above won't work because the embed SDK won't do that for me
So superset only returns the dashboard available to that user according to the role defined
Digging into this more, it seems
/api/v1/security/logindoes not set a session cookie; hence, the/api/v1/meand underlying calls fail b/c there's no session cookieI am facing the same issue Normally, how can I get the session cookie? if
/api/v1/security/logindoesn't return it, is there any other way to login and get cookie? how did superset work if there is no session cookie?
I had to do a hack (emphasis on hack: this is not production ready code, please review it b/c if done wrong it creates a security hole) to basically take a JWT, verify it, find the corresponding user, then login that user again. The result is a cookie getting set on response:
class CustomOAuthView(AuthOAuthView):
@expose('/custom/session-by-jwt', methods=['GET'])
def session_by_jwt(self, provider= None):
# get the jwt in the request
current_jwt = request.headers.get('Authorization').split(' ')[1]
# decode the jwt to get the claims
import jwt
try:
jwt_options = {
'verify_signature': False, # TODO: get the public key from the jwks_uri to verify the signature
'verify_exp': True,
'verify_nbf': False,
'verify_iat': True,
'verify_aud': False
}
jwt_decoded = jwt.decode(jwt=str.encode(current_jwt), algorithms=['HS256'], options=jwt_options)
# get the user from the jwt
user = self.appbuilder.sm.find_user(email=jwt_decoded['sub'])
# create a session cookie for the user
login_user(user)
except Exception as e:
print(f"Exception: {e}")
return "Invalid JWT"
return "session_by_jwt"
class CustomSsoSecurityManager(SupersetSecurityManager):
authoauthview = CustomOAuthView
def __init__(self, appbuilder):
super(CustomSsoSecurityManager, self).__init__(appbuilder)
Digging into this more, it seems
/api/v1/security/logindoes not set a session cookie; hence, the/api/v1/meand underlying calls fail b/c there's no session cookie
I found out that if we set those flag in superset config: SESSION_COOKIE_HTTPONLY = False SESSION_COOKIE_SECURE = False
the /api/v1/security/login endpoint will return a cookie like this:
is this the right cookie? if so, how to use it? I tried to add it in postman but it doesn't work
Ah, good find! Yeah, that's looks close, the one I have starts with a .. Digging into the superset_config.py in the main repo, I see this:
#
# Flask session cookie options
#
# See https://flask.palletsprojects.com/en/1.1.x/security/#set-cookie-options
# for details
#
SESSION_COOKIE_HTTPONLY = True # Prevent cookie from being read by frontend JS?
SESSION_COOKIE_SECURE = False # Prevent cookie from being transmitted over non-tls?
SESSION_COOKIE_SAMESITE: Literal["None", "Lax", "Strict"] | None = "Lax"
# Whether to use server side sessions from flask-session or Flask secure cookies
SESSION_SERVER_SIDE = False
# Example config using Redis as the backend for server side sessions
# from flask_session import RedisSessionInterface
#
# SESSION_SERVER_SIDE = True
# SESSION_USE_SIGNER = True
# SESSION_TYPE = "redis"
# SESSION_REDIS = Redis(host="localhost", port=6379, db=0)
#
# Other possible config options and backends:
# # https://flask-session.readthedocs.io/en/latest/config.html
Perhaps switch to server side sessions might help?
Perhaps switch to server side sessions might help?
I tried, but still not working Any other idea?
Hi all,
same problem here. Do I have to rollback on version 2 or do you think this problem may be fixed in a rather short time ?
Thx !!
~~Hi,~~
~~I'm also seeing this on Superset 3.1.0 when trying to embed dashboards using the embedded sdk. Any updates?~~
~~Thanks in advance~~
Turns out guest token I was using wasn't formatted correct in which case the Embedded SDK successfully creates the dashboard just to fail on the subsequent call to /roles
@mortenesbensen when you say it "wasn't formatted correctly" what was the issue? I think we're running into this same issue now.
Hello,
I am new to Apache Superset and am working on integrating REST APIs for CRUD operations within my project. I understand that in order to interact with the Superset REST APIs, I need to obtain an API token. Could you please provide guidance on how to retrieve the API token either through the Superset UI or by sending HTTP requests?
For context, I have already configured Keycloak for authentication, and would appreciate any instructions or references to help me proceed.
Thank you for your assistance!
This issue has seen a lot of activity in the past, but has been silent for several months now. Is this still an issue in 4.1.2/5.0.0/master? Otherwise tempted to close as inactive/not-planned.
@rusackas I'm still experiencing this in 4.1.1 and 5.0.0rc2. I'm using the sdk and successfully creating a guest token directly in my app signed with the secret set in configuration variable GUEST_TOKEN_JWT_SECRET. I've checked all the tokens and they are all valid and working and the embed partially works...it pulls lots of js and css files using the token but then the embed just shows "Something went wrong with embedded authentication. Check the dev console for details." Checking the dev console shows what others report: A 401 returned when calling to /api/v1/me/roles. I've tried many solutions and none have worked for me.
active issue getting 401 with SDK on roles
@mortenesbensen I realize its a year later, but I was wondering if you could elaborate on the changes you made to allow the embedding to work? I've checked the validity of my tokens and they are verified to be valid, yet I cannot get embedding to not fail on the call to /roles.
And, to anyone else, I'm wondering if there is a workaround? Maybe not using the SDK ?
@rusackas I resolved the issue, there were a couple of issues at hand in my case, due to my configuration and not due to Superset.
Firstly I needed to include the correct ROLE configuration variables in my config:
GUEST_ROLE_NAME = "Gamma"
PUBLIC_ROLE_LIKE = "Gamma"
Once they were in, I no longer got the 401 error. I did have a new error, though, related to the audience. I was using the guest token generated from the app:
{
"user": {
"username": "[email protected]",
"first_name": "embedded",
"last_name": "embedded"
},
"resources": [
{
"type": "dashboard",
"id": "d73e7841-9342-4afd-8e29-b4a416a2498c"
}
],
"rls_rules": [],
"iat": 1730883214,
"exp": 1732956814,
"aud": "superset",
"type": "guest"
}
And the aud was specified as superset. So to get this to work I realized I needed to include that in the configuration as well:
GUEST_TOKEN_JWT_AUDIENCE = "superset"
After that, it is working as expected in 5.0.0rc2 (and probably 4.1.1 as well, but I haven't checked). But in the end it was a configuration error on my end.
Apologies for the late reply. It's been a while since I worked on this so can't remember the exact issue, but I do remember that I had somehow formatted the guest token incorrectly (probably padded it with some extra characters or the like). What baffled me was that I got this error while other calls seemed to pass though