使用 Flask-Appbuilder 旋转 consumer_secret
Rotating consumer_secret with Flask-Appbuilder
有一个带有自定义 SecurityManager
的 Flask-Appbuilder 应用可以查找从浏览器获取的用户令牌。我们在应用程序启动时获取客户端凭据。在凭证轮换之前它工作正常。
是否有一个扩展点,我可以在其中实现从外部资源请求 customer_id
和 customer_secret
?
SecurityManager
实现:
class MySecurityManager(SecurityManager):
TOKENINFO_URL = "..."
USERINFO_URL = ".../{}"
def __init__(self, appbuilder):
super(MySecurityManager, self).__init__(appbuilder)
def get_oauth_user_info(self, provider, resp=None):
"""
We authenticate users against Our OAuth provider
"""
if provider == 'MyProvider':
tokeninfo = self.appbuilder.sm.oauth_remotes[provider].get(self.TOKENINFO_URL)
uid = tokeninfo.data.get('uid')
user = self.appbuilder.sm.oauth_remotes[provider].get(self.USERINFO_URL.format(uid))
log.debug("Token info: {0}".format(tokeninfo.data))
log.debug("User info: {0}".format(user.data))
return {'username': tokeninfo.data.get('uid', ''),
'email': user.data.get('email', ''),
'first_name': user.data.get('name', '').split(" ")[0],
'last_name': user.data.get('name', '').split(" ")[-1]}
else:
return super(MySecurityManager, self).get_oauth_user_info(provider, resp=None)
config.py
:
OAUTH_PROVIDERS = [
{
'name': 'MyProvider',
'icon': ...,
'token_key': ...,
'remote_app': {
'base_url': ...,
'consumer_key': SUPERSET_OAUTH_CONSUMER_KEY,
'consumer_secret': SUPERSET_OAUTH_CONSUMER_SECRET,
'request_token_params': {
'scope': ...,
},
'request_token_url': ...,
'access_token_url': ...,
'authorize_url': ...,
}
}
]
我通过覆盖 get oauth_providers 表单 https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/manager.py#L306 解决了这个问题。
举个例子:
@property
def oauth_providers(self):
providers = self.appbuilder.get_app.config['OAUTH_PROVIDERS']
for provider in providers:
if provider['name'] == 'XXXX':
# rotate logic here
provider['remote_app']['consumer_key'] = xxxxx
provider['remote_app']['consumer_secret'] = xxxx
return providers
有一个带有自定义 SecurityManager
的 Flask-Appbuilder 应用可以查找从浏览器获取的用户令牌。我们在应用程序启动时获取客户端凭据。在凭证轮换之前它工作正常。
是否有一个扩展点,我可以在其中实现从外部资源请求 customer_id
和 customer_secret
?
SecurityManager
实现:
class MySecurityManager(SecurityManager):
TOKENINFO_URL = "..."
USERINFO_URL = ".../{}"
def __init__(self, appbuilder):
super(MySecurityManager, self).__init__(appbuilder)
def get_oauth_user_info(self, provider, resp=None):
"""
We authenticate users against Our OAuth provider
"""
if provider == 'MyProvider':
tokeninfo = self.appbuilder.sm.oauth_remotes[provider].get(self.TOKENINFO_URL)
uid = tokeninfo.data.get('uid')
user = self.appbuilder.sm.oauth_remotes[provider].get(self.USERINFO_URL.format(uid))
log.debug("Token info: {0}".format(tokeninfo.data))
log.debug("User info: {0}".format(user.data))
return {'username': tokeninfo.data.get('uid', ''),
'email': user.data.get('email', ''),
'first_name': user.data.get('name', '').split(" ")[0],
'last_name': user.data.get('name', '').split(" ")[-1]}
else:
return super(MySecurityManager, self).get_oauth_user_info(provider, resp=None)
config.py
:
OAUTH_PROVIDERS = [
{
'name': 'MyProvider',
'icon': ...,
'token_key': ...,
'remote_app': {
'base_url': ...,
'consumer_key': SUPERSET_OAUTH_CONSUMER_KEY,
'consumer_secret': SUPERSET_OAUTH_CONSUMER_SECRET,
'request_token_params': {
'scope': ...,
},
'request_token_url': ...,
'access_token_url': ...,
'authorize_url': ...,
}
}
]
我通过覆盖 get oauth_providers 表单 https://github.com/dpgaspar/Flask-AppBuilder/blob/master/flask_appbuilder/security/manager.py#L306 解决了这个问题。 举个例子:
@property
def oauth_providers(self):
providers = self.appbuilder.get_app.config['OAUTH_PROVIDERS']
for provider in providers:
if provider['name'] == 'XXXX':
# rotate logic here
provider['remote_app']['consumer_key'] = xxxxx
provider['remote_app']['consumer_secret'] = xxxx
return providers