Skip to content

Commit

Permalink
Validate oauth token using before_request
Browse files Browse the repository at this point in the history
 * Uses FLASK_APP_MUTATOR in superset config
 * Refreshing tokens could be enabled via flag if required, but needs work
  • Loading branch information
rad-pat committed Jun 25, 2024
1 parent 6262ebf commit 5d40f64
Showing 1 changed file with 69 additions and 17 deletions.
86 changes: 69 additions & 17 deletions plaid/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@


log = logging.getLogger(__name__)
USE_REFRESH_TOKENS = False


def get_project_role_name(project_id: str) -> str:
Expand Down Expand Up @@ -390,24 +391,75 @@ def add_user_to_project(self, user, project_id):
"Appended %s to %s roles list.", role.name, user.username
)

def has_access(self, permission_name: str, view_name: str) -> bool:
# check token expiry and logout, then continue previous auth check
def set_oauth_session(self, provider, oauth_response):
"""
Set the current session with OAuth token dict
"""
# Save users token_dict on encrypted session cookie
if USE_REFRESH_TOKENS:
session["oauth_token_dict"] = oauth_response
super().set_oauth_session(provider, oauth_response)

def has_oauth_token(self):
if self.auth_type == AUTH_OAUTH:
if 'oauth' in session:
token, secret = session['oauth']
# provider = session["oauth_provider"]
if not token_is_valid(token):
logout_user()
session.clear()

elif self.auth_type == AUTH_OID:
if 'token' in session:
token = session['token']
if not token_is_valid(token):
logout_user()
session.clear()

return super().has_access(permission_name, view_name)
return 'oauth' in session
if self.auth_type == AUTH_OID:
return 'token' in session
return False

def validate_oauth_token(self):
def _internal_validate():
try:
if self.auth_type == AUTH_OAUTH:
if 'oauth' in session:
# Basic validation of token expiry
token, secret = session['oauth']
if token_is_valid(token):
return True

if USE_REFRESH_TOKENS:
# to do the below, it needs custom `set_oauth_session` to save the `oauth_token_dict`
provider = session["oauth_provider"]
token_dict = session['oauth_token_dict']
logging.info('Provider %s, Token %s', provider, token_dict)
# this will refresh the token if it is expired (via `token_update` listener)
self.appbuilder.sm.oauth_remotes[provider].token = token_dict
user_resp = self.appbuilder.sm.oauth_remotes[provider].get("userinfo")
user_resp.raise_for_status()
logging.info('Got user response')
# ToDo - probably should check token now refreshed, or use the introspection

#ToDo - I could not get introspection to work, I was calling from FlaskOAuth2App, but needs to be and OAuth2Session which is the _get_oauth_client() of the Flask thing
# maybe we don't need to introspect anyway, can just check expiry.

# # new token now stored in session
# token_dict = session['oauth_token_dict']
# logging.info('Provider %s, Revised Token %s', provider, token_dict)
# token_endpoint = self.appbuilder.sm.oauth.plaidkeycloak.access_token_url
# intro_resp = self.appbuilder.sm.oauth_remotes[provider].introspect_token(token_endpoint, token=token_dict)
# intro_resp.raise_for_status()
# logging.info('Did introspection')
# token_info = intro_resp.json()
# if token_info['active']:
# return True

elif self.auth_type == AUTH_OID:
if 'token' in session:
token = session['token']
if token_is_valid(token):
return True

return False

except Exception as e:
logging.exception('Failed to validate oauth token: %s', e)
return False

result = _internal_validate()
if not result:
logout_user()
session.clear()
return result


def token_is_valid(access_token):
Expand Down

0 comments on commit 5d40f64

Please sign in to comment.