Skip to content

Commit 13dee35

Browse files
Merge pull request #348 from supertokens/fix/sdk-issues
fix: Handle edge cases for verify_session decorator
2 parents 105947b + ba35576 commit 13dee35

File tree

4 files changed

+91
-2
lines changed

4 files changed

+91
-2
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88

99
## [unreleased]
1010

11+
### Changes
12+
13+
- Throw error when `verify_sesion` is used with a view that allows `OPTIONS` or `TRACE` requests
14+
- Allow `verify_session` decorator to be with `@app.before_request` in Flask without returning a response
15+
1116

1217
## [0.14.3] - 2023-06-7
1318

supertokens_python/recipe/session/api/implementation.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ async def verify_session(
7373
) -> Union[SessionContainer, None]:
7474
method = normalise_http_method(api_options.request.method())
7575
if method in ("options", "trace"):
76+
if session_required:
77+
raise Exception(f"verify_session cannot be used with {method} method")
7678
return None
7779
incoming_path = NormalisedURLPath(api_options.request.get_path())
7880
refresh_token_path = api_options.config.refresh_token_path

supertokens_python/recipe/session/framework/flask/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ def wrapped_function(*args: Any, **kwargs: Any):
6161
baseRequest.set_session_as_none()
6262
else:
6363
baseRequest.set_session(session)
64-
response = make_response(f(*args, **kwargs))
65-
return response
64+
65+
response = f(*args, **kwargs)
66+
return make_response(response) if response is not None else None
6667

6768
return cast(_T, wrapped_function)
6869

tests/Flask/test_flask.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,3 +683,84 @@ async def test_search_with_provider_google_and_phone_one(driver_config_app: Any)
683683
assert response.status_code == 200
684684
data_json = json.loads(response.data)
685685
assert len(data_json["users"]) == 0
686+
687+
from tests.utils import get_st_init_args
688+
689+
@fixture(scope="function")
690+
def flask_app():
691+
app = Flask(__name__)
692+
Middleware(app)
693+
694+
app.testing = True
695+
696+
counter: Dict[str, int] = {}
697+
698+
@app.before_request # type: ignore
699+
@verify_session(session_required=False)
700+
def audit_request(): # type: ignore
701+
nonlocal counter
702+
703+
user_id = None
704+
s: SessionContainer = g.supertokens
705+
706+
if s:
707+
user_id = s.get_user_id()
708+
print(f"User {user_id} tried to accesss {request.path}")
709+
else:
710+
user_id = "unknown"
711+
print(f"Unknown user tried to access {request.path}")
712+
713+
if request.path != "/stats":
714+
counter[user_id] = counter.get(user_id, 0) + 1
715+
716+
@app.route("/stats") # type: ignore
717+
def test_api(): # type: ignore
718+
return jsonify(counter)
719+
720+
@app.route("/login") # type: ignore
721+
def login(): # type: ignore
722+
user_id = "userId"
723+
s = create_new_session(request, user_id, {}, {})
724+
return jsonify({"user": s.get_user_id()})
725+
726+
@app.route("/ping") # type: ignore
727+
def ping(): # type: ignore
728+
return jsonify({"msg": "pong"})
729+
730+
@app.route("/options-api", methods=["OPTIONS", "GET"]) # type: ignore
731+
@verify_session()
732+
def options_api(): # type: ignore
733+
return jsonify({"msg": "Shouldn't come here"})
734+
735+
return app
736+
737+
def test_verify_session_with_before_request_with_no_response(flask_app: Any):
738+
init(**{**get_st_init_args([session.init(get_token_transfer_method=lambda *_: "cookie")]), "framework": "flask"}) # type: ignore
739+
start_st()
740+
741+
client = flask_app.test_client()
742+
743+
assert client.get("stats").json == {}
744+
745+
assert client.get("/ping").status_code == 200
746+
747+
assert client.get("stats").json == {"unknown": 1}
748+
749+
with pytest.raises(Exception) as e:
750+
client.options("/options-api")
751+
752+
assert str(e.value) == "verify_session cannot be used with options method"
753+
754+
assert client.get("stats").json == {"unknown": 2}
755+
756+
assert client.get("/login").status_code == 200
757+
758+
assert client.get("/stats").json == {"unknown": 3}
759+
760+
assert client.get("/ping").status_code == 200
761+
762+
assert client.get("/stats").json == {"unknown": 3, "userId": 1}
763+
764+
assert client.get("/ping").status_code == 200
765+
766+
assert client.get("/stats").json == {"unknown": 3, "userId": 2}

0 commit comments

Comments
 (0)