This page was machine-translated. Spotted a mistake?Help improve it.
Skip to content

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 라우트가 조용히 건너뛰어지고 경고가 로깅됩니다.

Prerequisites

  • 공개 URL로 접근할 수 있는 실행 중인 SnapOtter 인스턴스
  • 해당 공개 URL로 설정된 EXTERNAL_URL(예: https://photos.example.com)
  • saml_sso 기능이 포함된 team 또는 enterprise 라이선스 키
  • SAML ID 공급자에 대한 관리자 접근 권한

Quick start

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

컨테이너를 재시작하세요. 로그인 페이지에 "Sign in with SAML" 버튼(또는 SAML_PROVIDER_NAME로 설정한 레이블)이 나타납니다.

Configuration reference

VariableDefaultDescription
SAML_ENABLEDfalseSAML 로그인을 활성화합니다.
SAML_IDP_SSO_URLIdP의 SSO 엔드포인트 URL. SAML이 활성화되면 필수.
SAML_IDP_CERTIFICATEPEM 형식의 IdP X.509 서명 인증서(파일 경로가 아니라 인증서 텍스트 자체). SAML이 활성화되면 필수.
EXTERNAL_URLSnapOtter에 접근할 수 있는 공개 URL. SAML이 활성화되면 필수.
SAML_ENTITY_ID${EXTERNAL_URL}/api/auth/saml/metadataIdP로 전송되는 SP Entity ID / Audience URI.
SAML_CALLBACK_URL${EXTERNAL_URL}/api/auth/saml/callbackAssertion Consumer Service(ACS) URL.
SAML_AUTO_CREATE_USERStrue첫 SAML 로그인 시 로컬 사용자 계정을 자동으로 생성합니다.
SAML_AUTO_LINK_USERSfalse이메일 주소가 일치하면 SAML ID를 기존 로컬 사용자에 연결합니다.
SAML_DEFAULT_ROLEuser자동 생성된 SAML 사용자에게 할당되는 역할. admin, editor, user 중 하나.
SAML_PROVIDER_NAME프런트엔드의 SAML 로그인 버튼에 표시되는 레이블(예: "Okta", "Azure AD"). 비어 있으면 버튼에 "SAML"이라고 표시됩니다.
SAML_USERNAME_ATTRIBUTE사용자 이름으로 사용되는 SAML assertion 속성. 비어 있으면 이메일의 local-part로, 그다음 NameID로 대체됩니다.
SAML_EMAIL_ATTRIBUTEemail사용자의 이메일 주소로 사용되는 SAML assertion 속성.

SAML_ENABLED=true이면서 세 가지 필수 변수(SAML_IDP_SSO_URL, SAML_IDP_CERTIFICATE, EXTERNAL_URL) 중 하나라도 누락되면 서버가 시작을 거부합니다.

보안 참고 사항

wantAuthnResponseSignedwantAssertionsSigned는 모두 true로 하드코딩되어 있습니다. SnapOtter는 서명되지 않았거나 부적절하게 서명된 SAML 응답을 거부합니다. 신뢰할 수 있는 IdP의 assertion은 이메일이 검증된 것으로 취급됩니다.

SP-initiated 로그인만 지원됩니다. SnapOtter는 IdP-initiated(요청하지 않은) 로그인이나 Single Logout(SLO)을 지원하지 않습니다. SnapOtter에서 로그아웃해도 IdP에서 사용자가 로그아웃되지는 않습니다.

SP metadata and URLs

IdP는 SnapOtter로부터 세 가지 값이 필요합니다:

FieldValue
ACS URL (Assertion Consumer Service)${EXTERNAL_URL}/api/auth/saml/callback
Entity ID / Audience URI${EXTERNAL_URL}/api/auth/saml/metadata
SP Metadata (XML)GET ${EXTERNAL_URL}/api/auth/saml/metadata

예를 들어 EXTERNAL_URLhttps://photos.example.com라면:

  • ACS URL: https://photos.example.com/api/auth/saml/callback
  • Entity ID: https://photos.example.com/api/auth/saml/metadata
  • Metadata endpoint: https://photos.example.com/api/auth/saml/metadata (XML을 반환)

일부 IdP는 SP metadata URL을 직접 가져올 수 있으며, 이는 ACS URL과 Entity ID를 자동으로 채웁니다.

Provider setup

Okta

  1. Okta 관리자 콘솔에서 Applications > Create App Integration으로 이동합니다.
  2. SAML 2.0을 선택하고 Next를 클릭합니다.
  3. 이름을 설정하고(예: "SnapOtter") Next를 클릭합니다.
  4. 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
  5. Attribute Statements에서 emailuser.email에 매핑하여 추가합니다.
  6. Next를 클릭한 다음 Finish를 클릭합니다.
  7. Sign On 탭으로 이동하여 View SAML setup instructions를 클릭하고 다음을 복사합니다:
    • Identity Provider Single Sign-On URLSAML_IDP_SSO_URL
    • X.509 CertificateSAML_IDP_CERTIFICATE으로

Azure AD / Entra ID

  1. Azure 포털에서 Microsoft Entra ID > Enterprise applications > New application으로 이동합니다.
  2. Create your own application을 클릭하고 "SnapOtter"라고 이름을 지정한 다음 Integrate any other application you don't find in the gallery를 선택합니다.
  3. 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)
  4. SAML Certificates에서 **Certificate (Base64)**를 다운로드합니다.
  5. Set up SnapOtter에서 Login URL을 복사합니다.
  6. SAML_IDP_SSO_URL을 Login URL로, SAML_IDP_CERTIFICATE를 다운로드한 인증서 내용으로 설정합니다.
  7. Users and groups에서 사용자 또는 그룹을 애플리케이션에 할당합니다.

