หน้านี้แปลด้วยเครื่อง พบข้อผิดพลาดใช่ไหมช่วยกันปรับปรุง
Skip to content

OIDC / Single Sign-On ​

SnapOtter รองรับ OpenID Connect (OIDC) สำหรับ single sign-on ผู้ใช้สามารถเข้าสู่ระบบด้วยผู้ให้บริการข้อมูลประจำตัวภายนอกอย่าง Keycloak, Authentik, Google หรือ Microsoft Entra ID แทน (หรือควบคู่ไปกับ) การยืนยันตัวตนด้วยชื่อผู้ใช้/รหัสผ่านในเครื่อง

เริ่มต้นอย่างรวดเร็ว ​

เพิ่มตัวแปรสภาพแวดล้อมเหล่านี้ลงใน docker-compose.yml ของคุณ:

yaml
services:
  SnapOtter:
    image: snapotter/snapotter:latest
    environment:
      EXTERNAL_URL: "https://photos.example.com"
      OIDC_ENABLED: "true"
      OIDC_ISSUER_URL: "https://auth.example.com/realms/myrealm"
      OIDC_CLIENT_ID: "snapotter"
      OIDC_CLIENT_SECRET: "your-secret-here"

redirect URI สำหรับผู้ให้บริการของคุณจะเป็นแบบนี้เสมอ:

${EXTERNAL_URL}/api/auth/oidc/callback

ตัวอย่างเช่น หาก EXTERNAL_URL คือ https://photos.example.com ให้กำหนด redirect URI ของผู้ให้บริการเป็น https://photos.example.com/api/auth/oidc/callback

เอกสารอ้างอิงการกำหนดค่า ​

ตัวแปรค่าเริ่มต้นคำอธิบาย
OIDC_ENABLEDfalseเปิดใช้งานการเข้าสู่ระบบ OIDC ปุ่ม "Sign in with SSO" จะปรากฏบนหน้าเข้าสู่ระบบ
OIDC_ISSUER_URLURL ผู้ออก (issuer) ของผู้ให้บริการ ต้องรองรับ OIDC Discovery (/.well-known/openid-configuration)
OIDC_CLIENT_IDOAuth client ID ที่ลงทะเบียนกับผู้ให้บริการของคุณ
OIDC_CLIENT_SECRETOAuth client secret
OIDC_SCOPESopenid profile emailรายการ scope ที่คั่นด้วยช่องว่างเพื่อร้องขอ
OIDC_AUTO_CREATE_USERStrueสร้างบัญชีผู้ใช้ในเครื่องโดยอัตโนมัติเมื่อเข้าสู่ระบบ OIDC ครั้งแรก
OIDC_DEFAULT_ROLEuserบทบาทที่กำหนดให้ผู้ใช้ OIDC ที่สร้างอัตโนมัติ หนึ่งใน admin, editor หรือ user
OIDC_AUTO_LINK_USERSfalseเชื่อมโยงข้อมูลประจำตัว OIDC กับผู้ใช้ในเครื่องที่มีอยู่หากที่อยู่อีเมลตรงกัน
OIDC_PROVIDER_NAMEชื่อที่แสดงบนปุ่มเข้าสู่ระบบ (เช่น "Keycloak", "Google") หากว่างเปล่า ปุ่มจะแสดง "SSO"
OIDC_CLOCK_TOLERANCE30ความคลาดเคลื่อนของนาฬิกาที่ยอมรับได้เป็นวินาทีสำหรับการตรวจสอบ token
OIDC_USERNAME_CLAIMpreferred_usernameclaim ของ ID token ที่ใช้เป็นชื่อผู้ใช้สำหรับบัญชีใหม่
EXTERNAL_URLURL สาธารณะที่เข้าถึง SnapOtter ได้ จำเป็นสำหรับ OIDC เพื่อสร้าง redirect URI ที่ถูกต้อง
COOKIE_SECRETสร้างอัตโนมัติsecret สำหรับเซ็นชื่อคุกกี้เซสชัน ตั้งค่านี้อย่างชัดเจนเมื่อรันหลาย replica

คู่มือผู้ให้บริการ ​

