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

link-auth

v0.1.2

Published

Cloudflare WorkersでLinkAuthアカウント基盤を利用するためのapp側ライブラリです。

Readme

LinkAuth

Cloudflare WorkersでLinkAuthアカウント基盤を利用するためのapp側ライブラリです。

Install

npm install link-auth

Usage

Cloudflare Workers

import { handleAppAuthRequest, loadLinkAuthAppConfig } from "link-auth";

export default {
  async fetch(request, env) {
    const config = loadLinkAuthAppConfig(env);

    return await handleAppAuthRequest({
      authFailedResponse: () => new Response("unauthorized", { status: 401 }),
      config,
      handleRequest: ({ user }) =>
        Response.json({
          discord_id: user.discord_id,
          display_name: user.display_name,
          avatar_url: user.avatar_url,
        }),
      loginResponse: () => Response.redirect("/_auth/account", 302),
      request,
    });
  },
};

静的アセット・画像のlocal session検証

localSessionOnlyを指定すると、対象リクエストではapp session cookieをWorker内で署名検証し、account Workerの/session/verifyへ問い合わせません。画像や静的アセットのように大量リクエストが発生する経路で使用します。

import { handleAppAuthRequest, loadLinkAuthAppConfig } from "link-auth";

export default {
  async fetch(request, env) {
    const config = loadLinkAuthAppConfig(env);

    return await handleAppAuthRequest({
      authFailedResponse: () => new Response("unauthorized", { status: 401 }),
      config,
      handleRequest: ({ request }) => env.ASSETS.fetch(request),
      localSessionOnly: ({ url }) =>
        url.pathname.startsWith("/assets/") ||
        url.pathname.startsWith("/cards/"),
      loginResponse: () => Response.redirect("/_auth/account", 302),
      request,
    });
  },
};

local session検証で確認するのは、cookieの署名、期限、app_idです。ユーザーの無効化、削除、guild退出を即時反映するAPIや重要操作では、getLinkAuthUserまたはhandleAppAuthRequestの通常検証を使います。

APIサーバーのBearer token認証

getLinkAuthUserは、Authorization: Bearer ...またはapp session cookieを検証し、認証済みユーザーを返します。Bearer tokenには、LinkAuthのaccount画面で発行したPersonal Access Tokenを指定します。

import { getLinkAuthUser, loadLinkAuthAppConfig } from "link-auth";

const config = loadLinkAuthAppConfig(process.env);

async function authenticate(request: Request) {
  const user = await getLinkAuthUser({ config, request });

  if (!user) {
    return Response.json({ error: "unauthorized" }, { status: 401 });
  }

  return Response.json({ user });
}

NestJSでは、受け取ったHTTPリクエストからWeb標準のRequestを作ってgetLinkAuthUserへ渡します。

import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
import { getLinkAuthUser, loadLinkAuthAppConfig } from "link-auth";

@Injectable()
export class LinkAuthGuard implements CanActivate {
  private readonly config = loadLinkAuthAppConfig(process.env);

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const req = context.switchToHttp().getRequest();
    const host = req.headers.host;
    const protocol = req.protocol ?? "https";
    const url = `${protocol}://${host}${req.originalUrl ?? req.url}`;
    const request = new Request(url, {
      headers: req.headers,
      method: req.method,
    });
    const user = await getLinkAuthUser({
      config: this.config,
      request,
    });

    if (!user) {
      throw new UnauthorizedException();
    }

    req.linkAuthUser = user;
    return true;
  }
}

curlからは次のように呼び出します。

curl https://api.example.com/api/me \
  -H "Authorization: Bearer lka_pat_xxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Environment

ACCOUNT_URL=https://account.example.com
APP_ID=your-app-id
APP_SESSION_HMAC_SECRET=your-app-session-secret
SESSION_KID=your-session-key-id

API

loadLinkAuthAppConfig(env)

app WorkerのenvからLinkAuth設定を読み込みます。

handleAppAuthRequest(input)

ログイン開始、callback、ログアウト、現在ユーザー取得、app session検証をまとめて処理します。認証済みリクエストではhandleRequestLinkAuthUserを渡します。

localSessionOnlyを指定したリクエストでは、app session cookieをlocal検証します。Bearer token単独ではlocal検証しません。

getLinkAuthUser(input)

Web標準のRequestからBearer tokenまたはapp session cookieを検証し、LinkAuthUserを返します。検証に失敗した場合はnullを返します。

app session cookieでもaccount Workerの/session/verifyへ問い合わせるため、account側の現在状態を確認できます。

getLinkAuthSessionUser(input)

Web標準のRequestからapp session cookieだけをlocal検証し、LinkAuthUserを返します。account Workerへ問い合わせません。検証に失敗した場合はnullを返します。

getLinkAuthSessionToken(input)

Web標準のRequestからapp session cookieのtokenを取り出します。Bearer token単独では返しません。cookieとBearer tokenが両方あり、値が一致しない場合はnullを返します。

getLinkAuthSessionCookieName(appId)

app session cookie名を返します。

LinkAuthUser

type LinkAuthUser = {
  discord_id: string;
  display_name: string;
  role: "user" | "admin";
  status: "active";
  avatar_url: string | null;
  icon_source: "r2" | "none";
  icon_key: string | null;
};