Google Workspace

  1. Google 관리 콘솔에서 Apps > Web and mobile apps > Add app > Add custom SAML app으로 이동합니다.
  2. 앱 이름을 "SnapOtter"로 지정하고 Continue를 클릭합니다.
  3. Google Identity Provider details 페이지에서 SSO URL을 복사하고 Certificate를 다운로드합니다. Continue를 클릭합니다.
  4. 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
  5. Continue를 클릭한 다음 Finish를 클릭합니다.
  6. 조직 단위에 대해 앱을 ON으로 전환합니다.
  7. SAML_IDP_SSO_URL을 3단계의 SSO URL로, SAML_IDP_CERTIFICATE을 다운로드한 인증서 내용으로 설정합니다.

Generic SAML 2.0 IdP

모든 SAML 2.0 호환 ID 공급자에 대해:

  1. IdP에서 새 SAML 애플리케이션/서비스 공급자를 생성합니다.
  2. ACS URL${EXTERNAL_URL}/api/auth/saml/callback로 설정합니다.
  3. Entity ID / Audience${EXTERNAL_URL}/api/auth/saml/metadata으로 설정합니다.
  4. email이라는 속성으로 사용자의 이메일을 보내도록 IdP를 구성합니다(또는 IdP의 속성 이름과 일치하도록 SAML_EMAIL_ATTRIBUTE를 설정).
  5. IdP SSO URLsigning certificateSAML_IDP_SSO_URLSAML_IDP_CERTIFICATE에 복사합니다.

User provisioning

Auto-create

SAML_AUTO_CREATE_USERStrue일 때(기본값), 누군가 SAML로 처음 로그인하면 로컬 사용자 계정이 생성됩니다. 역할은 SAML_DEFAULT_ROLE로 설정됩니다.

사용자 이름은 다음 순서로 결정됩니다:

  1. SAML_USERNAME_ATTRIBUTE로 지정된 assertion 속성의 값(설정되어 있고 존재하는 경우)
  2. 이메일 주소의 local-part(@ 앞의 모든 부분)
  3. SAML NameID

사용자 이름 충돌이 발생하면 숫자 접미사가 추가됩니다(예: janejane_2이 됨).

SAML_AUTO_LINK_USERStrue일 때, SnapOtter는 이메일 주소가 일치하면 SAML ID를 기존 로컬 계정에 연결합니다. 사용자 계정을 미리 생성해 두고, 데이터를 잃지 않으면서 SSO를 사용하기 시작하도록 하려는 경우에 유용합니다.

WARNING

SAML IdP가 이메일 주소를 검증한다고 신뢰하는 경우에만 auto-link를 활성화하세요. 잘못 구성된 IdP의 검증되지 않은 이메일은 누군가가 다른 사용자의 계정을 탈취하도록 허용할 수 있습니다.

Attribute mapping

SnapOtter fieldSourceConfiguration
EmailAssertion attributeSAML_EMAIL_ATTRIBUTE (default: email)
UsernameAssertion attribute, email, or NameIDSAML_USERNAME_ATTRIBUTE (위의 결정 순서 참고)
External IDNameID항상 SAML NameID, 구성 불가

