andrewzah opened a new issue, #34024:
URL: https://github.com/apache/airflow/issues/34024
### Apache Airflow version
2.7.0
### What happened
When trying to log in to airflow with a keycloak 18.0.2 provider using
google chrome, I get this error:
```
Traceback (most recent call last):
File
"/home/kubezt/.local/lib/python3.8/site-packages/flask_appbuilder/security/views.py",
line 658, in oauth_authorized
resp =
self.appbuilder.sm.oauth_remotes[provider].authorize_access_token()
File
"/home/kubezt/.local/lib/python3.8/site-packages/authlib/integrations/flask_client/apps.py",
line 100, in authorize_access_token
params = self._format_state_params(state_data, params)
File
"/home/kubezt/.local/lib/python3.8/site-packages/authlib/integrations/base_client/sync_app.py",
line 234, in _format_state_params
raise MismatchingStateError()
authlib.integrations.base_client.errors.MismatchingStateError:
mismatching_state: CSRF Warning! State not equal in request and response.
```
### What you think should happen instead
I should be able to log in with the keycloak provider.
### How to reproduce
my webserver_config.py:
```python
import os
import logging
import jwt
import requests
from base64 import b64decode
from cryptography.hazmat.primitives import serialization
from tokenize import Exponent
from airflow import configuration as conf
from flask_appbuilder.security.manager import AUTH_OAUTH
from airflow.www.security import AirflowSecurityManager
from flask_appbuilder import expose
from flask_appbuilder.security.views import AuthOAuthView
basedir = os.path.abspath(os.path.dirname(__file__))
log = logging.getLogger(__name__)
SQLALCHEMY_CONN = os.environ['KC_DB_STRING']
SQLALCHEMY_DATABASE_URI = os.environ['KC_DB_STRING']
CSRF_ENABLED = True
AUTH_TYPE = AUTH_OAUTH
AUTH_ROLE_ADMIN = 'Admin'
AUTH_ROLE_PUBLIC = 'Public'
AUTH_USER_REGISTRATION = True
AUTH_ROLES_SYNC_AT_LOGIN = True
AUTH_USER_REGISTRATION_ROLE = 'User'
AUTH_ROLES_MAPPING = {
"airflow_admin": ["Admin"],
"airflow_op": ["Op"],
"airflow_user": ["User"],
"airflow_viewer": ["Viewer"],
"airflow_public": ["Public"],
}
PROVIDER_NAME = 'Keycloak SSO'
CLIENT_ID = os.environ['KC_CLIENT_ID']
OAUTH_PROVIDERS = [{
'name': PROVIDER_NAME,
'token_key':'access_token',
'icon':'fa-circle-o',
'remote_app': {
'api_base_url': os.environ['KC_CONFIG_URL'],
'access_token_url': os.environ['KC_TOKEN_URL'],
'authorize_url': os.environ['KC_AUTH_URL'],
'userinfo_url': os.environ['KC_USERINFO_URL'],
'request_token_url': None,
'client_id': CLIENT_ID,
'client_secret': os.environ['KC_CLIENT_SECRET'],
'client_kwargs':{
'scope': 'email profile'
},
}
}]
req = requests.get(os.environ['KC_BASE_REALM_URL'])
key_der_base64 = req.json()["public_key"]
key_der = b64decode(key_der_base64.encode())
public_key = serialization.load_der_public_key(key_der)
class CustomAuthRemoteUserView(AuthOAuthView):
@expose("/logout/")
def logout(self):
"""Delete access token before logging out."""
return super().logout()
class CustomSecurityManager(AirflowSecurityManager):
authoauthview = CustomAuthRemoteUserView
def oauth_user_info(self, provider, response):
if provider == PROVIDER_NAME:
log.info("response: {}".format(response))
token = response["access_token"]
log.info("token: {}".format(token))
me = jwt.decode(token, public_key, algorithms=['HS256',
'RS256'], audience=CLIENT_ID)
log.info("me: {}".format(me))
# sample of resource_access
# {
# "resource_access": { "airflow": { "roles": ["airflow_admin"]
}}
# }
groups = me.get("resource_access", {}).get("airflow",
{}).get("roles")
if groups is None or len(groups) < 1:
groups = ["airflow_public"]
else:
groups = [str for str in groups if "airflow" in str]
log.info("making userinfo")
userinfo = {
"username": me.get("preferred_username"),
"email": me.get("email"),
"first_name": me.get("given_name"),
"last_name": me.get("family_name"),
"role_keys": groups,
}
log.info("user info: {0}".format(userinfo))
return userinfo
else:
return {}
SECURITY_MANAGER_CLASS = CustomSecurityManager
```
### Operating System
Rocky Linux 8.8
### Versions of Apache Airflow Providers
_No response_
### Deployment
Docker-Compose
### Deployment details
```
$ pip freeze
aiohttp==3.8.5
aiosignal==1.3.1
alembic==1.11.3
amqp==5.1.1
anyio==3.7.1
apache-airflow==2.7.0
apache-airflow-providers-apache-hive==6.1.4
apache-airflow-providers-celery==3.3.2
apache-airflow-providers-common-sql==1.7.0
apache-airflow-providers-ftp==3.5.0
apache-airflow-providers-http==4.5.0
apache-airflow-providers-imap==3.3.0
apache-airflow-providers-jdbc==4.0.1
apache-airflow-providers-mysql==5.2.1
apache-airflow-providers-postgres==5.6.0
apache-airflow-providers-sqlite==3.4.3
apache-airflow-providers-ssh==3.7.1
apispec==6.3.0
argcomplete==3.1.1
asgiref==3.7.2
async-timeout==4.0.3
attrs==23.1.0
Authlib==1.2.1
Babel==2.12.1
backoff==2.2.1
backports.zoneinfo==0.2.1
bcrypt==4.0.1
billiard==4.1.0
blinker==1.6.2
cachelib==0.9.0
cattrs==23.1.2
celery==5.3.1
certifi==2023.7.22
cffi==1.15.1
charset-normalizer==3.2.0
click==8.1.7
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.3.0
clickclick==20.10.2
colorama==0.4.6
colorlog==4.8.0
ConfigUpdater==3.1.1
connexion==2.14.2
cron-descriptor==1.4.0
croniter==1.4.1
cryptography==41.0.3
Deprecated==1.2.14
dill==0.3.7
dnspython==2.4.2
docutils==0.20.1
email-validator==1.3.1
exceptiongroup==1.1.3
Flask==2.2.5
Flask-AppBuilder==4.3.3
Flask-Babel==2.0.0
Flask-Caching==2.0.2
Flask-JWT-Extended==4.5.2
Flask-Limiter==3.4.1
Flask-Login==0.6.2
Flask-Session==0.5.0
Flask-SQLAlchemy==2.5.1
Flask-WTF==1.1.1
flower==2.0.1
frozenlist==1.4.0
future==0.18.3
google-re2==1.1
googleapis-common-protos==1.60.0
graphviz==0.20.1
greenlet==2.0.2
grpcio==1.57.0
gunicorn==21.2.0
h11==0.14.0
hmsclient==0.1.1
httpcore==0.17.3
httpx==0.24.1
humanize==4.8.0
idna==3.4
importlib-metadata==4.13.0
importlib-resources==6.0.1
inflection==0.5.1
itsdangerous==2.1.2
JayDeBeApi==1.2.3
Jinja2==3.1.2
JPype1==1.4.1
jsonschema==4.19.0
jsonschema-specifications==2023.7.1
kafka-python==2.0.2
kombu==5.3.1
lazy-object-proxy==1.9.0
limits==3.5.0
linkify-it-py==2.0.2
lockfile==0.12.2
Mako==1.2.4
Markdown==3.4.4
markdown-it-py==3.0.0
MarkupSafe==2.1.3
marshmallow==3.20.1
marshmallow-oneofschema==3.0.1
marshmallow-sqlalchemy==0.26.1
mdit-py-plugins==0.4.0
mdurl==0.1.2
multidict==6.0.4
mysql-connector-python==8.1.0
mysqlclient==2.2.0
ndg-httpsclient==0.5.1
numpy==1.24.4
opentelemetry-api==1.15.0
opentelemetry-exporter-otlp==1.15.0
opentelemetry-exporter-otlp-proto-grpc==1.15.0
opentelemetry-exporter-otlp-proto-http==1.15.0
opentelemetry-proto==1.15.0
opentelemetry-sdk==1.15.0
opentelemetry-semantic-conventions==0.36b0
ordered-set==4.1.0
packaging==23.1
pandas==2.0.3
paramiko==3.3.1
pathspec==0.11.2
pendulum==2.1.2
pkgutil_resolve_name==1.3.10
pluggy==1.3.0
prison==0.2.1
prometheus-client==0.17.1
prompt-toolkit==3.0.39
protobuf==4.21.12
psutil==5.9.5
psycopg2-binary==2.9.7
pure-sasl==0.6.2
pyasn1==0.5.0
pyasn1-modules==0.3.0
pycparser==2.21
pydantic==1.10.12
Pygments==2.16.1
PyHive==0.7.0
PyJWT==2.8.0
PyNaCl==1.5.0
pyOpenSSL==23.2.0
python-daemon==3.0.1
python-dateutil==2.8.2
python-ldap==3.4.3
python-nvd3==0.15.0
python-slugify==8.0.1
pytz==2023.3
pytzdata==2020.1
PyYAML==6.0.1
redis==5.0.0
referencing==0.30.2
requests==2.31.0
requests-toolbelt==1.0.0
rfc3339-validator==0.1.4
rich==13.5.2
rich-argparse==1.3.0
rpds-py==0.10.0
sasl==0.3.1
setproctitle==1.3.2
six==1.16.0
sniffio==1.3.0
SQLAlchemy==1.4.49
SQLAlchemy-JSONField==1.0.1.post0
SQLAlchemy-Utils==0.41.1
sqlparse==0.4.4
sshtunnel==0.4.0
tabulate==0.9.0
tenacity==8.2.3
termcolor==2.3.0
text-unidecode==1.3
thrift==0.16.0
thrift-sasl==0.4.3
tornado==6.3.3
typing_extensions==4.7.1
tzdata==2023.3
uc-micro-py==1.0.2
unicodecsv==0.14.1
urllib3==2.0.4
vine==5.0.0
wcwidth==0.2.6
Werkzeug==2.2.3
wrapt==1.15.0
WTForms==3.0.1
yarl==1.9.2
zipp==3.16.2
```
in airflow.cfg, these changes were made
```
[webserver]
rbac = True
authenticate = True
```
and my env vars:
```
AIRFLOW__WEBSERVER__BASE_URL: 'https://airflow.arpa'
AIRFLOW__WEBSERVER__SECRET_KEY: 'secret_key_here'
```
### Anything else
This only occurs when logging in via Chrome (`115.0.5790.110`), not Firefox
(`112.0.1`). I seem to be getting a similar issue to [authlib
518](https://github.com/lepture/authlib/issues/518) and [authlib
376](https://github.com/lepture/authlib/issues/376).
I looked at [airflow issue
28098](https://github.com/apache/airflow/discussions/28098) and
[Flask-Appbuilder issue
1957](https://github.com/dpgaspar/Flask-AppBuilder/issues/1957) but I'm not
setting `AIRFLOW__WEBSERVER__SESSION_LIFETIME_MINUTES`.
### Are you willing to submit PR?
- [ ] Yes I am willing to submit a PR!
### Code of Conduct
- [X] I agree to follow this project's [Code of
Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)
--
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]