In this article
March 10, 2026
March 10, 2026

How to add auth to your Replit app with WorkOS

A step-by-step tutorial to adding authentication to your Replit app with WorkOS AuthKit.

Replit Agent is one of the fastest ways to go from idea to deployed app. Describe what you want to build, and Replit's AI writes the code, sets up the database, and publishes it, all without leaving your browser. It's genuinely impressive for getting prototypes off the ground quickly.

But there's one thing most Replit apps need before you can share them with real users: proper authentication. Replit ships its own built-in option (Replit Auth) which is great if you're exploring an idea or building a prototype you might throw away. It wires up automatically with a single Agent prompt, with no external accounts or configuration required.

The moment your app is real, though, Replit Auth starts to show its limits. It has no support for enterprise SSO, no audit logs, no directory sync, and it's coupled to Replit's infrastructure, so if you ever move off the platform, your auth doesn't come with you. For a B2B app in particular, enterprise customers will ask about SSO with their Okta or Azure AD tenant before they ever talk pricing.

WorkOS AuthKit gives you a production-ready auth layer with email/password, social login, passwordless auth, and enterprise SSO; all without rebuilding your app from scratch. In this tutorial, we'll walk through adding it to a Replit-generated Node.js/Express app step by step.

Prerequisites

  • A Replit app. We'll use Node.js/Express stack for this tutorial but the same WorkOS concepts apply to other stacks. See WorkOS's other SDKs for Python, Go, Ruby, and more.
  • A WorkOS account (free for up to 1 million active users, no credit card required).

Step 1: Install the WorkOS Node SDK

Open the Shell tab in your Replit workspace and install the WorkOS Node SDK:

  
npm install @workos-inc/node
  

Also install cookie-parser for session management, and dotenv if your app doesn't already use it:

  
npm install cookie-parser dotenv
  

Step 2: Configure your WorkOS dashboard

Before writing any code, you need to configure two things in the WorkOS dashboard.

  1. Set a redirect URI → this is the callback endpoint WorkOS will redirect to after a user authenticates. Go to the Redirects section of the Dashboard and add: http://localhost:3000/callback
  2. Set a sign-in endpoint → this tells AuthKit where to send users if they land on the hosted sign-in page directly (e.g. from a bookmarked link or a password reset email). In the same Redirects section, set your sign-in endpoint to: http://localhost:3000/login
Screenshot of WorkOS dashboard, showing where to configure the Redirect URIs
WorkOS dashboard > Redirects

You'll update both of these to your production domain before deploying.

Step 3: Add your secrets

Grab your API key and client ID from the WorkOS dashboard.

Screenshot of WorkOS dashboard where you can copy the environment variables to configure
WorkOS dashboard

In Replit, never put credentials in your code. Use the Secrets tab in the left sidebar (the padlock icon) to add the following:

  
WORKOS_API_KEY        sk_example_123456789
WORKOS_CLIENT_ID      client_123456789
WORKOS_COOKIE_PASSWORD  <your-generated-password>
  

WORKOS_COOKIE_PASSWORD encrypts the session cookie and must be exactly 32 characters. Generate one in the Shell:

  
openssl rand -base64 32
  

Replit automatically injects Secrets as environment variables at runtime, so process.env.WORKOS_API_KEY will work in your code without any extra configuration.

Step 4: Initialize the WorkOS client

At the top of your main server file (typically index.js or server.js), initialize the WorkOS client and set up cookie parsing:

  
// index.js
require('dotenv').config();
const express = require('express');
const cookieParser = require('cookie-parser');
const { WorkOS } = require('@workos-inc/node');

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

const workos = new WorkOS(process.env.WORKOS_API_KEY, {
  clientId: process.env.WORKOS_CLIENT_ID,
});
  

Step 5: Add the login route

This route generates an AuthKit authorization URL and redirects the user to WorkOS's hosted sign-in page:

  
// Redirect users to WorkOS-hosted sign-in
app.get('/login', (req, res) => {
  const authorizationUrl = workos.userManagement.getAuthorizationUrl({
    provider: 'authkit',
    redirectUri: process.env.WORKOS_REDIRECT_URI || 'http://localhost:3000/callback',
    clientId: process.env.WORKOS_CLIENT_ID,
  });

  res.redirect(authorizationUrl);
});
  

Also add WORKOS_REDIRECT_URI to your Replit Secrets:

  
WORKOS_REDIRECT_URI   http://localhost:3000/callback
  

Step 6: Add the callback route