SSO enforcement

모든 사용자가 SAML(또는 OIDC)을 통해 로그인하도록 요구하고 로컬 비밀번호 로그인을 차단하려면 SSO enforcement를 활성화하세요:

  1. sso_enforcement 엔터프라이즈 기능에 라이선스가 있는지 확인합니다(team 및 enterprise 플랜에서 사용 가능).
  2. Admin Settings > Security에서 SSO Enforcement를 켭니다.
  3. break-glass username을 설정합니다: 이것은 IdP에 접근할 수 없을 때 긴급 접근을 위해 여전히 비밀번호로 로그인할 수 있는 하나의 로컬 계정입니다.

SSO enforcement가 활성화되면, break-glass 사용자를 제외한 모든 로컬 로그인 시도는 "Local password login is disabled. Please use SSO." 메시지와 함께 403 오류를 반환합니다.

TIP

SSO enforcement를 활성화하기 전에 항상 break-glass username을 구성하세요. 그렇지 않으면 IdP가 다운될 경우 SnapOtter에서 잠길 수 있습니다.

Using SAML alongside OIDC

SAML과 OIDC를 동시에 활성화할 수 있습니다. 둘 다 활성화되면, 로그인 페이지에 각 공급자에 대한 별도의 버튼이 표시됩니다(SAML_PROVIDER_NAMEOIDC_PROVIDER_NAME로 레이블 지정됨). 사용자는 어느 방식으로든 로그인할 수 있습니다.

두 공급자는 auto-create, auto-link, SSO enforcement 설정을 각각 독립적으로 공유합니다: 각각 고유한 *_AUTO_CREATE_USERS, *_AUTO_LINK_USERS, *_DEFAULT_ROLE 변수를 가집니다.

Troubleshooting

Assertion validation failed

SAML 응답 서명 또는 assertion 서명을 검증할 수 없습니다. 다음을 확인하세요:

  • SAML_IDP_CERTIFICATE의 인증서가 IdP의 현재 서명 인증서와 일치하는지(인증서는 교체되므로 만료 여부를 확인하세요)
  • 인증서가 PEM 형식인지(-----BEGIN CERTIFICATE-----로 시작)
  • 인증서가 파일 경로가 아니라 전체 텍스트인지
  • IdP에 구성된 ACS URL과 Entity ID가 SnapOtter의 값과 정확히 일치하는지(스킴, 호스트, 포트, 경로)

Missing attributes

로그인 후 사용자 이름이나 이메일이 비어 있다면, IdP가 기대하는 속성을 보내지 않을 수 있습니다. 다음을 확인하세요:

  • IdP가 email 속성(또는 SAML_EMAIL_ATTRIBUTE에 설정된 값)을 릴리스하도록 구성되어 있는지
  • SAML_USERNAME_ATTRIBUTE을 사용하는 경우, 해당 속성이 assertion에 포함되어 있는지 확인
  • 일부 IdP는 클레임을 릴리스하기 전에 명시적인 속성 매핑 구성이 필요합니다

Clock skew

SAML assertion에는 타임스탬프 조건(NotBefore, NotOnOrAfter)이 포함됩니다. 서버 시계와 IdP 시계가 동기화되지 않으면 assertion 검증이 실패합니다. 시계를 맞추기 위해 두 머신 모두에서 NTP를 실행하세요.

"SAML is enabled via env but saml_sso enterprise feature is not licensed"

이 경고는 SAML_ENABLED=true이지만 라이선스에 saml_sso 기능이 포함되지 않은 경우 서버 로그에 나타납니다. 라이선스 키와 플랜을 확인하세요. saml_sso 기능은 team 및 enterprise 플랜에서 사용할 수 있습니다.

Login redirects back with error

SAML 로그인 버튼을 클릭하면 오류와 함께 로그인 페이지로 다시 리디렉션되는 경우, 자세한 내용은 서버 로그를 확인하세요. 흔한 원인은 다음과 같습니다:

  • IdP SSO URL에 서버에서 접근할 수 없음
  • IdP가 인증 요청을 거부함(IdP의 감사 로그를 확인하세요)
  • IdP가 서명되지 않은 응답을 반환함(SnapOtter는 응답과 assertion 모두 서명되어야 합니다)