Как использовать пользовательский поставщик [keycloak] для OAuth2.0 во Flask-Appbuilder? - PullRequest
0 голосов
/ 23 мая 2019

Я пытаюсь реализовать keycloak в качестве OAuth2.0 провайдера.У меня есть вся необходимая информация OAUTH_PROVIDER, и я объявил AUTH_TYPE, AUTH_USER_REGISTRATION, AUTH_USER_REGISTRATION_ROLE (см. Код ниже)

AUTH_TYPE = AUTH_OAUTH

AUTH_USER_REGISTRATION = True

AUTH_USER_REGISTRATION_ROLE = "Public"

OAUTH_PROVIDERS = [
 {
   ‘name’: ‘provider_name’,
   ‘icon’: ‘fa-icon’,
   ’token_key’: ‘access_token’, 
   ‘remote_app’: {
     ‘base_url’: ‘https://www.base_url.com‘,
     ‘request_token_params’: {
     ‘scope’: ‘email profile’
     },
     ‘request_token_url’: None,
     ‘access_token_url’: ‘https://www.access_token_url.com’,
     ‘authorize_url': ‘https://www.authorize_url.com',
     ‘consumer_key’: ‘PROVIDER_OAUTH_KEY’,
     ‘consumer_secret’: ‘PROVIDER_OAUTH_SECRET’
    }
  }
]

Поскольку это пользовательский поставщик (за исключением обычного Google,Facebook, ... провайдеры), в моем менеджере безопасности я переопределил функцию get_oauth_user_info , которая объявлена ​​в flask-appbuilder manager.py

    def get_oauth_user_info(self, provider, response=None):
        logging.debug("Oauth2 provider: {0}.".format(provider))
        me = self.appbuilder.sm.oauth_remotes[provider].get("user")
        logging.error(me)
        return {
            "preferred_username": me.data.get("preferred_username",""),
            "first_name": me.data.get("given_name", ""),
            "last_name": me.data.get("family_name", ""),
            "email": me.data.get("email", "")

Я ожидаю, что результаты перенаправят приложение на страницу входа в keycloak, однако в запросе на публикацию выдается следующая ошибка:

DEBUG:flask_oauthlib:Request 'https://...' with 'POST' method
ERROR:flask_appbuilder.security.manager:User info does not have username or email {}
[2019-05-23 12:52:10,130] ERROR in app: Exception on /oauth-authorized/login [GET]
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/usr/local/lib/python3.6/site-packages/flask_appbuilder/security/views.py", line 519, in oauth_authorized
    resp = self.appbuilder.sm.oauth_remotes[provider].authorized_response()

Если у кого-то есть указания относительно того, что я делаю неправильно, пожалуйста, не могли бы вы помочь?я.

1 Ответ

1 голос
/ 23 мая 2019

Вы должны добавить аннотацию @appbuilder.sm.oauth_user_info_getter к get_oauth_user_info функции, как в документации https://flask -appbuilder.readthedocs.io / en / latest / security.html # authentication-oauth

Также измените

me = self.appbuilder.sm.oauth_remotes[provider].get("user") 

на

me = self.appbuilder.sm.oauth_remotes[provider].get("userinfo") 

в случае, если base_url похоже на https://{keycloak-domain}/auth/realms/{realm}/protocol/openid-connect/

...