After a user authenticates, WorkOS redirects them to your callback route with an authorization code. Exchange it for a session and store it in an encrypted cookie:

  
app.get('/callback', async (req, res) => {
  const code = req.query.code;

  if (!code) {
    return res.status(400).send('No code provided');
  }

  try {
    const { user, sealedSession } = await workos.userManagement.authenticateWithCode({
      clientId: process.env.WORKOS_CLIENT_ID,
      code,
      session: {
        sealSession: true,
        cookiePassword: process.env.WORKOS_COOKIE_PASSWORD,
      },
    });

    // Store the encrypted session in a cookie
    res.cookie('wos-session', sealedSession, {
      path: '/',
      httpOnly: true,
      secure: true,
      sameSite: 'lax',
    });

    // Redirect to your app's main page
    return res.redirect('/dashboard');
  } catch (error) {
    console.error('Auth error:', error);
    return res.redirect('/login');
  }
});
  

Step 7: Create an auth middleware

This middleware reads the session cookie on every request. If the session is valid, it attaches the user to req. If the session has expired, it attempts to refresh it automatically. If there's no session at all, it redirects to login:

  
async function withAuth(req, res, next) {
  const session = workos.userManagement.loadSealedSession({
    sessionData: req.cookies['wos-session'],
    cookiePassword: process.env.WORKOS_COOKIE_PASSWORD,
  });

  const { authenticated, reason } = await session.authenticate();

  if (authenticated) {
    return next();
  }

  // No session cookie — send to login
  if (reason === 'no_session_cookie_provided') {
    return res.redirect('/login');
  }

  // Session expired — try to refresh it
  try {
    const { authenticated: refreshed, sealedSession } = await session.refresh();

    if (!refreshed) {
      return res.redirect('/login');
    }

    // Update the cookie with the refreshed session
    res.cookie('wos-session', sealedSession, {
      path: '/',
      httpOnly: true,
      secure: true,
      sameSite: 'lax',
    });

    // Redirect to the same route with the fresh session
    return res.redirect(req.originalUrl);
  } catch {
    res.clearCookie('wos-session');
    return res.redirect('/login');
  }
}
  

Step 8: Protect your routes

Apply the withAuth middleware to any route that requires a signed-in user. Use loadSealedSession to retrieve the user object inside the route:

  
// Public route — no auth required
app.get('/', (req, res) => {
  res.send('<h1>Welcome</h1><p><a href="/login">Sign in</a></p>');
});

// Protected route — auth required
app.get('/dashboard', withAuth, async (req, res) => {
  const session = workos.userManagement.loadSealedSession({
    sessionData: req.cookies['wos-session'],
    cookiePassword: process.env.WORKOS_COOKIE_PASSWORD,
  });

  const { user } = await session.authenticate();

  res.send(`
    <h1>Dashboard</h1>
    <p>Welcome back, ${user.firstName || user.email}</p>
    <form action="/logout" method="POST">
      <button type="submit">Sign out</button>
    </form>
    <!-- Your existing Replit-generated app content goes here -->
  `);
});
  

Step 9: Add a logout route

End the session by getting the logout URL from WorkOS, clearing the cookie, and redirecting:

  
app.post('/logout', async (req, res) => {
  const session = workos.userManagement.loadSealedSession({
    sessionData: req.cookies['wos-session'],
    cookiePassword: process.env.WORKOS_COOKIE_PASSWORD,
  });

  const logoutUrl = await session.getLogoutUrl();

  res.clearCookie('wos-session');
  res.redirect(logoutUrl);
});
  

!!Make sure you've configured a Sign-out redirect in the WorkOS Dashboard under Redirects. Without it, users will see an error after signing out.!!

Testing it in Replit

Click Run in your Replit workspace. In the web preview, navigate to /login. You'll be redirected to the WorkOS-hosted AuthKit sign-in page. Create an account and you'll land back in your app as an authenticated user.

To confirm it's all wired up, open the WorkOS Dashboard and check the Users section. Your newly created account should appear there.

Deploying to production

When you're ready to deploy, click Deploy in Replit. Once you have your .replit.app URL, do two things:

Update your Replit Secrets with your production values:

  
WORKOS_REDIRECT_URI   https://your-app.replit.app/callback
  

In the WorkOS Dashboard under Redirects:

  1. Add https://your-app.replit.app/callback as an allowed redirect URI.
  2. Update the sign-in endpoint to https://your-app.replit.app/login.
  3. Configure a sign-out redirect for after users log out.

What you get for free

Once AuthKit is wired up, you're not just getting a login form. WorkOS handles:

Next steps

With proper auth in place, your Replit app is ready for real users. If you're targeting businesses or enterprise customers, WorkOS also gives you:

  • Enterprise SSO: When an enterprise customer wants to sign in with Okta, Azure AD, or Google Workspace, WorkOS handles the full SAML/OIDC flow automatically.
  • Directory Sync: Automatically provision and deprovision users from Okta, Azure AD, and more.
  • Audit Logs: A tamper-proof record of every action in your app.
  • Radar: Realtime protection against bots, fraud, and abuse.
  • Feature Flags: Manage rollout of new features for specific users and organizations.
  • And more.

All of these can be added incrementally as your needs grow.

Get started with WorkOS →

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.