Skip to content

Commit 181f423

Browse files
Merge pull request #262 from supertokens/feat/header-based-auth
feat: Introduce header based auth along with existing cookie based auth
2 parents a3dd752 + 4f2cccc commit 181f423

File tree

75 files changed

+2209
-863
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+2209
-863
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,24 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## unreleased
9+
10+
### Breaking changes
11+
12+
- The frontend SDK should be updated to a version supporting the header-based sessions!
13+
- supertokens-auth-react: >= 0.32.0
14+
- supertokens-web-js: >= 0.5.0
15+
- supertokens-website: >= 16.0.0
16+
- supertokens-react-native: >= 4.0.0
17+
- !!!TODO: re-check before release and add mobile SDKs
18+
- Only supporting FDI 1.16
19+
20+
### Added
21+
22+
- Added support for authorizing requests using the `Authorization` header instead of cookies
23+
- Added `get_token_transfer_method` config option
24+
- Check out https://supertokens.com/docs/thirdpartyemailpassword/common-customizations/sessions/token-transfer-method for more information
25+
26+
927
# [0.11.13] - 2023-01-06
1028

1129
- Add missing `original` attribute to flask response and remove logic for cases where `response` is `None`

examples/with-django/with-thirdpartyemailpassword/project/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def get_website_domain():
6565
framework="django",
6666
mode="wsgi",
6767
recipe_list=[
68-
session.init(),
68+
session.init(get_token_transfer_method=lambda _, __, ___: "cookie"),
6969
emailverification.init("REQUIRED"),
7070
thirdpartyemailpassword.init(
7171
providers=[

examples/with-fastapi/with-thirdpartyemailpassword/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ def get_website_domain():
5555
),
5656
framework="fastapi",
5757
recipe_list=[
58-
session.init(),
58+
session.init(get_token_transfer_method=lambda _, __, ___: "cookie"),
5959
emailverification.init("REQUIRED"),
6060
thirdpartyemailpassword.init(
6161
providers=[

examples/with-flask/with-thirdpartyemailpassword/app.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def get_website_domain():
4848
),
4949
framework="flask",
5050
recipe_list=[
51-
session.init(),
51+
session.init(get_token_transfer_method=lambda _, __, ___: "cookie"),
5252
emailverification.init("REQUIRED"),
5353
thirdpartyemailpassword.init(
5454
providers=[

frontendDriverInterfaceSupported.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"_comment": "contains a list of frontend-driver interfaces branch names that this core supports",
33
"versions": [
4-
"1.15"
4+
"1.16"
55
]
66
}

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070

7171
setup(
7272
name="supertokens_python",
73-
version="0.11.13",
73+
version="0.12.0",
7474
author="SuperTokens",
7575
license="Apache 2.0",
7676
author_email="[email protected]",

supertokens_python/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414
SUPPORTED_CDI_VERSIONS = ["2.9", "2.10", "2.11", "2.12", "2.13", "2.14", "2.15"]
15-
VERSION = "0.11.13"
15+
VERSION = "0.12.0"
1616
TELEMETRY = "/telemetry"
1717
USER_COUNT = "/users/count"
1818
USER_DELETE = "/user/remove"

supertokens_python/framework/django/django_middleware.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def middleware(get_response: Any):
2525
from supertokens_python.framework.django.django_request import DjangoRequest
2626
from supertokens_python.framework.django.django_response import DjangoResponse
2727
from supertokens_python.recipe.session import SessionContainer
28-
from supertokens_python.supertokens import manage_cookies_post_response
28+
from supertokens_python.supertokens import manage_session_post_response
2929

3030
from django.http import HttpRequest
3131

@@ -45,7 +45,7 @@ async def __asyncMiddleware(request: HttpRequest):
4545
if hasattr(request, "supertokens") and isinstance(
4646
request.supertokens, SessionContainer # type: ignore
4747
):
48-
manage_cookies_post_response(
48+
manage_session_post_response(
4949
request.supertokens, result # type: ignore
5050
)
5151
if isinstance(result, DjangoResponse):
@@ -79,7 +79,7 @@ def __syncMiddleware(request: HttpRequest):
7979
if hasattr(request, "supertokens") and isinstance(
8080
request.supertokens, SessionContainer # type: ignore
8181
):
82-
manage_cookies_post_response(
82+
manage_session_post_response(
8383
request.supertokens, result # type: ignore
8484
)
8585
return result.response

supertokens_python/framework/django/django_response.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import json
1515
from datetime import datetime
1616
from math import ceil
17-
from typing import Any, Dict, Union
17+
from typing import Any, Dict, Optional
1818

1919
from supertokens_python.framework.response import BaseResponse
2020

@@ -42,7 +42,7 @@ def set_cookie(
4242
value: str,
4343
expires: int,
4444
path: str = "/",
45-
domain: Union[str, None] = None,
45+
domain: Optional[str] = None,
4646
secure: bool = False,
4747
httponly: bool = False,
4848
samesite: str = "lax",
@@ -69,11 +69,14 @@ def set_status_code(self, status_code: int):
6969
def set_header(self, key: str, value: str):
7070
self.response[key] = value
7171

72-
def get_header(self, key: str):
72+
def get_header(self, key: str) -> Optional[str]:
7373
if self.response.has_header(key):
7474
return self.response[key]
7575
return None
7676

77+
def remove_header(self, key: str):
78+
del self.response[key]
79+
7780
def set_json_content(self, content: Dict[str, Any]):
7881
if not self.response_sent:
7982
self.set_header("Content-Type", "application/json; charset=utf-8")

supertokens_python/framework/fastapi/fastapi_middleware.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ async def dispatch(self, request: Request, call_next: RequestResponseEndpoint):
3838
FastApiResponse,
3939
)
4040
from supertokens_python.recipe.session import SessionContainer
41-
from supertokens_python.supertokens import manage_cookies_post_response
41+
from supertokens_python.supertokens import manage_session_post_response
4242

4343
st = Supertokens.get_instance()
4444
from fastapi.responses import Response
@@ -56,7 +56,7 @@ async def dispatch(self, request: Request, call_next: RequestResponseEndpoint):
5656
if hasattr(request.state, "supertokens") and isinstance(
5757
request.state.supertokens, SessionContainer
5858
):
59-
manage_cookies_post_response(request.state.supertokens, result)
59+
manage_session_post_response(request.state.supertokens, result)
6060
if isinstance(result, FastApiResponse):
6161
return result.response
6262
except SuperTokensError as e:

supertokens_python/framework/fastapi/fastapi_response.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
import json
1515
from math import ceil
1616
from time import time
17-
from typing import Any, Dict, Union
17+
from typing import Any, Dict, Optional
1818

1919
from supertokens_python.framework.response import BaseResponse
2020

@@ -44,7 +44,7 @@ def set_cookie(
4444
value: str,
4545
expires: int,
4646
path: str = "/",
47-
domain: Union[str, None] = None,
47+
domain: Optional[str] = None,
4848
secure: bool = False,
4949
httponly: bool = False,
5050
samesite: str = "lax",
@@ -78,9 +78,12 @@ def set_cookie(
7878
def set_header(self, key: str, value: str):
7979
self.response.headers[key] = value
8080

81-
def get_header(self, key: str) -> Union[str, None]:
81+
def get_header(self, key: str) -> Optional[str]:
8282
return self.response.headers.get(key, None)
8383

84+
def remove_header(self, key: str):
85+
del self.response.headers[key]
86+
8487
def set_status_code(self, status_code: int):
8588
if not self.status_set:
8689
self.response.status_code = status_code

supertokens_python/framework/flask/flask_middleware.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def set_before_after_request(self):
3333
app = self.app
3434
from supertokens_python.framework.flask.flask_request import FlaskRequest
3535
from supertokens_python.framework.flask.flask_response import FlaskResponse
36-
from supertokens_python.supertokens import manage_cookies_post_response
36+
from supertokens_python.supertokens import manage_session_post_response
3737

3838
from flask.wrappers import Response
3939

@@ -65,7 +65,7 @@ def _(response: Response):
6565

6666
response_ = FlaskResponse(response)
6767
if hasattr(g, "supertokens") and g.supertokens is not None:
68-
manage_cookies_post_response(g.supertokens, response_)
68+
manage_session_post_response(g.supertokens, response_)
6969

7070
return response_.response
7171

supertokens_python/framework/flask/flask_response.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414
import json
15-
from typing import Any, Dict, List, Union
15+
from typing import Any, Dict, List, Optional
1616

1717
from supertokens_python.framework.response import BaseResponse
1818

@@ -40,7 +40,7 @@ def set_cookie(
4040
value: str,
4141
expires: int,
4242
path: str = "/",
43-
domain: Union[str, None] = None,
43+
domain: Optional[str] = None,
4444
secure: bool = False,
4545
httponly: bool = False,
4646
samesite: str = "lax",
@@ -57,11 +57,14 @@ def set_cookie(
5757
)
5858

5959
def set_header(self, key: str, value: str):
60-
self.response.headers.add(key, value)
60+
self.response.headers.set(key, value)
6161

62-
def get_header(self, key: str) -> Union[None, str]:
62+
def get_header(self, key: str) -> Optional[str]:
6363
return self.response.headers.get(key)
6464

65+
def remove_header(self, key: str):
66+
del self.response.headers[key]
67+
6568
def set_status_code(self, status_code: int):
6669
if not self.status_set:
6770
self.response.status_code = status_code

supertokens_python/framework/response.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# under the License.
1414

1515
from abc import ABC, abstractmethod
16-
from typing import Any, Dict, Union
16+
from typing import Any, Dict, Optional
1717

1818

1919
class BaseResponse(ABC):
@@ -31,19 +31,23 @@ def set_cookie(
3131
# max_age: Union[int, None] = None,
3232
expires: int,
3333
path: str = "/",
34-
domain: Union[str, None] = None,
34+
domain: Optional[str] = None,
3535
secure: bool = False,
3636
httponly: bool = False,
3737
samesite: str = "lax",
3838
):
3939
pass
4040

4141
@abstractmethod
42-
def set_header(self, key: str, value: str):
42+
def set_header(self, key: str, value: str) -> None:
4343
pass
4444

4545
@abstractmethod
46-
def get_header(self, key: str) -> Union[str, None]:
46+
def get_header(self, key: str) -> Optional[str]:
47+
pass
48+
49+
@abstractmethod
50+
def remove_header(self, key: str) -> None:
4751
pass
4852

4953
@abstractmethod

supertokens_python/recipe/emailpassword/api/implementation.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,9 @@ async def sign_in_post(
169169

170170
user = result.user
171171
session = await create_new_session(
172-
api_options.request, user.user_id, user_context=user_context
172+
api_options.request,
173+
user.user_id,
174+
user_context=user_context,
173175
)
174176
return SignInPostOkResult(user, session)
175177

@@ -204,6 +206,8 @@ async def sign_up_post(
204206

205207
user = result.user
206208
session = await create_new_session(
207-
api_options.request, user.user_id, user_context=user_context
209+
api_options.request,
210+
user.user_id,
211+
user_context=user_context,
208212
)
209213
return SignUpPostOkResult(user, session)

supertokens_python/recipe/passwordless/api/implementation.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,11 @@ async def consume_code_post(
288288
)
289289

290290
session = await create_new_session(
291-
api_options.request, user.user_id, {}, {}, user_context=user_context
291+
api_options.request,
292+
user.user_id,
293+
{},
294+
{},
295+
user_context=user_context,
292296
)
293297

294298
return ConsumeCodePostOkResult(

supertokens_python/recipe/session/__init__.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@
1313
# under the License.
1414
from __future__ import annotations
1515

16-
from typing import TYPE_CHECKING, Callable, Union
16+
from typing import TYPE_CHECKING, Any, Callable, Dict, Union
1717

1818
from typing_extensions import Literal
1919

2020
if TYPE_CHECKING:
2121
from ...recipe_module import RecipeModule
22-
from supertokens_python.supertokens import AppInfo
22+
from supertokens_python.supertokens import AppInfo, BaseRequest
23+
from .utils import TokenTransferMethod
2324

2425
from . import exceptions as ex
26+
from . import interfaces, utils
2527
from .recipe import SessionRecipe
26-
from . import utils
27-
from . import interfaces
2828

2929
InputErrorHandlers = utils.InputErrorHandlers
3030
InputOverrideConfig = utils.InputOverrideConfig
@@ -39,6 +39,13 @@ def init(
3939
cookie_same_site: Union[Literal["lax", "none", "strict"], None] = None,
4040
session_expired_status_code: Union[int, None] = None,
4141
anti_csrf: Union[Literal["VIA_TOKEN", "VIA_CUSTOM_HEADER", "NONE"], None] = None,
42+
get_token_transfer_method: Union[
43+
Callable[
44+
[BaseRequest, bool, Dict[str, Any]],
45+
Union[TokenTransferMethod, Literal["any"]],
46+
],
47+
None,
48+
] = None,
4249
error_handlers: Union[InputErrorHandlers, None] = None,
4350
override: Union[InputOverrideConfig, None] = None,
4451
jwt: Union[JWTConfig, None] = None,
@@ -50,6 +57,7 @@ def init(
5057
cookie_same_site,
5158
session_expired_status_code,
5259
anti_csrf,
60+
get_token_transfer_method,
5361
error_handlers,
5462
override,
5563
jwt,

0 commit comments

Comments
 (0)