Python Quickstart
This quickstart guide outlines the steps to integrate Stytch’s Consumer Authentication product into a Python application. For this example we’ll be using Flask, but Stytch’s Python SDK is framework agnostic.
Overview
Stytch offers developers a Python SDK that can be used in server-side applications. This guide will walk your through initial set up of a login or create flow using Email Magic Links. Want to skip straight to the source code? Check out an example app here.
Getting Started
1Install Stytch SDK and configure your API Keys
Create a Stytch Consumer Project in your Stytch Dashboard if you haven't already.
Install our Python SDK in your Flask environment:
pip install stytch
Configure your Stytch Project's API keys as environment variables:
STYTCH_PROJECT_ID="YOUR_STYTCH_PROJECT_ID"
STYTCH_SECRET="YOUR_STYTCH_PROJECT_SECRET"
# Use your Project's 'test' or 'live' credentials
2Set up your app and login route
Set up a basic app using the framework of your choice and initialize the Stytch client with the environment variables you set in the previous step. Create a /login route that takes in the user's email address and initiates the sign-up or login flow by calling Stytch.
import os
import dotenv
from flask import Flask, request, redirect, url_for, session
from stytch import Client
from stytch.core.response_base import StytchError
# load the .env file
dotenv.load_dotenv()
# Load stytch client
stytch_client = Client(
project_id=os.getenv("STYTCH_PROJECT_ID"),
secret=os.getenv("STYTCH_SECRET"),
environment="test"
)
app = Flask(__name__)
app.secret_key = 'some-secret-key'
@app.route('/login_or_create_user', methods=['POST'])
def login_or_create_user() -> str:
data = request.get_json()
email = data.get("email", None)
if not email:
return "Email required"
try:
resp = stytch_client.magic_links.email.login_or_create(
email=email
)
except StytchError as e:
return e.details.original_json
return "Email sent! Check your inbox!"
if __name__ == '__main__':
app.run(host='localhost', port=3000, debug=True)
3Add a route to handle redirect callback from Stytch
When a user completes an authentication flow in Stytch, we will call the Redirect URL specified in your Stytch Dashboard with a token used to securely complete the auth flow. By default the redirect URL is set tohttp://localhost:3000/authenticate.
You can read more about redirect URLs and possible token types in this guide.
@app.route('/authenticate', methods=['GET'])
def authenticate() -> str:
token = request.args.get("token", None)
token_type = request.args.get("stytch_token_type", None)
# Distinct token_type for each auth flow
# so you know which authenticate() method to use
if token_type != 'magic_links':
return f"token_type: {token_type} not supported"
try:
resp = stytch_client.magic_links.authenticate(
token=request.args["token"],
session_duration_minutes=60
)
except StytchError as e:
return e.details.original_json
session['stytch_session_token'] = resp.session_token
return f"Hello {resp.user.emails[0].email}"
By specifying session_duration_minutes in your authenticate() call, you will be issued a Session which we'll use in the next step.
4Add session protected route
Add a helper method that returns the session user information, and use it to gate any protected route that should only be accessed by an authenticated user.
@app.route('/profile', methods=["GET"])
def profile():
user = get_authenticated_user()
if not user:
return "Log in to view this page."
return f"Hello, {user.emails[0].email}!"
def get_authenticated_user():
stytch_session = session.get('stytch_session_token')
if not stytch_session:
return None
try:
resp = stytch_client.sessions.authenticate(session_token=stytch_session)
except StytchError as e:
# Session has expired or is invalid, clear it
session.pop("stytch_session_token", None)
return None
return resp.user
5Test your application
Run your Flask application and send a POST request to the /login_or_create_user endpoint with an email address to test the auth flow. You will recieve an email in your inbox with an Email Magic Link, which redirects you to the /authenticate endpoint or the redirect URL you set in your Dashboard.
What's next
Check out our product-specific guides for how to handle full authentication flows for additional products you'd like to support, like OAuth or check out our migration guide to plan your switch to Stytch!
Completed example
Check out the example app here or by running:
git clone https://github.com/stytchauth/stytch-python-magic-links.git
which expands upon the quickstart shown here.
import os
import dotenv
from flask import Flask, request, redirect, url_for, session
from stytch import Client
from stytch.core.response_base import StytchError
# load the .env file
dotenv.load_dotenv()
# Load stytch client
stytch_client = Client(
project_id=os.getenv("STYTCH_PROJECT_ID"),
secret=os.getenv("STYTCH_SECRET"),
environment="test"
)
app = Flask(__name__)
app.secret_key = 'some-secret-key'
@app.route('/login_or_create_user', methods=['POST'])
def login_or_create_user() -> str:
data = request.get_json()
email = data.get("email", None)
if not email:
return "Email required"
try:
resp = stytch_client.magic_links.email.login_or_create(
email=email
)
except StytchError as e:
return e.details.original_json
return "Email sent! Check your inbox!"
@app.route('/authenticate', methods=['GET'])
def authenticate() -> str:
token = request.args.get("token", None)
token_type = request.args.get("stytch_token_type", None)
# Distinct token_type for each auth flow
# so you know which authenticate() method to use
if token_type != 'magic_links':
return f"token_type: {token_type} not supported"
try:
resp = stytch_client.magic_links.authenticate(
token=request.args["token"],
session_duration_minutes=60
)
except StytchError as e:
return e.details.original_json
session['stytch_session_token'] = resp.session_token
return redirect(url_for("profile"))
@app.route('/profile', methods=["GET"])
def profile():
user = get_authenticated_user()
if not user:
return "Log in to view this page."
return f"Hello, {user.emails[0].email}!"
@app.route('/logout', methods=["GET"])
def logout():
session.pop("stytch_session_token", None)
return redirect(url_for("profile"))
def get_authenticated_user():
stytch_session = session.get('stytch_session_token')
if not stytch_session:
return None
try:
resp = stytch_client.sessions.authenticate(session_token=stytch_session)
except StytchError as e:
# Session has expired or is invalid, clear it
session.pop("stytch_session_token", None)
return None
return resp.user
if __name__ == '__main__':
app.run(host='localhost', port=3000, debug=True)