Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 145 additions & 73 deletions descope/auth.py

Large diffs are not rendered by default.

54 changes: 34 additions & 20 deletions descope/authmethod/enchantedlink.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

from typing import Awaitable, Union

import httpx

from descope._auth_base import AuthBase
Expand All @@ -14,6 +16,7 @@
validate_refresh_token_provided,
)
from descope.exceptions import ERROR_TYPE_INVALID_ARGUMENT, AuthException
from descope.future_utils import futu_apply


class EnchantedLink(AuthBase):
Expand All @@ -23,7 +26,7 @@ def sign_in(
uri: str,
login_options: LoginOptions | None = None,
refresh_token: str | None = None,
) -> dict:
) -> Union[dict, Awaitable[dict]]:
if not login_id:
raise AuthException(
400,
Expand All @@ -37,15 +40,18 @@ def sign_in(
uri = EnchantedLink._compose_signin_url()

response = self._auth.do_post(uri, body, None, refresh_token)
return EnchantedLink._get_pending_ref_from_response(response)
return futu_apply(
response,
lambda response: response.json(),
)

def sign_up(
self,
login_id: str,
uri: str,
user: dict | None,
signup_options: SignUpOptions | None = None,
) -> dict:
) -> Union[dict, Awaitable[dict]]:
if not user:
user = {}

Expand All @@ -61,11 +67,14 @@ def sign_up(
body = EnchantedLink._compose_signup_body(login_id, uri, user, signup_options)
uri = EnchantedLink._compose_signup_url()
response = self._auth.do_post(uri, body, None)
return EnchantedLink._get_pending_ref_from_response(response)
return futu_apply(
response,
lambda response: response.json(),
)

def sign_up_or_in(
self, login_id: str, uri: str, signup_options: SignUpOptions | None = None
) -> dict:
) -> Union[dict, Awaitable[dict]]:
login_options: LoginOptions | None = None
if signup_options is not None:
login_options = LoginOptions(
Expand All @@ -81,23 +90,29 @@ def sign_up_or_in(
)
uri = EnchantedLink._compose_sign_up_or_in_url()
response = self._auth.do_post(uri, body, None)
return EnchantedLink._get_pending_ref_from_response(response)
return futu_apply(
response,
lambda response: response.json(),
)

def get_session(self, pending_ref: str) -> dict:
def get_session(self, pending_ref: str) -> Union[dict, Awaitable[dict]]:
uri = EndpointsV1.get_session_enchantedlink_auth_path
body = EnchantedLink._compose_get_session_body(pending_ref)
response = self._auth.do_post(uri, body, None)

resp = response.json()
jwt_response = self._auth.generate_jwt_response(
resp, response.cookies.get(REFRESH_SESSION_COOKIE_NAME, None), None
return futu_apply(
response,
lambda response: self._auth.generate_jwt_response(
response.json(),
response.cookies.get(REFRESH_SESSION_COOKIE_NAME, None),
None,
),
)
return jwt_response

def verify(self, token: str):
def verify(self, token: str) -> Union[None, Awaitable[None]]:
uri = EndpointsV1.verify_enchantedlink_auth_path
body = EnchantedLink._compose_verify_body(token)
self._auth.do_post(uri, body, None)
response = self._auth.do_post(uri, body, None)
return futu_apply(response, lambda response: None)

def update_user_email(
self,
Expand All @@ -109,7 +124,7 @@ def update_user_email(
template_options: dict | None = None,
template_id: str | None = None,
provider_id: str | None = None,
) -> dict:
) -> Union[dict, Awaitable[dict]]:
if not login_id:
raise AuthException(
400, ERROR_TYPE_INVALID_ARGUMENT, "Identifier cannot be empty"
Expand All @@ -128,7 +143,10 @@ def update_user_email(
)
uri = EndpointsV1.update_user_email_enchantedlink_path
response = self._auth.do_post(uri, body, None, refresh_token)
return EnchantedLink._get_pending_ref_from_response(response)
return futu_apply(
response,
lambda response: response.json(),
)

@staticmethod
def _compose_signin_url() -> str:
Expand Down Expand Up @@ -210,7 +228,3 @@ def _compose_update_user_email_body(
@staticmethod
def _compose_get_session_body(pending_ref: str) -> dict:
return {"pendingRef": pending_ref}

@staticmethod
def _get_pending_ref_from_response(response: httpx.Response) -> dict:
return response.json()
57 changes: 41 additions & 16 deletions descope/authmethod/magiclink.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Iterable
from typing import Awaitable, Iterable, Union

from descope._auth_base import AuthBase
from descope.auth import Auth
Expand All @@ -14,6 +14,7 @@
validate_refresh_token_provided,
)
from descope.exceptions import ERROR_TYPE_INVALID_ARGUMENT, AuthException
from descope.future_utils import futu_apply


class MagicLink(AuthBase):
Expand All @@ -24,7 +25,7 @@ def sign_in(
uri: str,
login_options: LoginOptions | None = None,
refresh_token: str | None = None,
) -> str:
) -> Union[str, Awaitable[str]]:
if not login_id:
raise AuthException(
400,
Expand All @@ -38,7 +39,10 @@ def sign_in(
uri = MagicLink._compose_signin_url(method)

response = self._auth.do_post(uri, body, None, refresh_token)
return Auth.extract_masked_address(response.json(), method)
return futu_apply(
response,
lambda response: Auth.extract_masked_address(response.json(), method),
)

def sign_up(
self,
Expand All @@ -47,7 +51,7 @@ def sign_up(
uri: str,
user: dict | None = None,
signup_options: SignUpOptions | None = None,
) -> str:
) -> Union[str, Awaitable[str]]:
if not user:
user = {}

Expand All @@ -63,15 +67,18 @@ def sign_up(
)
uri = MagicLink._compose_signup_url(method)
response = self._auth.do_post(uri, body, None)
return Auth.extract_masked_address(response.json(), method)
return futu_apply(
response,
lambda response: Auth.extract_masked_address(response.json(), method),
)

def sign_up_or_in(
self,
method: DeliveryMethod,
login_id: str,
uri: str,
signup_options: SignUpOptions | None = None,
) -> str:
) -> Union[str, Awaitable[str]]:
login_options: LoginOptions | None = None
if signup_options is not None:
login_options = LoginOptions(
Expand All @@ -86,17 +93,25 @@ def sign_up_or_in(
)
uri = MagicLink._compose_sign_up_or_in_url(method)
response = self._auth.do_post(uri, body, None)
return Auth.extract_masked_address(response.json(), method)
return futu_apply(
response,
lambda response: Auth.extract_masked_address(response.json(), method),
)

def verify(self, token: str, audience: str | None | Iterable[str] = None) -> dict:
def verify(
self, token: str, audience: str | None | Iterable[str] = None
) -> Union[dict, Awaitable[dict]]:
uri = EndpointsV1.verify_magiclink_auth_path
body = MagicLink._compose_verify_body(token)
response = self._auth.do_post(uri, body, None)
resp = response.json()
jwt_response = self._auth.generate_jwt_response(
resp, response.cookies.get(REFRESH_SESSION_COOKIE_NAME, None), audience
return futu_apply(
response,
lambda response: self._auth.generate_jwt_response(
response.json(),
response.cookies.get(REFRESH_SESSION_COOKIE_NAME, None),
audience,
),
)
return jwt_response

def update_user_email(
self,
Expand All @@ -108,7 +123,7 @@ def update_user_email(
template_options: dict | None = None,
template_id: str | None = None,
provider_id: str | None = None,
) -> str:
) -> Union[str, Awaitable[str]]:
if not login_id:
raise AuthException(
400, ERROR_TYPE_INVALID_ARGUMENT, "Identifier cannot be empty"
Expand All @@ -127,7 +142,12 @@ def update_user_email(
)
uri = EndpointsV1.update_user_email_magiclink_path
response = self._auth.do_post(uri, body, None, refresh_token)
return Auth.extract_masked_address(response.json(), DeliveryMethod.EMAIL)
return futu_apply(
response,
lambda response: Auth.extract_masked_address(
response.json(), DeliveryMethod.EMAIL
),
)

def update_user_phone(
self,
Expand All @@ -140,7 +160,7 @@ def update_user_phone(
template_options: dict | None = None,
template_id: str | None = None,
provider_id: str | None = None,
) -> str:
) -> Union[str, Awaitable[str]]:
if not login_id:
raise AuthException(
400, ERROR_TYPE_INVALID_ARGUMENT, "Identifier cannot be empty"
Expand All @@ -159,7 +179,12 @@ def update_user_phone(
)
uri = EndpointsV1.update_user_phone_magiclink_path
response = self._auth.do_post(uri, body, None, refresh_token)
return Auth.extract_masked_address(response.json(), DeliveryMethod.SMS)
return futu_apply(
response,
lambda response: Auth.extract_masked_address(
response.json(), DeliveryMethod.SMS
),
)

@staticmethod
def _compose_signin_url(method: DeliveryMethod) -> str:
Expand Down
24 changes: 17 additions & 7 deletions descope/authmethod/oauth.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
from typing import Optional
from typing import Awaitable, Optional, Union

from descope._auth_base import AuthBase
from descope.common import EndpointsV1, LoginOptions, validate_refresh_token_provided
from descope.common import (
EndpointsV1,
LoginOptions,
REFRESH_SESSION_COOKIE_NAME,
validate_refresh_token_provided,
)
from descope.exceptions import ERROR_TYPE_INVALID_ARGUMENT, AuthException
from descope.future_utils import futu_apply


class OAuth(AuthBase):
Expand All @@ -12,7 +18,7 @@ def start(
return_url: str = "",
login_options: Optional[LoginOptions] = None,
refresh_token: Optional[str] = None,
) -> dict:
) -> Union[dict, Awaitable[dict]]:
""" """
if not self._verify_provider(provider):
raise AuthException(
Expand All @@ -29,11 +35,15 @@ def start(
uri, login_options.__dict__ if login_options else {}, params, refresh_token
)

return response.json()
return futu_apply(
response,
lambda response: response.json(),
)

def exchange_token(self, code: str) -> dict:
uri = EndpointsV1.oauth_exchange_token_path
return self._auth.exchange_token(uri, code)
def exchange_token(self, code: str) -> Union[dict, Awaitable[dict]]:
return self._auth.exchange_token(
EndpointsV1.oauth_exchange_token_path, code, None
)

@staticmethod
def _verify_provider(oauth_provider: str) -> bool:
Expand Down
Loading
Loading