Skip to content
Merged
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
3 changes: 1 addition & 2 deletions descope/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ def __init__(
self,
project_id: str,
public_key: str = None,
base_uri: str = None,
skip_verify: bool = False,
):
self.lock_public_keys = Lock()
Expand All @@ -54,7 +53,7 @@ def __init__(
if skip_verify:
self.secure = False

self.base_url = base_uri or DEFAULT_BASE_URL
self.base_url = os.getenv("DESCOPE_BASE_URI", None) or DEFAULT_BASE_URL

if not public_key:
public_key = os.getenv("DESCOPE_PUBLIC_KEY", None)
Expand Down
3 changes: 1 addition & 2 deletions descope/descope_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@ def __init__(
self,
project_id: str,
public_key: str = None,
base_url: str = None,
skip_verify: bool = False,
):
auth = Auth(project_id, public_key, base_url, skip_verify)
auth = Auth(project_id, public_key, skip_verify)
self._auth = auth
self._magiclink = MagicLink(auth)
self._oauth = OAuth(auth)
Expand Down
2 changes: 1 addition & 1 deletion samples/decorators/flask_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ def decorated(*args, **kwargs):
# (ignore return value as anyway we redirect)
f(*args, **kwargs)

return redirect(redirect_url, 302)
return redirect(redirect_url["url"], 302)

return decorated

Expand Down
99 changes: 66 additions & 33 deletions samples/otp_web_sample_app.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,47 @@
import datetime
import json
import os
import sys

from flask import Flask, Response, _request_ctx_stack, jsonify, request
from flask import Flask, Response, jsonify, request

dir_name = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(dir_name, "../"))
from decorators.flask_decorators import ( # noqa: E402;
descope_logout,
descope_validate_auth,
descope_verify_code_by_email,
from descope import ( # noqa: E402
REFRESH_SESSION_COOKIE_NAME,
SESSION_COOKIE_NAME,
AuthException,
DeliveryMethod,
DescopeClient,
)

from descope import AuthException # noqa: E402
from descope import DeliveryMethod, DescopeClient # noqa: E402

APP = Flask(__name__)

PROJECT_ID = ""

# init the DescopeClient
descope_client = DescopeClient(
PROJECT_ID, base_url="https://172.17.0.1:8443", skip_verify=True
)
descope_client = DescopeClient(PROJECT_ID, skip_verify=True)


def set_cookie_on_response(response: Response, data):
cookie_domain = data.get("cookieDomain", "")
if cookie_domain == "":
cookie_domain = None

current_time = datetime.datetime.now()
expire_time = current_time + datetime.timedelta(days=30)

return response.set_cookie(
key=data.get("cookieName", ""),
value=data.get("jwt", ""),
max_age=data.get("cookieMaxAge", int(expire_time.timestamp())),
expires=data.get("cookieExpiration", expire_time),
path=data.get("cookiePath", ""),
domain=cookie_domain,
secure=False, # True
httponly=True,
samesite="None", # "Strict", "Lax", "None"
)


class Error(Exception):
Expand Down Expand Up @@ -52,8 +71,7 @@ def signup():
except AuthException:
return Response("Unauthorized", 401)

response = "This is SignUp API handling"
return jsonify(message=response)
return Response("This is SignUp API handling", 200)


@APP.route("/api/signin", methods=["POST"])
Expand All @@ -68,8 +86,7 @@ def signin():
except AuthException:
return Response("Unauthorized, something went wrong when sending email", 401)

response = "This is SignIn API handling"
return jsonify(message=response)
return Response("This is SignIn API handling", 200)


@APP.route("/api/signuporin", methods=["POST"])
Expand All @@ -84,8 +101,7 @@ def signuporin():
except AuthException:
return Response("Unauthorized, something went wrong when sending email", 401)

response = "This is SignUpOrIn API handling"
return jsonify(message=response)
return Response("This is SignUpOrIn API handling", 200)


@APP.route("/otp/verify", methods=["POST"])
Expand All @@ -101,32 +117,49 @@ def verify():
except AuthException:
return Response("Unauthorized", 401)

response = Response(json.dumps(jwt_response), 200)
return response


@APP.route("/api/verify_by_decorator", methods=["POST"])
@descope_verify_code_by_email(descope_client)
def verify_by_decorator(*args, **kwargs):
claims = _request_ctx_stack.top.claims
data = jwt_response["jwts"]
response = Response(
f"This is Verify code API handling, info example: {json.dumps(jwt_response)}",
200,
)
for _, cookieData in data.items():
set_cookie_on_response(response, cookieData)

response = f"This is a code verification API, claims are: {claims}"
return jsonify(message=response)
return response


# This needs authentication
@APP.route("/api/private", methods=["POST"])
@descope_validate_auth(descope_client)
def private():
response = "This is a private API and you must be authenticated to see this"
return jsonify(message=response)
cookies = request.cookies.copy()
session_token = cookies.get(SESSION_COOKIE_NAME, None)
refresh_token = cookies.get(REFRESH_SESSION_COOKIE_NAME, None)
try:
data = descope_client.validate_session_request(session_token, refresh_token)
except AuthException:
return Response("Access denied", 401)

response = Response(
"This is a private API and you must be authenticated to see this", 200
)
for _, cookieData in data.items():
set_cookie_on_response(response, cookieData)
return response


@APP.route("/api/logout")
@descope_logout(descope_client)
def logout():
response = "Logged out"
return jsonify(message=response)
cookies = request.cookies.copy()
refresh_token = cookies.get(REFRESH_SESSION_COOKIE_NAME)
try:
descope_client.logout(refresh_token)
except AuthException as e:
return Response(f"Logout failed {e}", e.status_code)

response = Response("This is Logout API handling", 200)
response.delete_cookie(SESSION_COOKIE_NAME)
response.delete_cookie(REFRESH_SESSION_COOKIE_NAME)
return response


# This doesn't need authentication
Expand Down