SCALE — Build Lab
開発パターン · TYPESCRIPT LIBRARY

外部サービス認証

CATEGORY開発パターン TYPETypeScript Library EFFORT240〜600分 DIFFICULTY
PRIMARY CODE
ts · lib/external-auth.ts
// SCALE Base から分離システム(scale-finance / scale-x / scale-recruit 等)へ
// 認証情報を引き継ぐためのユーティリティ。
//
// クロスドメイン(*.pages.dev は別オリジン)なので localStorage / sessionStorage が共有されない。
// 暫定対応として URL クエリ ?auth=<base64(json)> で受け渡す。
// 受け取った側は最初に sessionStorage に保存してクエリを削除する。
//
// セキュリティ: パスワードは含まない。表示用の id / name / email / allowedSystems のみを渡す。

interface UserLite {
  id: string;
  name: string;
  email: string;
  altEmail?: string;
  role?: string;
  departmentId?: string;
  departmentName?: string;
  avatar?: string;
  allowedSystems?: string[];
}

/**
 * 独自認証システムを持つドメイン(auth クエリ不要・付けると URL がノイズだらけになる)
 * - SCALE CRM (crm.scale-group.co.jp / lead.scale-group.co.jp): D1 + 共通PW(scale2023) の独自認証
 * - 必要に応じて追加
 */
const SKIP_AUTH_DOMAINS = [
  'crm.scale-group.co.jp',
  'lead.scale-group.co.jp',
  'build.scale-group.co.jp', // Astro 静的サイト・auth不要
];

export function withAuthQuery(externalUrl: string, user: UserLite | null | undefined): string {
  if (!user) return externalUrl;
  // 独自認証ドメインには auth クエリを付けない(URLをきれいに保つ)
  if (SKIP_AUTH_DOMAINS.some(d => externalUrl.includes(d))) return externalUrl;
  try {
    // 必要最小限のフィールドだけシリアライズ(パスワードは絶対に含めない)
    const payload: UserLite = {
      id: user.id,
      name: user.name,
      email: user.email,
      altEmail: user.altEmail,
      role: user.role,
      departmentId: user.departmentId,
      departmentName: user.departmentName,
      avatar: user.avatar,
      allowedSystems: user.allowedSystems,
    };
    // UTF-8 セーフな base64
    const json = JSON.stringify(payload);
    const utf8 = new TextEncoder().encode(json);
    let bin = '';
    utf8.forEach(b => { bin += String.fromCharCode(b); });
    const b64 = btoa(bin);
    const sep = externalUrl.includes('?') ? '&' : '?';
    return `${externalUrl}${sep}auth=${encodeURIComponent(b64)}`;
  } catch {
    return externalUrl;
  }
}

前提条件
Tailwind CSS v4TypeScript 5
USE CASES
  • 外部API連携が多いシステム

外部サービス認証

:LiTarget: 用途

Slack / Google / Notion 等の外部サービス認証をまとめて管理。

:LiSparkle: 特徴

  • OAuth管理
  • トークンリフレッシュ
  • 複数プロバイダ対応

:LiCode: 実コード(SCALE Base より自動抽出)

:LiInfo: lib/external-auth.ts の中身そのもの。コピペ即可。

// SCALE Base から分離システム(scale-finance / scale-x / scale-recruit 等)へ
// 認証情報を引き継ぐためのユーティリティ。
//
// クロスドメイン(*.pages.dev は別オリジン)なので localStorage / sessionStorage が共有されない。
// 暫定対応として URL クエリ ?auth=<base64(json)> で受け渡す。
// 受け取った側は最初に sessionStorage に保存してクエリを削除する。
//
// セキュリティ: パスワードは含まない。表示用の id / name / email / allowedSystems のみを渡す。

interface UserLite {
  id: string;
  name: string;
  email: string;
  altEmail?: string;
  role?: string;
  departmentId?: string;
  departmentName?: string;
  avatar?: string;
  allowedSystems?: string[];
}

/**
 * 独自認証システムを持つドメイン(auth クエリ不要・付けると URL がノイズだらけになる)
 * - SCALE CRM (crm.scale-group.co.jp / lead.scale-group.co.jp): D1 + 共通PW(scale2023) の独自認証
 * - 必要に応じて追加
 */
const SKIP_AUTH_DOMAINS = [
  'crm.scale-group.co.jp',
  'lead.scale-group.co.jp',
  'build.scale-group.co.jp', // Astro 静的サイト・auth不要
];

export function withAuthQuery(externalUrl: string, user: UserLite | null | undefined): string {
  if (!user) return externalUrl;
  // 独自認証ドメインには auth クエリを付けない(URLをきれいに保つ)
  if (SKIP_AUTH_DOMAINS.some(d => externalUrl.includes(d))) return externalUrl;
  try {
    // 必要最小限のフィールドだけシリアライズ(パスワードは絶対に含めない)
    const payload: UserLite = {
      id: user.id,
      name: user.name,
      email: user.email,
      altEmail: user.altEmail,
      role: user.role,
      departmentId: user.departmentId,
      departmentName: user.departmentName,
      avatar: user.avatar,
      allowedSystems: user.allowedSystems,
    };
    // UTF-8 セーフな base64
    const json = JSON.stringify(payload);
    const utf8 = new TextEncoder().encode(json);
    let bin = '';
    utf8.forEach(b => { bin += String.fromCharCode(b); });
    const b64 = btoa(bin);
    const sep = externalUrl.includes('?') ? '&' : '?';
    return `${externalUrl}${sep}auth=${encodeURIComponent(b64)}`;
  } catch {
    return externalUrl;
  }
}

:LiFolder: ソースファイルのパス

/Users/oogushiyuuki/Library/CloudStorage/GoogleDrive-y-ogushi@scale-group.co.jp/マイドライブ/AI/scale-base/lib/external-auth.ts

:LiHandPointer: 使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

:LiAlertCircle: 注意事項

  • 依存パッケージを忘れず追加