Consumer Authentication

/

Quickstarts

/

Quickstarts

/

Node

Node Quickstart

This quickstart guide outlines the steps to integrate Stytch’s Consumer Authentication product into a Node application. For this example we’ll be using Express, but Stytch’s Node SDK is framework agnostic.

Overview

Stytch offers developers a Node 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

1
Install Stytch SDK and configure your API Keys

Create a Stytch Consumer Project in your Stytch Dashboard if you haven't already.

Install our Node SDK in your Express environment:

npm 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

2
Set 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.

const express = require('express');
const stytch = require('stytch');
const session = require('express-session');
const bodyParser = require('body-parser');

const app = express();
app.use(express.json());

/**
 * Express session management
*/
app.use(session({
  resave: true,
  saveUninitialized: false,
  secret: 'session-signing-secret',
  cookie: {maxAge: 60000}
}));

const stytchClient = new stytch.Client({
  project_id: process.env.STYTCH_PROJECT_ID,
  secret: process.env.STYTCH_SECRET,
});

const StytchSessionToken = 'stytch_session_token'

app.post('/login', (req, res) => {
  const email = req.body.email;
  stytchClient.magicLinks.email.loginOrCreate({
    email: email
  })
  .then(response => {
    res.json(response)
  })
  .catch(err => {
    res.status(500).send(err.toString())
  });
});

app.listen(3000, () => console.log('Server running on http://localhost:3000'));

3
Add 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.

app.get('/authenticate', (req, res) => {
  const token = req.query.token;
  const tokenType = req.query.stytch_token_type
  
  // Distinct token_type for each auth flow
  // so you know which authenticate() method to use
  if (tokenType !== 'magic_links') {
    console.error(`Unsupported token type: '${tokenType}'`);
    res.status(400).send();
    return;
  }

  stytchClient.magicLinks.authenticate({
    token: token,
    session_duration_minutes: 60,
  })
  .then(response => {
    // Using express sessions to store the returned session cookie
    req.session.StytchSessionToken = response.session_token
    res.send(`Hello, ${response.user.emails[0].email}!`)
  })
  .catch(err => {
    res.status(401).send(err.toString())
  });
});

4
Add 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.get('/profile', async (req, res) => {
    const user = await getAuthenticatedUser(req);
    if (user) {
      res.send(`Hello, ${user.emails[0].email}!`);
      return;
    }
    res.send("Log in to view this page");
});

async function getAuthenticatedUser(req) {
    const sessionToken = req.session.StytchSessionToken;
    if (!sessionToken) {
      return null;
    }

    const resp = await stytchClient.sessions.authenticate({session_token: sessionToken});
    if (resp.status_code !== 200) {
      console.log('Session invalid or expired');
      req.session.StytchSessionToken = undefined;
      return null;
    }

    req.session.StytchSessionToken = resp.session_token;
    return resp.user;
}

5
Test your application

Run your 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-node-magic-links.git

which expands upon the quickstart shown here.

const express = require('express');
const stytch = require('stytch');
const session = require('express-session');
const bodyParser = require('body-parser');

const app = express();
app.use(express.json());

/**
 * Express session management
*/
app.use(session({
  resave: true,
  saveUninitialized: false,
  secret: 'session-signing-secret',
  cookie: {maxAge: 60000}
}));

const stytchClient = new stytch.Client({
  project_id: process.env.STYTCH_PROJECT_ID,
  secret: process.env.STYTCH_SECRET,
});

const StytchSessionToken = 'stytch_session_token'

app.post('/login', (req, res) => {
  const email = req.body.email;
  stytchClient.magicLinks.email.loginOrCreate({
    email: email
  })
  .then(response => {
    res.json(response)
  })
  .catch(err => {
    res.status(500).send(err.toString())
  });
});

app.get('/authenticate', (req, res) => {
  const token = req.query.token;
  const tokenType = req.query.stytch_token_type
  
  // Distinct token_type for each auth flow
  // so you know which authenticate() method to use
  if (tokenType !== 'magic_links') {
    console.error(`Unsupported token type: '${tokenType}'`);
    res.status(400).send();
    return;
  }

  stytchClient.magicLinks.authenticate({
    token: token,
    session_duration_minutes: 60,
  })
  .then(response => {
    // Using express sessions to store the returned session cookie
    req.session.StytchSessionToken = response.session_token
    res.redirect('/profile')
  })
  .catch(err => {
    res.status(401).send(err.toString())
  });
});

app.get('/profile', async (req, res) => {
    const user = await getAuthenticatedUser(req);
    if (user) {
      res.send(`Hello, ${user.emails[0].email}!`);
      return;
    }
    res.send("Log in to view this page");
});

app.get('/logout', (req, res) => {
  req.session.StytchSessionToken = undefined;
  res.redirect('/profile');
});

async function getAuthenticatedUser(req) {
    const sessionToken = req.session.StytchSessionToken;
    if (!sessionToken) {
      return null;
    }

    const resp = await stytchClient.sessions.authenticate({session_token: sessionToken});
    if (resp.status_code !== 200) {
      console.log('Session invalid or expired');
      req.session.StytchSessionToken = undefined;
      return null;
    }

    req.session.StytchSessionToken = resp.session_token;
    return resp.user;
}

app.listen(3000, () => console.log('Server running on http://localhost:3000'));