Remix Auth Steam Strategy

1.0.4 · active · verified Wed Apr 22

remix-auth-steam provides a specialized authentication strategy for integrating Steam OpenID into Remix applications via the `remix-auth` library. Currently at version 1.0.4, this package acts as a bridge, enabling developers to leverage Steam's authentication flow within their Remix projects on Node.js runtimes. While it doesn't specify a strict release cadence, updates appear to be made on demand to address bug fixes, as seen in recent patch versions. Its primary differentiator is its focused implementation for Steam, building upon the extensible architecture of `remix-auth`. Developers should be aware of its specific dependency on `@remix-run/server-runtime` and `remix-auth` itself, and ensure their Remix environment is configured for server-side operations, as browser or edge worker support for Steam OpenID directly is not fully tested or guaranteed by this package. It ships with TypeScript types for improved developer experience.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates a complete Steam authentication flow in a Remix application, including session management, strategy configuration, and protected routes. It shows how to initialize the `SteamStrategy`, handle Steam callbacks, and display user authentication status.

import { createCookieSessionStorage, redirect } from "@remix-run/node";
import type { LoaderFunction, ActionFunction } from "@remix-run/node";
import { Authenticator } from "remix-auth";
import { SteamStrategy, SteamStrategyVerifyParams } from "remix-auth-steam";
import { useLoaderData, Form, Link } from "@remix-run/react";
import React from "react";

// app/services/session.server.ts
// Helper to calculate cookie expiration
const calculateExpirationDate = (days: number) => {
  const expDate = new Date();
  expDate.setDate(expDate.getDate() + days);
  return expDate;
};

// Session storage setup
export let sessionStorage = createCookieSessionStorage({
  cookie: {
    name: "_session",
    sameSite: "lax",
    path: "/",
    httpOnly: true,
    secrets: [process.env.SESSION_SECRET ?? "super-secret-dev-key"], // IMPORTANT: Use a strong, production secret from environment variables
    secure: process.env.NODE_ENV === "production",
    expires: calculateExpirationDate(7),
  },
});

export let { getSession, commitSession, destroySession } = sessionStorage;

// app/services/auth.server.ts
// Define the User type based on SteamStrategyVerifyParams
export type User = SteamStrategyVerifyParams;

// Create an Authenticator instance
export let authenticator = new Authenticator<User>(sessionStorage);

// Register the SteamStrategy
authenticator.use(
  new SteamStrategy(
    {
      returnURL: "http://localhost:3000/auth/steam/callback",
      apiKey: process.env.STEAM_API_KEY ?? "YOUR_STEAM_API_KEY", // IMPORTANT: Get your API key from https://steamcommunity.com/dev/apikey
    },
    // The verify callback: here you can perform additional checks or database operations
    async (user) => {
      // For this example, we simply return the user data provided by Steam
      console.log("Steam User Authenticated:", user.nickname, user.steamid);
      return user;
    }
  ),
  "steam" // The name of the strategy to be used in authenticate calls
);

// app/routes/auth/steam.tsx
// This route initiates the Steam authentication flow
export let loader: LoaderFunction = async ({ request }) => {
  return authenticator.authenticate("steam", request);
};

// app/routes/auth/steam/callback.tsx
// This route handles the callback from Steam after authentication
export let loader: LoaderFunction = ({ request }) => {
  return authenticator.authenticate("steam", request, {
    successRedirect: "/", // Redirect to home on success
    failureRedirect: "/login", // Redirect to login on failure
  });
};

// app/routes/login.tsx
export default function Login() {
  return (
    <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
      <h1>Login</h1>
      <p>You need to log in to access this page.</p>
      <Link to="/auth/steam">
        <button>Login with Steam</button>
      </Link>
    </div>
  );
}

// app/routes/index.tsx
export let loader: LoaderFunction = async ({ request }) => {
  // Check if the user is authenticated
  const user = await authenticator.isAuthenticated(request);
  return user;
};

export default function Index() {
  const user = useLoaderData<User | null>();

  return (
    <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
      {user ? (
        <>
          <h1>Welcome, {user.nickname}!</h1>
          <p>Your SteamID: {user.steamid}</p>
          <Form action="/logout" method="post">
            <button type="submit">Logout</button>
          </Form>
        </>
      ) : (
        <>
          <h1>Not Authenticated</h1>
          <p>
            <Link to="/login">Login with Steam</Link>
          </p>
        </>
      )}
    </div>
  );
}

// app/routes/logout.tsx
export let action: ActionFunction = async ({ request }) => {
  // Destroy the session and redirect to the login page
  await authenticator.logout(request, { redirectTo: "/login" });
  return redirect("/login");
};

view raw JSON →