AI

SSO OSS比較:Keycloak vs Authentik vs Zitadel でAuth0代替をセルフホスト

オープンソースラボ編集部2026年6月13日

SSO OSS比較:Keycloak vs Authentik vs Zitadel でAuth0代替をセルフホスト

Auth0は月$23〜(最低1,000MAU)・Okta は月$2/ユーザーと、ユーザーが増えるほどコストが指数的に増加します。Keycloak(Red Hat製・最も実績多)・Authentik(Python製・モダンUI)・Zitadel(Go製・マルチテナント)はOSSのIdentity Providerで、OAuth2/OIDC・SAML・MFA・ソーシャルログインをセルフホストで実装できます。

SSOツールの選定理由

  • コスト削減: Auth0の月5,000MAUプランは月$240。セルフホストでサーバー代のみに
  • マルチテナント: SaaSアプリで顧客ごとに独立したユーザーテナントを管理したい
  • 社員SSO: Google Workspaceと連携してSAML SSOで全社ツールにシングルサインオン
  • カスタムログインUI: ブランドに合わせたログイン画面・MFA・パスキーを実装したい
  • Next.js統合: NextAuth.jsやAuthelia経由でOIDCプロバイダーとして接続したい

主要ツールの概要

Keycloak

Red Hat(IBM)が開発・メンテナンスするエンタープライズグレードのIdentity and Access Managementサーバーです。GitHubスター23k+。OAuth2・OIDC・SAML 2.0・WebAuthn・LDAP/AD連携に対応し、世界中の大企業・政府機関で採用されています。

# Keycloakをdocker-composeで起動
version: "3"

services:
  keycloak:
    image: quay.io/keycloak/keycloak:24.0
    restart: always
    command: start
    ports:
      - "8080:8080"
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: keycloak_pass
      KC_HOSTNAME: auth.yoursite.com
      KC_PROXY: edge
      KC_HTTP_ENABLED: "true"
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: your-admin-password
    depends_on:
      - postgres

  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: keycloak_pass
    volumes:
      - keycloak_db:/var/lib/postgresql/data

volumes:
  keycloak_db:
// Next.js + NextAuth.js でKeycloakと連携
// npm install next-auth

// app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";
import type { NextAuthOptions } from "next-auth";
import KeycloakProvider from "next-auth/providers/keycloak";

export const authOptions: NextAuthOptions = {
  providers: [
    KeycloakProvider({
      clientId: process.env.KEYCLOAK_CLIENT_ID!,
      clientSecret: process.env.KEYCLOAK_CLIENT_SECRET!,
      issuer: process.env.KEYCLOAK_ISSUER!,
      // issuer例: https://auth.yoursite.com/realms/yourapp
    }),
  ],
  callbacks: {
    async jwt({ token, account }) {
      // Keycloakのアクセストークンをセッションに保持
      if (account) {
        token.accessToken = account.access_token;
        token.refreshToken = account.refresh_token;
        token.idToken = account.id_token;
      }
      return token;
    },
    async session({ session, token }) {
      session.accessToken = token.accessToken as string;
      return session;
    },
  },
  events: {
    async signOut({ token }) {
      // Keycloakからもサインアウト(シングルログアウト)
      if (token.idToken) {
        const params = new URLSearchParams({
          id_token_hint: token.idToken as string,
          post_logout_redirect_uri: process.env.NEXTAUTH_URL!,
        });
        await fetch(
          `${process.env.KEYCLOAK_ISSUER}/protocol/openid-connect/logout?${params}`
        );
      }
    },
  },
};

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
// Keycloak Admin REST APIでユーザーをプログラム的に管理
// サービスアカウントトークンを取得してユーザー操作

async function getAdminToken() {
  const res = await fetch(
    `${process.env.KEYCLOAK_URL}/realms/master/protocol/openid-connect/token`,
    {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({
        grant_type: "client_credentials",
        client_id: "admin-cli",
        client_secret: process.env.KEYCLOAK_ADMIN_SECRET!,
      }),
    }
  );
  const data = await res.json();
  return data.access_token;
}

// 新規ユーザーを作成(サインアップ後に自動実行)
async function createKeycloakUser(email: string, firstName: string) {
  const token = await getAdminToken();
  await fetch(
    `${process.env.KEYCLOAK_URL}/admin/realms/yourapp/users`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        username: email,
        email,
        firstName,
        enabled: true,
        emailVerified: false,
        credentials: [],
        requiredActions: ["VERIFY_EMAIL"],
      }),
    }
  );
}

Authentik

Python(Django)製のモダンなIdentity Providerです。GitHubスター14k+。視覚的なフローデザイナーで認証フロー(パスワード→MFA→利用規約同意)をノーコードで設計でき、Keycloakより学習コストが低いです。プロキシモード(Nginx/Traefikと連携してVPNなしでアプリを保護)も特徴です。

# Authentikをdocker-composeで起動
version: "3"

services:
  postgresql:
    image: postgres:16-alpine
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d authentik -U authentik"]
      interval: 5s
      timeout: 5s
      retries: 5
    environment:
      POSTGRES_PASSWORD: authentik_pass
      POSTGRES_USER: authentik
      POSTGRES_DB: authentik
    volumes:
      - authentik_db:/var/lib/postgresql/data

  redis:
    image: redis:alpine
    restart: unless-stopped

  server:
    image: ghcr.io/goauthentik/server:2024.4
    restart: unless-stopped
    command: server
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: authentik_pass
      AUTHENTIK_SECRET_KEY: "your-50-char-secret-key"
      AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
      AUTHENTIK_EMAIL__HOST: smtp.sendgrid.net
      AUTHENTIK_EMAIL__PORT: "587"
      AUTHENTIK_EMAIL__USERNAME: apikey
      AUTHENTIK_EMAIL__PASSWORD: your-sendgrid-key
      AUTHENTIK_EMAIL__FROM: auth@yoursite.com
      AUTHENTIK_EMAIL__USE_TLS: "true"
    ports:
      - "9000:9000"
      - "9443:9443"
    depends_on:
      postgresql:
        condition: service_healthy
      redis:
        condition: service_started

  worker:
    image: ghcr.io/goauthentik/server:2024.4
    restart: unless-stopped
    command: worker
    environment:
      AUTHENTIK_REDIS__HOST: redis
      AUTHENTIK_POSTGRESQL__HOST: postgresql
      AUTHENTIK_POSTGRESQL__USER: authentik
      AUTHENTIK_POSTGRESQL__NAME: authentik
      AUTHENTIK_POSTGRESQL__PASSWORD: authentik_pass
      AUTHENTIK_SECRET_KEY: "your-50-char-secret-key"
    depends_on:
      postgresql:
        condition: service_healthy

volumes:
  authentik_db:

Zitadel

Go製のマルチテナント対応Identity Platformです。GitHubスター9k+。SaaS向けのマルチオーガニゼーション管理・カスタムドメイン・ブランド別ログインUI・パスキー(FIDO2)ファーストの設計が特徴で、B2Bプロダクトの認証基盤として使いやすいです。

# ZitadelをDockerで起動(自己完結型)
docker run -d   --name zitadel   -p 8080:8080   -v zitadel_data:/data   -e ZITADEL_MASTERKEY="your-32-byte-masterkey-here!!"   -e ZITADEL_DATABASE_POSTGRES_HOST=postgres   -e ZITADEL_DATABASE_POSTGRES_PORT=5432   -e ZITADEL_DATABASE_POSTGRES_DATABASE=zitadel   -e ZITADEL_DATABASE_POSTGRES_USER_USERNAME=zitadel   -e ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=zitadel_pass   -e ZITADEL_EXTERNALSECURE=true   -e ZITADEL_EXTERNALPORT=443   -e ZITADEL_EXTERNALDOMAIN=auth.yoursite.com   ghcr.io/zitadel/zitadel:latest start-from-init --masterkey "your-32-byte-masterkey-here!!"
// Next.js + Zitadel OIDCでログインを実装
// npm install @zitadel/react @zitadel/node

// app/providers.tsx
"use client";
import { ZitadelProvider, createZitadelClient } from "@zitadel/react";

const zitadel = createZitadelClient({
  issuer: process.env.NEXT_PUBLIC_ZITADEL_ISSUER!,
  clientId: process.env.NEXT_PUBLIC_ZITADEL_CLIENT_ID!,
});

export function AuthProvider({ children }: { children: React.ReactNode }) {
  return (
    <ZitadelProvider client={zitadel}>
      {children}
    </ZitadelProvider>
  );
}

// ログインボタン
"use client";
import { useZitadel } from "@zitadel/react";

export function LoginButton() {
  const { signIn, signOut, user, isAuthenticated } = useZitadel();

  if (isAuthenticated) {
    return (
      <div>
        <p>ログイン中: {user?.profile?.name}</p>
        <button onClick={() => signOut()}>ログアウト</button>
      </div>
    );
  }

  return (
    <button onClick={() => signIn()}>
      Zitadelでログイン
    </button>
  );
}

機能比較表

比較項目KeycloakAuthentikZitadel
ライセンスApache-2.0MITApache-2.0
OAuth2/OIDC
SAML 2.0
MFA/TOTP
パスキー(FIDO2)✅ 重視
フロービルダー
プロキシモード
マルチテナント✅ 優秀
最小RAM1GB512MB512MB
GitHub Stars23k+14k+9k+

SSO・認証と組み合わせるパスワード管理の強化はopen-source-password-manager(/categories/security)を参照。Next.jsでの認証全体の設計はsecurityカテゴリ(/categories/security)でまとめています。

FAQ

Q. Auth0からKeycloakに移行する際、既存ユーザーのパスワードハッシュを移行できますか?

A. ユーザーデータの移行は可能ですが、パスワードハッシュの直接移行は困難です。移行アプローチ: ①Export→Import: Auth0のManagement APIでユーザー一覧をJSONエクスポート→KeycloakのAdmin APIでユーザーをインポート(パスワードなし)。ユーザーは次回ログイン時に「パスワードリセット」のメールを受け取ります②ジャスト・イン・タイム移行: 既存ユーザーが最初にKeycloakにログインしようとした際、裏でAuth0に認証を委譲し成功したらKeycloakにユーザーを作成。Auth0での認証が成功したパスワードをKeycloakに設定(Keycloakのカスタムユーザーストレージプロバイダーで実装)。推奨: 方法②が最もユーザー体験を損なわない移行方法です。移行期間中にAuth0を並行稼働させ、全ユーザーがKeycloakに移行したらAuth0を解約します。

Q. Authentikのプロキシモードを使うとVPNなしで社内ツールを保護できますか?

A. はい、Authentikのプロキシモードは「Reverse Proxy + 認証」を組み合わせた構成で、VPNなしでサービスを保護できます。仕組み: ①Nginx/TraefikがAuthentikをフォワード認証プロバイダーとして設定②ユーザーがサービスにアクセスするとAuthentikにリダイレクト③Authentikで認証成功後、元のサービスに戻る。設定例(Nginx): auth_request /outpost.goauthentik.io/auth/nginx;をNginxのlocationブロックに追加。保護できるサービスの例: Grafana・Kibana・Metabase・Jupyter・Redash・会社の内部ダッシュボード。VPNとの比較: Authentikプロキシはアプリ単位で認証を適用できますが、DBポートやSSHには使えません。DBへのアクセスはWireGuard/Headscaleを引き続き使います。

Q. ZitadelをB2B SaaSに使う場合のマルチテナント設定はどうすればよいですか?

A. Zitadelは「インスタンス→組織→ユーザー」の階層でマルチテナントを管理します。B2B SaaSでの設定パターン: ①1インスタンス・複数組織(推奨): 1つのZitadelインスタンスで顧客企業ごとに「組織」を作成。各組織が独立したユーザー管理・ポリシー・ブランドを持てる②カスタムドメイン: 顧客企業ごとにtenant1.auth.yoursite.comというドメインを付与し、ブランド付きログイン画面を表示③ロール管理: 組織ごとにロール(Admin/Member/Viewer等)を定義し、ZitadelのIDトークンにロール情報を含める。コードでの判定: JWTのurn:zitadel:iam:org:project:rolesクレームを取得してユーザーの権限を判断。Next.js実装: JWTにorg_idとroleを含め、middleware.tsでルートごとのアクセス制御を実装。

Q. KeycloakのSAML SSOをGoogle Workspaceと連携して全社ツールに適用する方法は?

A. 設定の流れはGoogle WorkspaceをIdP(Identity Provider)・Keycloakを中継として使います。①Google Workspace管理コンソール→アプリ→Webアプリとモバイルアプリ→アプリを追加→「カスタムSAMLアプリ」②Google SSO URLとSAML証明書をコピー③Keycloakの設定→Identity Providers→「SAML v2.0」→Google WorkspaceのSSO URLと証明書を貼り付け④Keycloakのグループ・ロールマッピング: GoogleのグループメンバーシップをKeycloakのロールにマッピング(例: Googleのengineeringグループ→Keycloakのdeveloperロール)⑤Keycloakをアプリケーションの認証基盤として設定(各アプリはKeycloakのOIDCを使う)。この構成のメリット: Google Workspaceを離職した社員は全アプリへのアクセスが自動的に無効化されます(Googleアカウント無効化→Keycloakへのログインも不可)。

まとめ

ユースケース推奨ツール
エンタープライズ・SAML・実績重視Keycloak
モダンUI・プロキシモードAuthentik
B2B SaaS・マルチテナントZitadel
Auth0代替のファースト選択Authentik

関連外部リソース

他の記事も読む

Let's Build Together

OSS導入、自社だけで悩まない。

ツール選定から構築・運用・AI活用まで、オープンソースラボ運営元のClasslessが伴走します。初回のご相談は無料です。