runlot
DataAuth

env.auth.user

Returns the logged-in user for a request. Returns null for requests that are not logged in.

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const user = await env.auth.user(request);
    if (!user) return Response.redirect(new URL("/__runlot/auth/sign-in", request.url));
    return Response.json({ email: user.email });
  },
};
Always pass the request object to user(). The session lives in the request's cookies or headers, and env outlives any single request. If you omit the argument you get the error env.auth.user(request): pass the request object. Next.js is the exception: with @runlot/next the adapter tracks the current request, so you can call it with no arguments.

User

export interface User {
  id: string;                  // uuid
  email: string | null;
  emailVerified: boolean;
  name: string | null;
  avatarUrl: string | null;
  providers: string[];         // e.g. ["password", "github"]
  createdAt: string;           // ISO 8601
  lastSignInAt: string | null;
}

id is the primary key of runlot_auth.users. Use it to link user-owned rows in your own tables.

create table posts (
  id       bigserial primary key,
  owner_id uuid not null,
  title    text not null
);
const user = await env.auth.user(request);
await env.db.exec("insert into posts (owner_id, title) values ($1, $2)", [user.id, title]);

Logging out

if (url.pathname === "/logout") {
  return new Response(null, {
    status: 302,
    headers: { location: "/", ...(await env.auth.signOut(request)) },
  });
}

signOut deletes the server-side session and returns a headers object that clears the cookie. From a browser form you can also post to POST /__runlot/auth/sign-out.

Managing users

const u = await env.auth.users.get(id);
const byEmail = await env.auth.users.getByEmail("[email protected]");
const page = await env.auth.users.list({ limit: 50, cursor });
await env.auth.users.update(id, { name: "New name" });
await env.auth.users.delete(id);
await env.auth.sessions.revokeAll(userId);

list returns 50 records by default and 200 at most. An empty cursor means you are on the last page.

Browser helpers

import { session, signInUrl, signOutUrl } from "@runlot/auth/client";

const { user } = await session();          // { user: null } when not logged in
location.href = signInUrl("github", { next: "/app" });

This module has no external dependencies. If you pass an external URL to next, it is ignored for security.

Calling without a request

Calling env.auth.user() without a request argument is a feature of the framework adapters. Today the only adapter is @runlot/next for Next.js. Everywhere else, always pass the request object.

On this page