Authdog

Remix

View as Markdown

The @authdog/remix-node SDK integrates Authdog with Remix through a callback-aware loader, client URL cleanup, and HttpOnly session cookies.

Install

npm install @authdog/remix-node

Requires @remix-run/node ^2.15+ and React 18 or 19. Set PK_AUTHDOG (your pk_... key) on the server.

Wrap the app

Run identityLoader() on the route users return to after hosted sign-in. The loader validates ?token= through Authdog userinfo before setting HttpOnly cookies. AuthdogProvider removes the token after the server has handled the request:

// app/root.tsx
import { Outlet, Scripts } from "@remix-run/react"
import { AuthdogProvider, ReloadPage } from "@authdog/remix-node/client"
import { identityLoader } from "@authdog/remix-node"

export const loader = identityLoader()

export default function App() {
  return (
    <AuthdogProvider>
      <Outlet />
      <Scripts />
      <ReloadPage />
    </AuthdogProvider>
  )
}

Resolve the session in a loader

The loader returns { user, isAuthenticated, signinUri }. It revalidates cookie credentials through userinfo, but returning an unauthenticated result does not redirect or deny access. Enforce the result in each protected loader:

// app/routes/profile.tsx
import { useLoaderData } from "@remix-run/react"
import { identityLoader } from "@authdog/remix-node"
import { redirect, type LoaderFunctionArgs } from "@remix-run/node"

const loadIdentity = identityLoader()

export const loader = async (args: LoaderFunctionArgs) => {
  const response = await loadIdentity(args)
  const identity = await response.json()
  if (!identity.isAuthenticated) throw redirect(identity.signinUri)
  return identity
}

export default function Profile() {
  const { user } = useLoaderData<typeof loader>()
  return <p>Signed in as {user.emails?.[0]?.value}</p>
}

If this protected loader may receive the initial callback, preserve the original Response headers when adapting it; otherwise its Set-Cookie headers are lost. A dedicated callback/root loader avoids that issue.

Sign out

Wire a route to logoutLoader, which clears the session and redirects:

// app/routes/logout.ts
import { logoutLoader } from "@authdog/remix-node"
export const loader = logoutLoader

Pair the loader-resolved session with your authorization model to decide what a user may do.

Next steps

Learn more