Search K
SAML SSO
SnapOtter はシングルサインオンのために SAML 2.0 をサポートしています。ユーザーは、ローカルのユーザー名/パスワード認証の代わりに、外部 ID プロバイダー(Okta、Azure AD / Entra ID、Google Workspace、または任意の標準 SAML 2.0 IdP)経由でログインできます。
エンタープライズ機能
SAML SSO には、saml_sso 機能を含む team または enterprise ライセンスが必要です。有効なライセンスなしに SAML_ENABLED=true が設定されている場合、SAML ルートは通知なくスキップされ、警告がログに記録されます。
前提条件
- 公開 URL で到達可能な、稼働中の SnapOtter インスタンス
- その公開 URL に設定された
EXTERNAL_URL(例:https://photos.example.com) saml_sso機能を含む team または enterprise のライセンスキー- SAML ID プロバイダーへの管理者アクセス
クイックスタート
これらの環境変数を docker-compose.yml に追加します:
yaml
services:
snapotter:
image: snapotter/snapotter:latest
environment:
EXTERNAL_URL: "https://photos.example.com"
SNAPOTTER_LICENSE_KEY: "your-license-key"
SAML_ENABLED: "true"
SAML_IDP_SSO_URL: "https://idp.example.com/sso/saml"
SAML_IDP_CERTIFICATE: |
MIICpDCCAYwCCQDU+pQ4pHgSpDANBgkqhkiG9w0BAQsFADAUMRIw
...your IdP's signing certificate in PEM format...
EAYHKoZIzj0CAQYFK4EEACIDYgAEコンテナを再起動します。ログインページに「SAML でサインイン」ボタン(または SAML_PROVIDER_NAME で設定されたラベル)が表示されます。
設定リファレンス
| 変数 | デフォルト | 説明 |
|---|---|---|
SAML_ENABLED | false | SAML ログインを有効にします。 |
SAML_IDP_SSO_URL | IdP の SSO エンドポイント URL。SAML が有効な場合は 必須。 | |
SAML_IDP_CERTIFICATE | PEM 形式の IdP の X.509 署名証明書(ファイルパスではなく証明書のテキストそのもの)。SAML が有効な場合は 必須。 | |
EXTERNAL_URL | SnapOtter に到達できる公開 URL。SAML が有効な場合は 必須。 | |
SAML_ENTITY_ID | ${EXTERNAL_URL}/api/auth/saml/metadata | IdP に送信される SP Entity ID / Audience URI。 |
SAML_CALLBACK_URL | ${EXTERNAL_URL}/api/auth/saml/callback | Assertion Consumer Service (ACS) URL。 |
SAML_AUTO_CREATE_USERS | true | 初回 SAML ログイン時にローカルユーザーアカウントを自動作成します。 |
SAML_AUTO_LINK_USERS | false | メールアドレスが一致する場合、SAML ID を既存のローカルユーザーにリンクします。 |
SAML_DEFAULT_ROLE | user | 自動作成された SAML ユーザーに割り当てられるロール。admin、editor、user のいずれか。 |
SAML_PROVIDER_NAME | フロントエンドの SAML ログインボタンの表示ラベル(例:「Okta」、「Azure AD」)。空の場合、ボタンには「SAML」と表示されます。 | |
SAML_USERNAME_ATTRIBUTE | ユーザー名として使用される SAML アサーション属性。空の場合、メールのローカル部分、次に NameID にフォールバックします。 | |
SAML_EMAIL_ATTRIBUTE | email | ユーザーのメールアドレスとして使用される SAML アサーション属性。 |
SAML_ENABLED=true で、3 つの必須変数(SAML_IDP_SSO_URL、SAML_IDP_CERTIFICATE、EXTERNAL_URL)のいずれかが欠けている場合、サーバーは起動を拒否します。
セキュリティに関する注意
wantAuthnResponseSigned と wantAssertionsSigned はどちらも true にハードコードされています。SnapOtter は署名されていない、または不適切に署名された SAML レスポンスを拒否します。信頼された IdP からのアサーションは、メール検証済みとして扱われます。
SP 起点のログインのみがサポートされています。SnapOtter は IdP 起点(未承諾)のログインやシングルログアウト (SLO) をサポートしていません。SnapOtter からログアウトしても、ユーザーは IdP からログアウトされません。
SP メタデータと URL
IdP には SnapOtter から 3 つの値が必要です:
| フィールド | 値 |
|---|---|
| ACS URL(Assertion Consumer Service) | ${EXTERNAL_URL}/api/auth/saml/callback |
| Entity ID / Audience URI | ${EXTERNAL_URL}/api/auth/saml/metadata |
| SP メタデータ(XML) | GET ${EXTERNAL_URL}/api/auth/saml/metadata |
たとえば、EXTERNAL_URL が https://photos.example.com の場合:
- ACS URL:
https://photos.example.com/api/auth/saml/callback - Entity ID:
https://photos.example.com/api/auth/saml/metadata - メタデータエンドポイント:
https://photos.example.com/api/auth/saml/metadata(XML を返します)
一部の IdP は SP メタデータ URL を直接インポートでき、これにより ACS URL と Entity ID が自動入力されます。
プロバイダーのセットアップ
Okta
- Okta 管理コンソールで、Applications > Create App Integration に移動します。
- SAML 2.0 を選択して Next をクリックします。
- 名前(例:「SnapOtter」)を設定して Next をクリックします。
- SAML 設定を構成します:
- Single sign-on URL: あなたの ACS URL(例:
https://photos.example.com/api/auth/saml/callback) - Audience URI (SP Entity ID): あなたの Entity ID(例:
https://photos.example.com/api/auth/saml/metadata) - Name ID format: EmailAddress
- Application username: Email
- Single sign-on URL: あなたの ACS URL(例:
- Attribute Statements で、
user.emailにマッピングされたemailを追加します。 - Next をクリックし、次に Finish をクリックします。
- Sign On タブに移動し、View SAML setup instructions をクリックして、以下をコピーします:
- Identity Provider Single Sign-On URL を
SAML_IDP_SSO_URLへ - X.509 Certificate を
SAML_IDP_CERTIFICATEへ
- Identity Provider Single Sign-On URL を
Azure AD / Entra ID
- Azure ポータルで、Microsoft Entra ID > Enterprise applications > New application に移動します。
- Create your own application をクリックし、「SnapOtter」と名前を付け、Integrate any other application you don't find in the gallery を選択します。
- Single sign-on > SAML に移動し、Basic SAML Configuration セクションで Edit をクリックします:
- Identifier (Entity ID): あなたの Entity ID(例:
https://photos.example.com/api/auth/saml/metadata) - Reply URL (ACS URL): あなたの ACS URL(例:
https://photos.example.com/api/auth/saml/callback)
- Identifier (Entity ID): あなたの Entity ID(例:
- SAML Certificates で、Certificate (Base64) をダウンロードします。
- Set up SnapOtter で、Login URL をコピーします。
SAML_IDP_SSO_URLを Login URL に、SAML_IDP_CERTIFICATEをダウンロードした証明書の内容に設定します。- Users and groups でアプリケーションにユーザーまたはグループを割り当てます。
Google Workspace
- Google 管理コンソールで、Apps > Web and mobile apps > Add app > Add custom SAML app に移動します。
- アプリに「SnapOtter」と名前を付け、Continue をクリックします。
- Google Identity Provider details ページで、SSO URL をコピーし、Certificate をダウンロードします。Continue をクリックします。
- Service Provider の詳細を設定します:
- ACS URL: あなたの ACS URL(例:
https://photos.example.com/api/auth/saml/callback) - Entity ID: あなたの Entity ID(例:
https://photos.example.com/api/auth/saml/metadata) - Name ID format: EMAIL
- Name ID: Basic Information > Primary email
- ACS URL: あなたの ACS URL(例:
- Continue をクリックし、次に Finish をクリックします。
- 組織部門に対してアプリを ON にします。
SAML_IDP_SSO_URLをステップ 3 の SSO URL に、SAML_IDP_CERTIFICATEをダウンロードした証明書の内容に設定します。
汎用 SAML 2.0 IdP
任意の SAML 2.0 準拠の ID プロバイダーの場合:
- IdP に新しい SAML アプリケーション/サービスプロバイダーを作成します。
- ACS URL を
${EXTERNAL_URL}/api/auth/saml/callbackに設定します。 - Entity ID / Audience を
${EXTERNAL_URL}/api/auth/saml/metadataに設定します。 emailという名前の属性でユーザーのメールを送信するように IdP を設定します(または、IdP の属性名に合わせてSAML_EMAIL_ATTRIBUTEを設定します)。- IdP SSO URL と 署名証明書 を
SAML_IDP_SSO_URLとSAML_IDP_CERTIFICATEにコピーします。
ユーザープロビジョニング
自動作成
SAML_AUTO_CREATE_USERS が true(デフォルト)の場合、誰かが初めて SAML 経由でログインしたときにローカルユーザーアカウントが作成されます。ロールは SAML_DEFAULT_ROLE に設定されます。
ユーザー名は次の順序で導出されます:
SAML_USERNAME_ATTRIBUTEで指定されたアサーション属性の値(設定されていて存在する場合)- メールアドレスのローカル部分(
@より前のすべて) - SAML NameID
ユーザー名の衝突が発生した場合、数値のサフィックスが追加されます(例: jane は jane_2 になります)。
自動リンク
SAML_AUTO_LINK_USERS が true の場合、メールアドレスが一致すれば、SnapOtter は SAML ID を既存のローカルアカウントにリンクします。これは、事前に作成したユーザーアカウントがあり、データを失うことなく SSO の使用を開始させたい場合に便利です。
WARNING
自動リンクは、SAML IdP がメールアドレスを検証することを信頼できる場合にのみ有効にしてください。設定が誤った IdP からの検証されていないメールにより、誰かが別のユーザーのアカウントを乗っ取れる可能性があります。
属性マッピング
| SnapOtter フィールド | ソース | 設定 |
|---|---|---|
| メール | アサーション属性 | SAML_EMAIL_ATTRIBUTE(デフォルト: email) |
| ユーザー名 | アサーション属性、メール、または NameID | SAML_USERNAME_ATTRIBUTE(上記の導出順序を参照) |
| 外部 ID | NameID | 常に SAML NameID で、設定不可 |
SSO の強制
すべてのユーザーに SAML(または OIDC)経由でのログインを要求し、ローカルパスワードログインをブロックしたい場合は、SSO の強制を有効にします:
sso_enforcementエンタープライズ機能がライセンスされていることを確認します(team および enterprise プランで利用可能)。- Admin Settings > Security で、SSO Enforcement をオンに切り替えます。
- break-glass ユーザー名 を設定します。これは、IdP に到達できない場合の緊急アクセス用に、引き続きパスワードでログインできる唯一のローカルアカウントです。
SSO の強制が有効な場合、(break-glass ユーザーを除く)ローカルログインの試行は「Local password login is disabled. Please use SSO.」というメッセージとともに 403 エラーを返します。
TIP
SSO の強制を有効にする前に、必ず break-glass ユーザー名を設定してください。それがないと、IdP がダウンした場合に SnapOtter からロックアウトされる可能性があります。
OIDC と併用した SAML の使用
SAML と OIDC は同時に有効にできます。両方が有効な場合、ログインページには各プロバイダー用の個別のボタン(SAML_PROVIDER_NAME と OIDC_PROVIDER_NAME でラベル付け)が表示されます。ユーザーはどちらの方法でもログインできます。
両方のプロバイダーは、自動作成、自動リンク、SSO 強制の設定を独立して共有します。それぞれが独自の *_AUTO_CREATE_USERS、*_AUTO_LINK_USERS、*_DEFAULT_ROLE 変数を持ちます。
トラブルシューティング
アサーションの検証に失敗
SAML レスポンスの署名またはアサーションの署名を検証できませんでした。次を確認してください:
SAML_IDP_CERTIFICATEの証明書が IdP の現在の署名証明書と一致している(証明書はローテーションされるため、有効期限を確認してください)- 証明書が PEM 形式である(
-----BEGIN CERTIFICATE-----で始まる) - 証明書がファイルパスではなく、全文である
- IdP に設定された ACS URL と Entity ID が SnapOtter の値と正確に一致している(スキーム、ホスト、ポート、パス)
属性の欠落
ログイン後にユーザー名やメールが空の場合、IdP が期待される属性を送信していない可能性があります。次を確認してください:
- IdP が
email属性(またはSAML_EMAIL_ATTRIBUTEに設定されている値)を提供するように設定されている SAML_USERNAME_ATTRIBUTEを使用している場合、その属性がアサーションに含まれていることを確認してください- 一部の IdP では、クレームを提供する前に明示的な属性マッピング設定が必要です
クロックスキュー
SAML アサーションにはタイムスタンプ条件(NotBefore、NotOnOrAfter)が含まれます。サーバーの時刻と IdP の時刻が同期していない場合、アサーションの検証は失敗します。時刻を揃えておくために、両方のマシンで NTP を実行してください。
「SAML is enabled via env but saml_sso enterprise feature is not licensed」
この警告は、SAML_ENABLED=true であるがライセンスに saml_sso 機能が含まれていない場合にサーバーログに表示されます。ライセンスキーとプランを確認してください。saml_sso 機能は team および enterprise プランで利用可能です。
ログインがエラーとともに戻される
SAML ログインボタンをクリックするとエラーとともにログインページに戻される場合は、詳細についてサーバーログを確認してください。一般的な原因:
- IdP SSO URL がサーバーから到達不能である
- IdP が認証リクエストを拒否した(IdP の監査ログを確認してください)
- IdP が署名されていないレスポンスを返した(SnapOtter はレスポンスとアサーションの両方が署名されていることを要求します)
