Quickstart
This quickstart guides you through building a login or signup flow. Select a framework:- Node.js
- Go
- Python
- Ruby on Rails
- Java
Example apps
Node.js SDK
API reference
Before you start
- Have your
project_idandsecret_keyfrom your Stytch project & environment. - Add
http://localhost:3000/authenticateas a redirect URL in your Dashboard.
Install the Node.js SDK and configure API keys
- Install the SDK:
npm install stytch express express-session
- Then add your Stytch API keys to your project’s
.envfile:
STYTCH_PROJECT_ID="YOUR_STYTCH_PROJECT_ID"
STYTCH_SECRET="YOUR_STYTCH_PROJECT_SECRET"
# Use your Project's 'live' or any available 'test' credentials
Set up your app and login routes
- Initialize the Stytch client with your environment variables.
- Create a
/loginroute that takes in a user’s email address and initiates the login or signup flow.
const express = require('express');
const session = require('express-session');
const stytch = require('stytch');
const app = express();
app.use(express.json());
app.use(session({
resave: true,
saveUninitialized: false,
secret: 'session-signing-secret',
}));
const stytchClient = new stytch.Client({
project_id: process.env.STYTCH_PROJECT_ID,
secret: process.env.STYTCH_SECRET,
});
app.post('/login', async (req, res) => {
const params = {
email: req.body.email,
login_magic_link_url: "http://localhost:3000/authenticate",
signup_magic_link_url: "http://localhost:3000/authenticate",
};
const resp = await stytchClient.magicLinks.email.loginOrCreate(params);
res.json(resp);
});
Add a route to handle Stytch's redirect callback
- Stytch calls your authenticate redirect URL with a token to complete the flow.
- Add an
/authenticateroute to mint a session:
app.get('/authenticate', async (req, res) => {
const token = req.query.token;
const resp = await stytchClient.magicLinks.authenticate({
token,
session_duration_minutes: 60,
});
req.session.session_jwt = resp.session_jwt;
res.redirect('/dashboard');
});
Add a session-protected route
- Create a helper method that authenticates a session.
- Use the method to gate any protected route.
app.get('/dashboard', async (req, res) => {
const sessionJWT = req.session.session_jwt;
if (!sessionJWT) {
res.send("Log in to view this page");
return;
}
const resp = await stytchClient.sessions.authenticate({
session_jwt: sessionJWT,
});
if (resp.status_code !== 200) {
req.session.session_jwt = undefined;
res.send("Log in to view this page");
return;
}
res.send("You're logged in.");
});
Full completed example:
const express = require('express');
const session = require('express-session');
const stytch = require('stytch');
const app = express();
app.use(express.json());
app.use(session({
resave: true,
saveUninitialized: false,
secret: 'session-signing-secret',
}));
const stytchClient = new stytch.Client({
project_id: process.env.STYTCH_PROJECT_ID,
secret: process.env.STYTCH_SECRET,
});
app.post('/login', async (req, res) => {
const params = {
email: req.body.email,
login_magic_link_url: "http://localhost:3000/authenticate",
signup_magic_link_url: "http://localhost:3000/authenticate",
};
const resp = await stytchClient.magicLinks.email.loginOrCreate(params);
res.json(resp);
});
app.get('/authenticate', async (req, res) => {
const token = req.query.token;
const resp = await stytchClient.magicLinks.authenticate({
token,
session_duration_minutes: 60,
});
req.session.session_jwt = resp.session_jwt;
res.redirect('/dashboard');
});
app.get('/dashboard', async (req, res) => {
const sessionJWT = req.session.session_jwt;
if (!sessionJWT) {
res.send("Log in to view this page");
return;
}
const resp = await stytchClient.sessions.authenticate({
session_jwt: sessionJWT,
});
if (resp.status_code !== 200) {
req.session.session_jwt = undefined;
res.send("Log in to view this page");
return;
}
res.send("You're logged in.");
});
app.listen(3000, () => console.log('Server running on http://localhost:3000'));
Install dependencies and configure API keys
net/http, encoding/json) or your preferred HTTP client.Set up your app and login routes
payload := map[string]any{
"email": email,
"login_magic_link_url": "http://localhost:3000/authenticate",
"signup_magic_link_url": "http://localhost:3000/authenticate",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://test.stytch.com/v1/magic_links/email/login_or_create", bytes.NewReader(body))
req.SetBasicAuth(os.Getenv("STYTCH_PROJECT_ID"), os.Getenv("STYTCH_SECRET"))
req.Header.Set("Content-Type", "application/json")
Add a route to handle Stytch's redirect callback
payload := map[string]any{
"token": token,
"session_duration_minutes": 60,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://test.stytch.com/v1/magic_links/authenticate", bytes.NewReader(body))
req.SetBasicAuth(os.Getenv("STYTCH_PROJECT_ID"), os.Getenv("STYTCH_SECRET"))
req.Header.Set("Content-Type", "application/json")
Add a session-protected route
payload := map[string]any{"session_jwt": sessionJWT}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://test.stytch.com/v1/sessions/authenticate", bytes.NewReader(body))
req.SetBasicAuth(os.Getenv("STYTCH_PROJECT_ID"), os.Getenv("STYTCH_SECRET"))
req.Header.Set("Content-Type", "application/json")
Full completed example:
package main
import (
"bytes"
"encoding/json"
"net/http"
"os"
)
func main() {
http.HandleFunc("/login", sendLoginHandler)
http.HandleFunc("/authenticate", authenticateHandler)
http.HandleFunc("/dashboard", dashboardHandler)
http.ListenAndServe(":3000", nil)
}
// Implement sendLoginHandler/authenticateHandler/dashboardHandler using the
// requests shown above.
Example apps
Python SDK
API reference
Set up your app and login routes
import requests
resp = requests.post(
"https://test.stytch.com/v1/magic_links/email/login_or_create",
auth=(project_id, secret),
json={
"email": email,
"login_magic_link_url": "http://localhost:3000/authenticate",
"signup_magic_link_url": "http://localhost:3000/authenticate",
},
)
Add a route to handle Stytch's redirect callback
resp = requests.post(
"https://test.stytch.com/v1/magic_links/authenticate",
auth=(project_id, secret),
json={"token": token, "session_duration_minutes": 60},
)
session_jwt = resp.json()["session_jwt"]
Add a session-protected route
resp = requests.post(
"https://test.stytch.com/v1/sessions/authenticate",
auth=(project_id, secret),
json={"session_jwt": session_jwt},
)
Full completed example:
# Combine the login, authenticate, and session check requests in your
# framework of choice (Flask, Django, FastAPI, etc.).
Install dependencies and configure API keys
net/http or your preferred HTTP client.Set up your app and login routes
uri = URI("https://test.stytch.com/v1/magic_links/email/login_or_create")
req = Net::HTTP::Post.new(uri)
req.basic_auth(project_id, secret)
req["Content-Type"] = "application/json"
req.body = {
email: email,
login_magic_link_url: "http://localhost:3000/authenticate",
signup_magic_link_url: "http://localhost:3000/authenticate"
}.to_json
Add a route to handle Stytch's redirect callback
uri = URI("https://test.stytch.com/v1/magic_links/authenticate")
req = Net::HTTP::Post.new(uri)
req.basic_auth(project_id, secret)
req["Content-Type"] = "application/json"
req.body = { token: token, session_duration_minutes: 60 }.to_json
Add a session-protected route
uri = URI("https://test.stytch.com/v1/sessions/authenticate")
req = Net::HTTP::Post.new(uri)
req.basic_auth(project_id, secret)
req["Content-Type"] = "application/json"
req.body = { session_jwt: session_jwt }.to_json
Full completed example:
# Combine the login, authenticate, and session check requests in your
# Rails controllers and routes.
Example apps
Java SDK
API reference
Install dependencies and configure API keys
java.net.http.HttpClient or your preferred HTTP client library.Set up your app and login routes
var payload = """
{
"email": "%s",
"login_magic_link_url": "http://localhost:3000/authenticate",
"signup_magic_link_url": "http://localhost:3000/authenticate"
}
""".formatted(email);
var request = HttpRequest.newBuilder()
.uri(URI.create("https://test.stytch.com/v1/magic_links/email/login_or_create"))
.header("Content-Type", "application/json")
.header("Authorization", basicAuth(projectId, secret))
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
Add a route to handle Stytch's redirect callback
var payload = """
{
"token": "%s",
"session_duration_minutes": 60
}
""".formatted(token);
var request = HttpRequest.newBuilder()
.uri(URI.create("https://test.stytch.com/v1/magic_links/authenticate"))
.header("Content-Type", "application/json")
.header("Authorization", basicAuth(projectId, secret))
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
Add a session-protected route
var payload = """
{
"session_jwt": "%s"
}
""".formatted(sessionJwt);
var request = HttpRequest.newBuilder()
.uri(URI.create("https://test.stytch.com/v1/sessions/authenticate"))
.header("Content-Type", "application/json")
.header("Authorization", basicAuth(projectId, secret))
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
Full completed example:
import java.nio.charset.StandardCharsets;
import java.util.Base64;
private static String basicAuth(String projectId, String secret) {
var token = projectId + ":" + secret;
return "Basic " + Base64.getEncoder().encodeToString(token.getBytes(StandardCharsets.UTF_8));
}
// Wire the requests above into your controllers/routes and store sessionJwt
// in a server-side session or signed cookie.