Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
fix: improve next URL on OAuth (#1668)
* fix: improve next URL on OAuth * add tests and extra dependency for OAuth * lint * fix test * add test for unknown provider * lint * Update flask_appbuilder/security/views.py Co-authored-by: Ash Berlin-Taylor <ash_github@firemirror.com> Co-authored-by: Ash Berlin-Taylor <ash_github@firemirror.com>
- Loading branch information
Showing
5 changed files
with
166 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import os | ||
|
|
||
| from flask_appbuilder.security.manager import AUTH_OAUTH | ||
|
|
||
| basedir = os.path.abspath(os.path.dirname(__file__)) | ||
|
|
||
| SQLALCHEMY_DATABASE_URI = os.environ.get( | ||
| "SQLALCHEMY_DATABASE_URI" | ||
| ) or "sqlite:///" + os.path.join(basedir, "app.db") | ||
|
|
||
| SECRET_KEY = "thisismyscretkey" | ||
|
|
||
| AUTH_TYPE = AUTH_OAUTH | ||
|
|
||
| OAUTH_PROVIDERS = [ | ||
| { | ||
| "name": "google", | ||
| "icon": "fa-google", | ||
| "token_key": "access_token", | ||
| "remote_app": { | ||
| "client_id": "CLIENT_ID", | ||
| "client_secret": "CLIENT_SECRET", | ||
| "api_base_url": "https://www.googleapis.com/oauth2/v2/", | ||
| "client_kwargs": {"scope": "email profile"}, | ||
| "request_token_url": None, | ||
| "access_token_url": "https://accounts.google.com/o/oauth2/token", | ||
| "authorize_url": "https://accounts.google.com/o/oauth2/auth", | ||
| }, | ||
| } | ||
| ] | ||
|
|
||
| # Will allow user self registration | ||
| AUTH_USER_REGISTRATION = True | ||
|
|
||
| # The default user self registration role for all users | ||
| AUTH_USER_REGISTRATION_ROLE = "Admin" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| from flask_appbuilder import SQLA | ||
| from flask_appbuilder.tests.base import FABTestCase | ||
| import jwt | ||
|
|
||
|
|
||
| class UserInfoReponseMock: | ||
| def json(self): | ||
| return { | ||
| "id": "1", | ||
| "given_name": "first-name", | ||
| "family_name": "last-name", | ||
| "email": "user1@fab.org", | ||
| } | ||
|
|
||
|
|
||
| class OAuthRemoteMock: | ||
| def authorize_access_token(self): | ||
| return {"access_token": "some-key"} | ||
|
|
||
| def get(self, item): | ||
| if item == "userinfo": | ||
| return UserInfoReponseMock() | ||
|
|
||
|
|
||
| class APICSRFTestCase(FABTestCase): | ||
| def setUp(self): | ||
| from flask import Flask | ||
| from flask_wtf import CSRFProtect | ||
| from flask_appbuilder import AppBuilder | ||
|
|
||
| self.app = Flask(__name__) | ||
| self.app.config.from_object("flask_appbuilder.tests.config_oauth") | ||
| self.app.config["WTF_CSRF_ENABLED"] = True | ||
|
|
||
| self.csrf = CSRFProtect(self.app) | ||
| self.db = SQLA(self.app) | ||
| self.appbuilder = AppBuilder(self.app, self.db.session) | ||
|
|
||
| def test_oauth_login(self): | ||
| """ | ||
| OAuth: Test login | ||
| """ | ||
| client = self.app.test_client() | ||
|
|
||
| self.appbuilder.sm.oauth_remotes = {"google": OAuthRemoteMock()} | ||
|
|
||
| raw_state = {} | ||
| state = jwt.encode(raw_state, self.app.config["SECRET_KEY"], algorithm="HS256") | ||
|
|
||
| response = client.get(f"/oauth-authorized/google?state={state.decode('utf-8')}") | ||
| self.assertEqual(response.location, "http://localhost/") | ||
|
|
||
| def test_oauth_login_unknown_provider(self): | ||
| """ | ||
| OAuth: Test login with unknown provider | ||
| """ | ||
| client = self.app.test_client() | ||
|
|
||
| self.appbuilder.sm.oauth_remotes = {"google": OAuthRemoteMock()} | ||
|
|
||
| raw_state = {} | ||
| state = jwt.encode(raw_state, self.app.config["SECRET_KEY"], algorithm="HS256") | ||
|
|
||
| response = client.get( | ||
| f"/oauth-authorized/unknown_provider?state={state.decode('utf-8')}" | ||
| ) | ||
| self.assertEqual(response.location, "http://localhost/login/") | ||
|
|
||
| def test_oauth_login_next(self): | ||
| """ | ||
| OAuth: Test login next | ||
| """ | ||
| client = self.app.test_client() | ||
|
|
||
| self.appbuilder.sm.oauth_remotes = {"google": OAuthRemoteMock()} | ||
|
|
||
| raw_state = {"next": ["http://localhost/users/list/"]} | ||
| state = jwt.encode(raw_state, self.app.config["SECRET_KEY"], algorithm="HS256") | ||
|
|
||
| response = client.get(f"/oauth-authorized/google?state={state.decode('utf-8')}") | ||
| self.assertEqual(response.location, "http://localhost/users/list/") | ||
|
|
||
| def test_oauth_login_next_check(self): | ||
| """ | ||
| OAuth: Test login next check | ||
| """ | ||
| client = self.app.test_client() | ||
|
|
||
| self.appbuilder.sm.oauth_remotes = {"google": OAuthRemoteMock()} | ||
|
|
||
| raw_state = {"next": ["http://www.google.com"]} | ||
| state = jwt.encode(raw_state, self.app.config["SECRET_KEY"], algorithm="HS256") | ||
|
|
||
| response = client.get(f"/oauth-authorized/google?state={state.decode('utf-8')}") | ||
| self.assertEqual(response.location, "http://localhost/") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters