🚧

Dify をほぼ触らずに Google ログインを追加する方法

に公開

はじめに

本記事では、Difyで提供するアプリページ(/chat、/workflow)に Google アカウントでのログイン認証を最小の変更で導入する方法を紹介します。

OSS版DifyはLLMアプリケーションの開発プラットフォームとして非常に便利な一方で、アプリページ(/chat、/workflow)においてデフォルトではアクセス制御の仕組みがありません。組織内で利用する場合、社内アカウントのみがアクセスできるようにしたいというニーズがありました。

そこで、今回はOAuth2 Proxyを利用してGoogle認証を導入し、NGINXリバースプロキシと連携させることで、安全なアクセス制御を実現する手順を紹介します。

構成の全体像

今回実装する認証フローは以下のようになります。

未認証のリクエストは /oauth2/auth によって oauth2-proxy へ問い合わせが行われます。未ログイン状態の場合は /oauth2/sign_in へリダイレクトされ、Google認証画面が表示されます。認証成功後は X-Auth-Request-User/X-Auth-Request-Email などのヘッダがNGINXを経由してDify Webへ連携されます。

前提条件

本記事では、以下の環境が整っていることを前提としています。

  • Google Workspaceを利用しており@xxx.comなど社用アカウントがあること
  • DifyがDocker Composeで稼働していること
  • 外部からアクセス可能なドメインがあること(例: https://dify.example.com
  • HTTPS/TLS(ポート443)経由で公開されていること

Google Cloud側の設定

まず、Google CloudコンソールでOAuth 2.0クライアントを作成します。

OAuth同意画面の設定

Google Cloudのコンソール画面から「APIとサービス」→「OAuth 同意画面」を選択します。

OAuth クライアントの作成

サイドメニューから「認証情報」を選択し、「認証情報を作成」→「OAuth クライアント ID」を選択します。


以下の項目を設定します。

  • アプリケーションの種類: ウェブ アプリケーション
  • 名前: わかりやすいクライアント名(例: dify.example.com
  • 承認済みのJavaScript生成元: Difyを提供するルートドメイン(例: https://dify.example.com
  • 承認済みのリダイレクトURI: https://dify.example.com/oauth2/callback

設定が完了すると、クライアントIDとクライアントシークレットが発行されます。この2つの値は後ほど使用するため、控えておいてください。

Note: OAuth 2.0のスコープは openid email profile を前提とします。これはoauth2-proxyのデフォルト設定で動作します。

oauth2-proxyの設定

設定ファイルの作成

Difyのプロジェクトディレクトリ内に./dify/docker/oauth2_proxy/oauth2_proxy.cfg を作成します。

provider      = "google"
client_id     = "<Google Cloudで発行したクライアントID>"
client_secret = "<Google Cloudで発行したクライアントシークレット>"
redirect_url  = "https://<YOUR_DOMAIN>/oauth2/callback"
scope         = "openid email"

# 社用のGoogleアカウントのドメイン["xxx.com"]を設定
# 全てのメールアドレスを許可する場合は["*"]
email_domains = ["xxx.com"]

cookie_name     = "_oauth2_proxy"
cookie_secret   = "<BASE64_URLSAFE_32BYTES>"  # 「openssl rand -base64 32」を実行して出力された値を入力
cookie_secure   = true
cookie_expire   = "168h"
cookie_samesite = "lax"
session_cookie_minimal = true

upstreams         = "http://web:3000"
http_address      = ":4180"
set_xauthrequest  = true
pass_access_token = true
pass_user_headers = true

Cookieシークレットの生成

cookie_secret には32バイトのランダムな文字列が必要です。以下のコマンドで生成できます。

openssl rand -base64 32

出力された値を cookie_secret に設定してください。

設定項目の説明

設定項目 説明
provider OAuth2プロバイダ(今回はGoogle)
client_id Google Cloudで発行したクライアントID
client_secret Google Cloudで発行したクライアントシークレット
redirect_url 認証後のリダイレクト先URL
scope 要求するスコープ(メール取得には email が必要)
email_domains 許可するメールドメイン(*は全許可、本番では組織ドメインに限定推奨)
cookie_secret Cookie暗号化用の秘密鍵(16/24/32バイト必要)
cookie_secure trueの場合、HTTPS通信時のみCookieを送信。falseの場合、HTTP通信でも送信されます。
cookie_expire Cookieの有効期限(例: 168h = 7日間)
upstreams 認証後のプロキシ先(Difyのwebサービス)
http_address oauth2-proxyの待受ポート
set_xauthrequest NGINX auth_request連携を有効化

Docker Composeの設定

./docker/docker-compose.yaml に oauth2-proxy サービスを追加します。

services:
  # ... 既存のサービス定義 ...

  # oauth2-proxy Service
  oauth2_proxy:
    image: quay.io/oauth2-proxy/oauth2-proxy:v7.12.0
    restart: always
    volumes:
      - ./oauth2_proxy/oauth2_proxy.cfg:/etc/oauth2_proxy.cfg
      - ./oauth2_proxy/allowed_emails.txt:/etc/oauth2-proxy/allowed_emails.txt:ro
    command:
      - --config=/etc/oauth2_proxy.cfg
      - --authenticated-emails-file=/etc/oauth2-proxy/allowed_emails.txt
    depends_on:
      - web

  # ... その他のサービス ...

この設定により、oauth2-proxyがDifyのwebサービスと連携して動作します。

NGINXの設定

次に、NGINXの設定ファイルを編集して、認証フローを組み込みます。

./docker/nginx/conf.d/default.conf.template を以下のように修正します。

server {
  # ... 既存の設定 ...

  # oauth2-proxyへのプロキシ設定
  location /oauth2/ {
    proxy_pass http://oauth2_proxy:4180;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header X-Auth-Request-Redirect $request_uri;
  }

  # 認証チェック用のエンドポイント
  location = /oauth2/auth {
    proxy_pass http://oauth2_proxy:4180;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Scheme $scheme;
    proxy_set_header X-Auth-Request-Redirect $request_uri;
    proxy_set_header Content-Length "";
    proxy_pass_request_body off;
  }

  # チャット機能への認証適用
  location /chat {
    auth_request /oauth2/auth;
    error_page 401 = /oauth2/sign_in;

    auth_request_set $user $upstream_http_x_auth_request_user;
    auth_request_set $email $upstream_http_x_auth_request_email;
    proxy_set_header X-User $user;
    proxy_set_header X-Email $email;

    proxy_pass http://web:3000;
    include proxy.conf;
  }

  # ワークフロー機能への認証適用
  location /workflow {
    auth_request /oauth2/auth;
    error_page 401 = /oauth2/sign_in;

    auth_request_set $user $upstream_http_x_auth_request_user;
    auth_request_set $email $upstream_http_x_auth_request_email;
    proxy_set_header X-User $user;
    proxy_set_header X-Email $email;

    proxy_pass http://web:3000;
    include proxy.conf;
  }

  # その他のパスは認証なし
  location / {
    proxy_pass http://web:3000;
    include proxy.conf;
  }
}

この設定により、Difyのアプリページ /chat/workflow へのアクセス時に認証が要求されるようになります。

デプロイと起動

設定が完了したら、Docker ComposeでDifyを再起動します。

docker compose up -d --build

コンテナの起動状態を確認します。

docker compose ps

oauth2-proxynginxが正常に起動していることを確認してください。

ログを確認する場合は以下のコマンドを使用します。

docker compose logs -f oauth2_proxy nginx

動作確認

認証フローの確認

ブラウザで Dify のチャット画面にアクセスします。

https://<YOUR_DOMAIN>/chat/xxx

未認証の状態でアクセスすると、自動的にGoogle認証画面にリダイレクトされます。

許可リストの動作確認

ケース1: 許可されたメールアドレスでログイン

email_domains に記載されたドメインを持つメールアドレスでログインすると、正常にDifyのアプリケーションにアクセスできます。

ケース2: 許可されていないメールアドレスでログイン

許可されていないメールアドレスでログインを試みると、403 Forbidden エラーが表示されます。

おわりに

本記事では、DifyにGoogle認証を導入し、oauth2-proxyとNGINXを連携させてアクセス制御を最小の変更で実現する方法を紹介しました。

この仕組みにより、組織内での安全なDify利用が可能になります。認証プロバイダはGoogleだけでなく、GitHub、GitLab、OIDCなど様々なプロバイダに対応しているため、組織の要件に合わせて選択できます。

セキュリティ設定については、組織のポリシーに従って適切に調整してください。特に本番環境では、最小権限の原則に基づいたアクセス制御が重要です。

参考資料

株式会社ZOZO

Discussion