Keycloak ​

  1. สร้าง realm ใหม่ (หรือใช้ที่มีอยู่)
  2. ไปที่ Clients และสร้าง client ใหม่:
    • Client ID: snapotter
    • Client authentication: เปิด (confidential)
    • Authentication flow: Standard flow (Authorization Code)
  3. ใต้แท็บ Settings ของ client ให้ตั้งค่า Valid redirect URIs เป็น callback URL ของคุณ (เช่น https://photos.example.com/api/auth/oidc/callback)
  4. คัดลอก Client secret จากแท็บ Credentials
  5. ตั้งค่า OIDC_ISSUER_URL เป็น https://keycloak.example.com/realms/your-realm

Authentik ​

  1. ในหน้าจอผู้ดูแลระบบ ไปที่ Applications > Providers และสร้าง OAuth2/OpenID Provider ใหม่
    • Client type: Confidential
    • Redirect URIs: callback URL ของคุณ
    • Signing key: เลือกคีย์ที่มีอยู่หรือสร้างขึ้นใหม่
  2. สร้าง Application และเชื่อมโยงกับ provider
  3. คัดลอก Client ID และ Client Secret จากการตั้งค่า provider
  4. ตั้งค่า OIDC_ISSUER_URL เป็น https://authentik.example.com/application/o/snapotter/ (เครื่องหมายทับท้ายมีความสำคัญ)

Google ​

  1. ไปที่ Google Cloud Console
  2. สร้างโปรเจกต์ (หรือเลือกที่มีอยู่)
  3. ไปที่ APIs & Services > OAuth consent screen และกำหนดค่า
  4. ไปที่ APIs & Services > Credentials และสร้าง OAuth 2.0 Client ID:
    • Application type: Web application
    • Authorized redirect URIs: callback URL ของคุณ
  5. คัดลอก Client ID และ Client secret
  6. ตั้งค่า OIDC_ISSUER_URL เป็น https://accounts.google.com
  7. ตั้งค่า OIDC_USERNAME_CLAIM เป็น email (Google ไม่ให้ preferred_username)

Azure AD / Entra ID ​

  1. ในพอร์ทัล Azure ไปที่ Microsoft Entra ID > App registrations > New registration
  2. ตั้งชื่อแอปว่า "SnapOtter" ใต้ Redirect URI ให้เลือกแพลตฟอร์ม Web และป้อน callback URL ของคุณ (เช่น https://photos.example.com/api/auth/oidc/callback) อย่าเลือก Single-page application เพราะ SnapOtter ยืนยันตัวตนด้วย client secret ซึ่ง Entra ID ไม่ยอมรับสำหรับการลงทะเบียนแบบ SPA
  3. คัดลอก Application (client) ID และ Directory (tenant) ID จากหน้า Overview
  4. ไปที่ Certificates & secrets > New client secret และคัดลอก Value ของ secret ทันที ค่านี้แสดงเพียงครั้งเดียว และ Secret ID ที่อยู่ข้าง ๆ ไม่ใช่ตัว secret
  5. ตั้งค่า OIDC_ISSUER_URL เป็น https://login.microsoftonline.com/<tenant-id>/v2.0 โดยใช้ Directory (tenant) ID จากขั้นตอนที่ 3
  6. ปล่อย OIDC_USERNAME_CLAIM ไว้ที่ค่าเริ่มต้น Entra ID ให้ preferred_username มาอยู่แล้ว จึงไม่ต้องตั้งค่าทับเป็น email แบบในคู่มือ Google

ใช้ tenant ID ของคุณใน issuer URL เสมอ ไม่ใช่ common หรือ organizations เพราะ endpoint แบบ multi-tenant เหล่านั้นประกาศเทมเพลตตามตัวอักษร {tenantid} เป็น issuer ซึ่งทำให้การตรวจสอบ OIDC discovery ล้มเหลว

WARNING

preferred_username ของ Entra ID อิงตาม user principal name ซึ่งจะเปลี่ยนเมื่อผู้ใช้ถูกเปลี่ยนชื่อหรือถูกย้ายไปยัง tenant อื่น SnapOtter อ่าน claim นี้เพียงครั้งเดียวตอนเข้าสู่ระบบครั้งแรก บัญชีจึงคงชื่อผู้ใช้เดิมไว้หลังจากนั้น การเข้าสู่ระบบยังใช้งานได้ในทุกกรณี เพราะผู้ใช้ที่กลับมาจะถูกจับคู่ด้วย subject ที่คงที่ของ token ไม่ใช่ด้วยชื่อผู้ใช้

การเปลี่ยนไปใช้ Entra ID ไม่ปิดการเข้าสู่ระบบด้วยรหัสผ่าน ดู การปิดการเข้าสู่ระบบในเครื่อง

Okta และผู้ให้บริการอื่น ๆ ​

ผู้ให้บริการรายใดก็ตามที่รองรับ OIDC Discovery ใช้งานได้ในแบบเดียวกัน: สร้าง web client แบบ confidential พร้อม callback URL ของคุณ แล้วชี้ OIDC_ISSUER_URL ไปที่ issuer สำหรับ Okta ให้สร้างแอปด้วยวิธีเข้าสู่ระบบ OIDC - OpenID Connect และประเภท Web Application จากนั้นใช้โดเมน Okta ของคุณเป็น issuer (เช่น https://your-company.okta.com)

SnapOtter ไม่จับคู่กลุ่มจากผู้ให้บริการข้อมูลประจำตัวเข้ากับบทบาท ผู้ใช้ SSO ใหม่จะได้รับ OIDC_DEFAULT_ROLE ผู้ดูแลระบบเปลี่ยนบทบาทได้ที่ Settings > Users และการร้องขอ claim ของกลุ่มผ่าน OIDC_SCOPES ไม่มีผล

การจัดสรรผู้ใช้ ​

สร้างอัตโนมัติ ​

เมื่อ OIDC_AUTO_CREATE_USERS เป็น true (ค่าเริ่มต้น) บัญชีผู้ใช้ในเครื่องจะถูกสร้างขึ้นในครั้งแรกที่มีคนเข้าสู่ระบบผ่าน OIDC ชื่อผู้ใช้จะดึงมาจาก claim ที่ระบุโดย OIDC_USERNAME_CLAIM และบทบาทจะถูกตั้งเป็น OIDC_DEFAULT_ROLE

หากเกิดชื่อผู้ใช้ซ้ำกัน จะมีการต่อท้ายด้วยตัวเลข (เช่น jane กลายเป็น jane_2)

เมื่อ OIDC_AUTO_LINK_USERS เป็น true SnapOtter จะเชื่อมโยงข้อมูลประจำตัว OIDC กับบัญชีในเครื่องที่มีอยู่หากที่อยู่อีเมลตรงกัน สิ่งนี้มีประโยชน์เมื่อคุณมีบัญชีผู้ใช้ที่สร้างไว้ล่วงหน้าและต้องการให้พวกเขาเริ่มใช้ SSO โดยไม่สูญเสียข้อมูล

WARNING

เปิดใช้งานการเชื่อมโยงอัตโนมัติเฉพาะเมื่อคุณไว้ใจผู้ให้บริการ OIDC ของคุณในการตรวจสอบที่อยู่อีเมล อีเมลที่ไม่ได้รับการยืนยันอาจทำให้ใครบางคนเข้ายึดบัญชีของผู้ใช้อื่นได้

การปิดการเข้าสู่ระบบในเครื่อง ​

OIDC ไม่ปิดการเข้าสู่ระบบด้วยชื่อผู้ใช้/รหัสผ่านในเครื่อง ทั้งสองวิธียังคงใช้งานได้ ผู้ดูแลระบบยังสามารถเข้าสู่ระบบด้วยข้อมูลประจำตัวในเครื่องได้หากผู้ให้บริการ OIDC ไม่สามารถเข้าถึงได้

ใบรับรองที่เซ็นด้วยตนเอง ​

หากผู้ให้บริการ OIDC ของคุณใช้ใบรับรองที่เซ็นด้วยตนเองหรือใบรับรอง CA ส่วนตัว ให้ mount CA bundle เข้าไปในคอนเทนเนอร์และชี้ NODE_EXTRA_CA_CERTS ไปที่มัน:

yaml
services:
  SnapOtter:
    image: snapotter/snapotter:latest
    volumes:
      - ./my-ca.pem:/etc/ssl/certs/custom-ca.pem:ro
    environment:
      NODE_EXTRA_CA_CERTS: /etc/ssl/certs/custom-ca.pem
      OIDC_ENABLED: "true"
      OIDC_ISSUER_URL: "https://auth.internal.example.com/realms/myrealm"
      OIDC_CLIENT_ID: "snapotter"
      OIDC_CLIENT_SECRET: "your-secret-here"

DANGER

อย่าตั้งค่า NODE_TLS_REJECT_UNAUTHORIZED=0 สิ่งนี้จะปิดการตรวจสอบ TLS ทั้งหมดและเป็นความเสี่ยงด้านความปลอดภัย

ผู้ออกโทเค็นที่ใช้ http แบบไม่เข้ารหัส ​

SnapOtter ยอมรับ URL ของผู้ออกโทเค็นที่เป็น http:// ก็ต่อเมื่อ EXTERNAL_URL เป็น http แบบไม่เข้ารหัสด้วย ซึ่งเหมาะกับการตั้งค่าทดสอบในเครื่องหรือใน LAN ในกรณีนี้ การค้นหา (discovery) การแลกเปลี่ยนรหัสเข้าสู่ระบบ และโทเค็นจะส่งผ่านเครือข่ายโดยไม่เข้ารหัส SnapOtter จึงบันทึกคำเตือนเมื่อเริ่มทำงานโดยระบุโฮสต์ของผู้ออกโทเค็น หาก EXTERNAL_URL เป็น https:// ผู้ออกโทเค็นที่ใช้ http จะถูกปฏิเสธเมื่อเข้าสู่ระบบ และคำเตือนตอนเริ่มทำงานจะแจ้งเรื่องนี้ ไม่ว่ากรณีใด วิธีแก้คือให้บริการผู้ให้บริการข้อมูลประจำตัวผ่าน https

การแก้ไขปัญหา ​

redirect URI ไม่ตรงกัน ​

ข้อผิดพลาดที่พบบ่อยที่สุด ตรวจสอบความแตกต่างเหล่านี้ระหว่างสิ่งที่ผู้ให้บริการคาดหวังกับสิ่งที่ SnapOtter ส่ง:

  • http กับ https scheme ต้องตรงกันทุกประการ
  • เครื่องหมายทับท้าย ผู้ให้บริการบางรายเข้มงวดเรื่องนี้
  • หมายเลขพอร์ต ระบุพอร์ตหากไม่ใช่ค่ามาตรฐาน
  • Path ต้องเป็น /api/auth/oidc/callback

ตรวจสอบ EXTERNAL_URL อีกครั้ง มันต้องตรงกับ URL ที่ผู้ใช้พิมพ์ในเบราว์เซอร์

UNABLE_TO_VERIFY_LEAF_SIGNATURE ​

ผู้ให้บริการ OIDC กำลังใช้ใบรับรองที่ Node.js ไม่ไว้ใจ ดู ใบรับรองที่เซ็นด้วยตนเอง ด้านบน

ข้อผิดพลาดความคลาดเคลื่อนของนาฬิกา ​

หากนาฬิกาเซิร์ฟเวอร์และนาฬิกาผู้ให้บริการ OIDC ไม่ตรงกัน การตรวจสอบ token อาจล้มเหลว เพิ่มค่า OIDC_CLOCK_TOLERANCE (ค่าเริ่มต้นคือ 30 วินาที) วิธีแก้ที่ดีกว่าคือรัน NTP บนทั้งสองเครื่อง

"OIDC provider unreachable" ​

SnapOtter ดึงเอกสาร discovery ของผู้ให้บริการเมื่อเริ่มต้นและระหว่างการเข้าสู่ระบบ ตรวจสอบ:

  • การแปลง DNS จากภายในคอนเทนเนอร์ Docker (docker exec snapotter nslookup auth.example.com)
  • กฎไฟร์วอลล์ระหว่างคอนเทนเนอร์และผู้ให้บริการ
  • ค่า OIDC_ISSUER_URL ต้องเข้าถึงได้จากเซิร์ฟเวอร์ ไม่ใช่แค่จากเบราว์เซอร์ของคุณ

claim ที่ขาดหายไป ​

หากชื่อผู้ใช้หรืออีเมลว่างเปล่าหลังจากเข้าสู่ระบบ ผู้ให้บริการของคุณอาจไม่ได้ส่ง claim ที่คาดหวังกลับมา ตรวจสอบ:

  • scope ที่กำหนดค่าใน OIDC_SCOPES มี profile และ email
  • ผู้ให้บริการถูกกำหนดค่าให้รวม claim ที่ระบุใน OIDC_USERNAME_CLAIM ไว้ใน ID token
  • ผู้ให้บริการบางรายต้องการการกำหนดค่า mapper/scope อย่างชัดเจนเพื่อปล่อย claim