npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hlao-adapter/google-sso-oauth

v0.1.0

Published

Google OAuth 2.0 authorization-code flow with server-side sessions. Express-compatible middleware for HLAO deployments where the app owns the login flow.

Downloads

63

Readme

@hlao-adapter/google-sso-oauth

Reference implementation of an HLAO verifyActor source using Google OAuth 2.0 authorization-code flow with server-side sessions. Express-compatible middleware for HLAO deployments where the app owns the login flow itself.

When to reach for this shape

Your app is server-rendered (like @hlao/oversight) and the browser navigates through your app's own login redirect. You want cookies + sessions, not bearer tokens on every request.

Not the right shape if:

Install

npm install @hlao-adapter/google-sso-oauth
# express is a peer dep; you provide the version

Wire it up

import express from "express";
import {
  InMemorySessionStore,
  createGoogleOauthAdapter,
} from "@hlao-adapter/google-sso-oauth";

const adapter = createGoogleOauthAdapter(
  {
    clientId: process.env.GOOGLE_OAUTH_CLIENT_ID!,
    clientSecret: process.env.GOOGLE_OAUTH_CLIENT_SECRET!,
    redirectUri: process.env.GOOGLE_OAUTH_REDIRECT_URI!,
    stateSigningSecret: process.env.GOOGLE_OAUTH_STATE_SIGNING_SECRET!,
    hostedDomain: process.env.GOOGLE_OAUTH_HOSTED_DOMAIN,
  },
  { sessionStore: new InMemorySessionStore() },
);

const app = express();
app.use(adapter.sessionMiddleware);

app.get("/auth/google/start", adapter.startHandler);
app.get("/auth/google/callback", adapter.callbackHandler);
app.post("/auth/logout", adapter.logoutHandler);

// Protect a route: redirect to /auth/google/start if no session.
app.get("/reviews", (req, res, next) => {
  if (req.hlaoActor === undefined) {
    return res.redirect(`/auth/google/start?redirect=${encodeURIComponent(req.originalUrl)}`);
  }
  next();
});

// Wire runner:
const runner = createRunner({
  gate,
  sink,
  artifactStore,
  verifyPassport,
  verifyActor: adapter.verifyActor, // <-- ADR-0020 seam
});

// In the approve/deny handler:
app.post("/reviews/:id/action", async (req, res) => {
  if (req.hlaoActor === undefined) return res.status(401).send("no session");
  await runner.approveReview({
    workspaceRunId: req.params.id,
    actorHumanId: req.hlaoActor.actorId,
    reason: req.body.reason,
  });
  res.redirect("/reviews");
});

Handlers exported

| Handler | Route | What it does | | -------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------- | | startHandler | GET /auth/google/start | Signs a state parameter, builds Google's authorize URL, redirects. | | callbackHandler | GET /auth/google/callback | Validates state, exchanges code, creates a session, sets a signed cookie, redirects. | | sessionMiddleware | Global | Reads the session cookie, populates req.hlaoActor if valid. Silent on missing. | | logoutHandler | POST /auth/logout | Destroys the session, clears the cookie, redirects to defaultRedirectPath. | | verifyActor | Runner dep | Returns true iff the actor id has an active session. |

What the callback checks

  • state parameter is a valid HMAC-signed JWT that has not expired. Prevents CSRF and forged callbacks.
  • Google's token endpoint returned a 200 with an id_token.
  • email claim exists.
  • email_verified is true.
  • hd claim matches hostedDomain (if configured).
  • email is in allowedActorIds (if configured).

Failing any check aborts the callback with 403 or 400, no session created.

Session store

Ships an in-memory reference. For multi-process / durable deployments:

import type { SessionStore, SessionData } from "@hlao-adapter/google-sso-oauth";

class RedisSessionStore implements SessionStore {
  async create(data: SessionData): Promise<string> { ... }
  async get(sessionId: string): Promise<SessionData | null> { ... }
  async destroy(sessionId: string): Promise<void> { ... }
}

Pass it as sessionStore in the adapter options.

Configuration

| Field | Purpose | Required | | ------------------------ | ---------------------------------------------------------------------- | -------- | | clientId | Google OAuth 2.0 web client id | Yes | | clientSecret | Google OAuth 2.0 web client secret | Yes | | redirectUri | Absolute callback URL registered in Google Cloud Console | Yes | | stateSigningSecret | 32+ byte HMAC secret for signing state parameters and session cookies | Yes | | hostedDomain | Enforce Workspace domain via hd claim | No | | allowedActorIds | Explicit email allowlist enforced at session creation | No | | sessionCookieName | Cookie name. Default hlao_session. | No | | sessionTtlMs | Session lifetime. Default 24h. | No | | cookieDomain | Cookie Domain attribute. Default browser-inferred. | No | | cookieSecure | Secure cookie attribute. Default true (only false for local http dev). | No | | defaultRedirectPath | Path to redirect after login when state has no explicit target. | No |

How to obtain credentials

  1. Google Cloud Console → APIs & Services → OAuth consent screen: configure. Add email and profile scopes.
  2. APIs & Services → Credentials → Create credentials → OAuth client ID → Web application. Add your redirect URI as an authorized redirect URI.
  3. Copy the client ID and client secret to your .env.
  4. Generate a 32-byte HMAC secret:
    openssl rand -hex 32
    Store it as GOOGLE_OAUTH_STATE_SIGNING_SECRET.

Local development

For local http:// testing, set cookieSecure: false to allow cookies over http.

cp .env.example .env
pnpm install
pnpm --filter @hlao-adapter/google-sso-oauth build
pnpm --filter @hlao-adapter/google-sso-oauth test