Authentication

Import your shared auth instance:

import { simple } from '~/lib/simpleLogin'

Redirect to Login

When a user needs to sign in, redirect them to the hosted login UI:

// app/routes/login.tsx
export async function loader() {
  return simple.redirectToAuth()
}

Returns a Response that redirects to a secure login page. The user authenticates using their preferred method.

Handle the Callback

After authentication, the user is redirected to your redirect_uri:

// app/routes/auth.callback.tsx
export async function loader({ request }: { request: Request }) {
  const { response, user } = await simple.handleCallback(request, '/home')

  // Optional: store user in your database
  await db.users.upsert({
    id: user.sub,
    email: user.email,
    name: user.name,
  })

  return response
}

The response sets secure cookies and redirects to /home.

Verify Requests

Protect your routes with authenticate:

// app/routes/dashboard.tsx
export async function loader({ request }: { request: Request }) {
  const session = await simple.authenticate(request)

  if (!session) {
    return simple.redirectToAuth()
  }

  const userId = session.claims.sub

  // Include session.headers - they may contain refreshed tokens
  return new Response(JSON.stringify({ userId }), {
    headers: session.headers,
  })
}

Returns null if not authenticated. Otherwise returns:

  • claims - session info (user id, email, etc.)
  • headers - may contain refreshed tokens, include them in your response

Logout

// app/routes/logout.tsx
export async function loader({ request }: { request: Request }) {
  return simple.logout(request)
}

Revokes the session, clears cookies, redirects to login.


Quick Reference

MethodReturns
redirectToAuth()Response - redirects to login
handleCallback(request, redirectTo){ response, user } - exchanges code, sets cookies
authenticate(request){ claims, headers } or null
logout(request)Response - clears session, redirects to login

Full Example

// app/routes/dashboard.tsx
import { simple } from '~/lib/simpleLogin'

export async function loader({ request }: { request: Request }) {
  const session = await simple.authenticate(request)

  if (!session) {
    return simple.redirectToAuth()
  }

  const data = await getDataForUser(session.claims.sub)

  return new Response(JSON.stringify(data), {
    headers: session.headers,
  })
}

No cookie management, no token handling, automatic session refresh.