-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Azure OAuth CSRF State Not Equal Error #1957
Comments
Have you checked this: https://stackoverflow.com/questions/61922045/mismatchingstateerror-mismatching-state-csrf-warning-state-not-equal-in-reque also what Authlib version are you using? |
Yes, I have checked that stack overflow article. Our secret key is being set in our helm chart for Airflow and this error still persists. As far as versions, I will give you what we were using before when it worked and what we are using now that is not working: The versions we had when this was working: Airflow==2.2.5 The versions we have now: Airflow==2.4.3 |
You can look for additional info on this issue here as well: lepture/authlib#518 |
@dpgaspar to give an update for you and everybody else with FAB, I have did additional debugging and want to share the results: It looks like when I try to log in, it is failing in the file flask_appbuilder/security/views.py at line 657: log.error("Error authorizing OAuth access token: {0}".format(e)). It hits this line because it is in a try block. This is the function it is trying: resp = self.appbuilder.sm.oauth_remotes[provider].authorize_access_token() Following this function, I found it leads to this file: authlib/integrations/flask_client/apps.py. It is failing at line 103 which is: params = self._format_state_params(state_data, params) Looking into this further, it looks like this calls the _format_state_params method in the file authlib/integrations/base_client/sync_app.py, and in this method it is going in the if statement, which is: if state_data is None so, in the apps.py file when it does the line: state_data = self.framework.get_state_data(session, params.get('state')) my state is coming in as none. But, when I look at the network debugger tool in chrome, it looks like state is getting added to the urls being sent. Digging into this even more, in the authlib/integrations/flask_client/apps.py file, line 101: state_data = self.framework.get_state_data(session, params.get('state')) is how it is getting the state_data. I have printed out the line "params.get('state')", and this returns the correct state value. Looking into this more, it looks like this leads to this file: authlib/integrations/base_client/framework_integration.py. In this file, it sets up a key at line 34: key = f'state{self.name}_{state}' and tries to get the session data with this key: value = session.get(key). But, it is returning "None". I have also tried to print out he name of the session, and it prints out "None" as well. When I just try to print out the session in general, this is what is printed: <SqlAlchemySession {'_permanent': True, '_fresh': False}> So, it looks like the session is being created, but there is nothing in it. So my question is, why would the session be empty, and how do I debug and fix this? |
Also, if it helps, I have found where the app gets created in Airflow:
|
@dpgaspar I have did more debugging, and am back with another update to provide more information on this issue. Looks like I figured out what is happening but am unsure on how to fix. I have put in a ton of debugging statements to follow the flow of code to see what was happening in the background. But, in interest of keeping this update short, I will just summarize what I found and what I think is happening. We start in flask_appbuilder/security/views.py in the "def login(self, provider: Optional[str] = None) -> WerkzeugResponse:" function under the "AuthOAuthView(AuthView) class. This function returns a call to another function, "authorize_redirect". The function" authorize_redirect" is found in authlib/integrations/flask_client/apps.py at line 39. This function does a lot of things, but the most important is at the end when it calls "save_authorize_data". "save_authorize_data" is in the same file, and found at line 32. This function calls a function called "set_state_data". This leads us to authlib/integrations/base_client/framework_integration.py, where it sets the session data and returns. Before the function "Authorize_redirect" returns back to "views.py", I printed out the session to see what it looked like. This is what is printed: Clearly, you can see here that session has the correct state. So it returns the redirect url, and according to this in the return statement of the "login" function: "redirect_uri=url_for( ".oauth_authorized", provider=provider _external=True)" my guess is that the next place its going is the "oauth_authorized" function within the "views.py" file. So, I put print statements at the top of this file to print out the session, and this is what I get: So, somehow the redirect is causing the session to lose all its data… I will be investigating on this more Tuesday, but I hope you can help provide insight on how to fix. |
@dpgaspar I have been stuck on finding out why the redirect is causing the session to lose all of its data, any help on how to debug and fix this? |
@dpgaspar I have finally found what the source of this problem was, as well as the solution. Doing more debugging, I found that the problem with the session was coming from the webserver_config.py file that I had created. So, what I did was started with as barebones of a Oauth Webserver_config.py file as I could, and kept adding lines until one of them screwed up the session. In doing this I found that it was this line: PERMANENT_SESSION_LIFETIME = 1800 That was causing the session to not persist. I am not too sure as to why. The reason I had put this in my webserver_config.py file in the first place is because it is in the FAB documentation(https://flask-appbuilder.readthedocs.io/en/latest/security.html#), but in further researching I found that it is already being set in the creation of the flask app by Airflow and is an configuration option: AIRFLOW__WEBSERVER__SESSION_LIFETIME_MINUTES Now why this worked in Airflow version 2.2.5 and not in Airflow 2.4.3, I am not for sure. Also through my debugging I found out that FAB natively supports Azure now, so a custom security class and user info handler function is not needed. So, the solution to my problem was to start using thie webserver_config.py file down below.
|
@dpgaspar interesting note I want to add that should be reported as bug either on your side or Airflow's side. Looks like the problem is with the PERMANENT_SESSION_LIFETIME variable in general. I just tried to set this value to 30 minutes in my helm chart like this: AIRFLOW__WEBSERVER__SESSION_LIFETIME_MINUTES: "30" And the CSRF state error instantly came back. After taking this out, it worked again. So this should be reported as a bug. |
when i am using azure authentication in flask app builder getting this error : Error returning OAuth user info: %s 'upn'
i have got jwt token credentials are verified but getting UPN key error how can i resolve it |
fixed on #2121 |
If you'd like to report a bug in Flask-Appbuilder, fill out the template below. Provide
any extra information that may be useful
Responsible disclosure:
We want to keep Flask-AppBuilder safe for everyone. If you've discovered a security vulnerability
please report to [email protected].
Environment
Flask-Appbuilder version:
pip freeze output: Flask-Appbuilder version==4.1.4
Describe the expected results
We are currently running Airflow 2.4.3 on Kubernetes with the Airflow Community helm chart version 8.6.1 (located here: https://github.com/airflow-helm/charts).
We have enabled Azure OAuth authentication for our webserver. This should bring up our webserver with an "login with azure" button and we should be able to click it and log in just fine. This is our webserver_config that we are using:
Describe the actual results
Instead, we are getting this error after we click the Azure button:
[2022-11-28 22:04:58,744] {views.py:659} ERROR - Error authorizing OAuth access token: mismatching_state: CSRF Warning! State not equal in request and response.
airflow-web [2022-11-28 22:04:58,744] {views.py:659} ERROR - Error authorizing OAuth access token: mismatching_state: CSRF Warning! State not equal in request and response.
Steps to reproduce
Running Airflow 2.4.3 on Kubernetes with the Airflow Community helm chart version 8.6.1 and using the webserver_config file like above. When the webserver is running, you click on the "login to azure" button.
Additional Comments
I already posted an issue like this in the Airflow repo, and they said this could more then likely be a Flask problem, which is why I am making this issue here. If any other information is needed please let me know
The text was updated successfully, but these errors were encountered: