บทความทั้งหมด
GitHubGitHub AppsOAuthwebhook design

GitHub App กับ OAuth App: เทียบ webhook

ครั้งแรกที่คุณสร้างการเชื่อมต่อกับ GitHub คุณจะใช้เวลาหนึ่งชั่วโมงพยายามหาว่าควรใช้ GitHub App หรือ OAuth App เอกสารปฏิบัติต่อทั้งคู่เหมือนตัวเลือกเทียบเท่ากัน แต่ไม่ใช่ ลำพังเรื่อง webhook ก็มักพอจะตัดสินใจให้คุณได้

สรุปสั้นมาก

  • GitHub App: ติดตั้งบนบัญชีหรือ repository มีสิทธิ์แบบละเอียด รับ webhook สำหรับทรัพยากรที่มันถูกติดตั้ง ยืนยันตัวตนในฐานะตัวมันเองด้วย token อายุสั้น
  • OAuth App: ผู้ใช้อนุญาตมัน มันทำงานแทนผู้ใช้ด้วยสิทธิ์ของผู้ใช้ รับ webhook เฉพาะเมื่อมันตั้งค่าเองเหมือนเครื่องมือภายนอกทั่วไป ยืนยันตัวตนในฐานะผู้ใช้ด้วย token อายุยาว

ถ้าคุณสร้างอะไรที่ทำงานโดยไม่มีผู้ใช้ที่กำลังใช้งาน — บอต CI, การรีวิวโค้ดอัตโนมัติ, อะไรที่ทำตามกำหนดเวลา — คุณต้องการ GitHub App ถ้าคุณสร้างเครื่องมือที่ทำสิ่งต่าง ๆ แทนผู้ใช้ที่ล็อกอินอยู่ (เช่น UI ค้นหาโค้ด) OAuth App คือรูปแบบที่ถูกต้อง

วิธีที่ทั้งคู่รับ webhook

GitHub Apps

คุณตั้งค่า URL webhook หนึ่งตัวตอนสร้างแอป เมื่อผู้ใช้ติดตั้งแอปบนบัญชีหรือ repository GitHub จะเริ่มส่งอีเวนต์ของขอบเขตนั้นมายัง URL ของคุณ อีเวนต์รวมถึง installation (วงจรชีวิตติดตั้ง/ถอนติดตั้ง), installation_repositories (repo ที่เพิ่มหรือเอาออก) และชนิดอีเวนต์ที่แอปสมัครไว้ (push, pull_request ฯลฯ)

ทุกอีเวนต์มี header X-GitHub-Hook-Installation-Target-Type ("integration") และ installation ID ที่ใช้สร้าง token สำหรับการติดตั้งนั้นโดยเฉพาะได้ ลายเซ็นเป็น HMAC SHA-256 ใน X-Hub-Signature-256 — รูปแบบเดียวกับ webhook ของ repository

OAuth Apps

OAuth Apps ไม่มีการสมัคร webhook ในตัว เพื่อรับ webhook ผู้ใช้ที่อนุญาตแอปต้องสร้าง webhook ของ repository หรือ organization ที่ชี้ไปยัง URL ของแอป นั่นหมายความว่าระยะเอื้อมของ webhook ของแอปผูกกับที่ที่ผู้ใช้ตั้งค่าการสมัครไว้ ไม่ใช่ที่ที่แอปเอง "ถูกติดตั้ง"

บางทีมสร้าง OAuth Apps ที่สร้าง webhook อัตโนมัติผ่าน GitHub API หลังการอนุญาต ใช้ได้ แต่ตอนนี้คุณต้องจัดการวงจรชีวิต webhook รายผู้ใช้ควบคู่กับตรรกะของแอปเอง

การยืนยันตัวตนคือจุดต่างจริง

GitHub Apps ยืนยันตัวตนด้วยคำขอที่เซ็นด้วย JWT เพื่อสร้าง installation token อายุสั้น (1 ชั่วโมง) ต่อการติดตั้ง JWT เซ็นด้วย private key ที่คุณสร้างตอนสร้างแอป โค้ดของคุณ:

// 1. เซ็น JWT ด้วย private key ของแอป (หมดอายุ 10 นาที)
const jwt = createAppJwt(APP_ID, PRIVATE_KEY);

// 2. แลก JWT เป็น installation token (ใช้ได้ 1 ชั่วโมง)
const token = await fetchInstallationToken(jwt, INSTALLATION_ID);

// 3. เรียก API ด้วย token นั้น
const res = await fetch('https://api.github.com/repos/x/y/issues', {
  headers: { Authorization: `token ${token}` },
});

installation token จำกัดที่การติดตั้งและหมดอายุอัตโนมัติ — การรั่วจึงมีรัศมีผลกระทบจำกัด

OAuth Apps ยืนยันตัวตนด้วย user access token ที่ได้จากกระบวนการ OAuth มาตรฐาน token เหล่านี้อายุยาวโดยค่าเริ่มต้นและทำงานในฐานะผู้ใช้ — รั่วหนึ่งตัวหมายถึงผู้โจมตีทำได้ทุกอย่างที่ผู้ใช้คนนั้นทำได้ เอกสาร GitHub ผลักไปทาง GitHub Apps สำหรับการเชื่อมต่อใหม่ ส่วนหนึ่งก็ด้วยเหตุนี้

สิทธิ์: จำกัด vs กว้าง

GitHub Apps ให้คุณขอสิทธิ์แบบละเอียด: อ่าน issues, เขียน checks, อ่าน pull requests, ไม่มีสิทธิ์อื่น แต่ละสิทธิ์เป็นอิสระ ผู้ใช้เห็นรายการที่แน่ชัดและปฏิเสธได้

OAuth Apps ใช้ระบบเก่าแบบ scope: repo, read:user ฯลฯ scope หยาบกว่า scope repo ให้สิทธิ์อ่านและเขียนทุก repository ที่ผู้ใช้เห็น — ไม่มีเวอร์ชัน "อ่านอย่างเดียวบน repo เฉพาะ"

สำหรับบอตรีวิวโค้ดที่ต้องการเพียงอ่านโค้ดและเขียน check runs GitHub App ที่มีสองสิทธิ์เฉพาะรุกล้ำน้อยกว่า OAuth App ที่ขอสิทธิ์ repo เต็มมาก

ทดสอบในเครื่องทั้งคู่

กลไกลายเซ็น webhook เหมือนกัน — ดูการตั้งค่าที่ การทดสอบ webhook ของ GitHub ในเครื่อง ความต่างคือวิธีลงทะเบียน URL

  • GitHub App: ตั้ง URL webhook ในหน้าตั้งค่าของแอป ติดตั้งแอปบน repository ทดสอบ ทริกเกอร์อีเวนต์ เสร็จ
  • OAuth App: ตัวแอปเองไม่มี webhook เพิ่ม webhook ของ repository (ด้วยมือในหน้าตั้งค่า repo หรือผ่าน API) ที่ชี้ไปยัง URL tunnel ของคุณ

สำหรับ OAuth Apps คุณต้องทดสอบกระบวนการ callback OAuth เองด้วย — ดู วิธีทดสอบ callback OAuth ในเครื่อง

การย้ายระหว่างกันเจ็บปวด

ถ้าคุณเริ่มด้วย OAuth App แล้วภายหลังพบว่าต้องใช้ GitHub App คุณย้ายไม่ได้ ผู้ใช้ต้องอนุญาตแอปใหม่อีกครั้ง คุณต้องออก token ที่เก็บไว้ใหม่ และ webhook ของ repository ที่ตั้งผ่าน OAuth App จะยิงต่อไปจนกว่าจะลบ ใช้สิบนาทีตอนแรกเลือกชนิดที่ถูกต้อง

เมื่อไรเลือกอันไหน

เลือก GitHub App เมื่อ:

  • การเชื่อมต่อทำงานตามกำหนดเวลาของตัวเองหรือตอบสนองอีเวนต์ โดยไม่มีผู้ใช้ล็อกอิน
  • คุณต้องการสิทธิ์จำกัดบน repository หรือ organization เฉพาะ
  • คุณต้องการ webhook ผูกกับขอบเขตการติดตั้ง ไม่ใช่ตั้งค่าราย repo
  • คุณกำลังสร้างอะไรที่สุดท้ายจะลงใน GitHub Marketplace

เลือก OAuth App เมื่อ:

  • เครื่องมือของคุณคือ UI ที่ผู้ใช้ล็อกอินและทำสิ่งต่าง ๆ ในบัญชี GitHub ของตัวเอง
  • คุณต้องทำงานในฐานะผู้ใช้อย่างแม่นยำ รวมถึงรูปแบบการเข้าถึงของเขา
  • คุณไม่ต้องการ webhook หรือจะตั้งค่าด้วยมือราย repo

รายละเอียดการตรวจสอบลายเซ็นเบื้องล่าง ดู คู่มือตรวจสอบลายเซ็น เข้าร่วมรายชื่อรอของ PortPreview เพื่อ tunnel ที่จัดการเรื่องเวลาของ webhook GitHub และการจับเพื่อส่งซ้ำ

คำถามที่พบบ่อย

ควรสร้าง GitHub App หรือ OAuth App?
GitHub App สำหรับการเชื่อมต่อที่ทำงานอัตโนมัติ ต้องการสิทธิ์จำกัด หรือต้องการ webhook ผูกกับขอบเขตการติดตั้ง OAuth App สำหรับเครื่องมือที่ทำงานแทนผู้ใช้ที่ล็อกอิน ถ้าการเชื่อมต่อทำงานโดยไม่มีผู้ใช้อยู่ (บอต อัตโนมัติ งานตามกำหนดเวลา) เกือบทุกครั้งคือ GitHub App
webhook ของ GitHub App ต่างจาก webhook ของ repository อย่างไร?
GitHub Apps มี URL webhook ที่ตั้งไว้หนึ่งตัวซึ่งรับอีเวนต์จากทุกขอบเขตการติดตั้ง บวกอีเวนต์วงจรชีวิตการติดตั้ง webhook ของ repository ตั้งค่าราย repo และไม่รวมอีเวนต์การติดตั้ง กลไกลายเซ็น (HMAC SHA-256, X-Hub-Signature-256) เหมือนกัน
แปลง OAuth App เป็น GitHub App ได้ไหม?
ไม่ได้โดยตรง คุณต้องสร้าง GitHub App ใหม่ ขอให้ผู้ใช้ติดตั้ง ออก credential ที่เก็บไว้ใหม่ และเก็บกวาด webhook ของ repository ที่ OAuth App ตั้งไว้ ไม่มีการย้ายในตัว เลือกชนิดอย่างรอบคอบก่อนผู้ใช้เริ่มอนุญาต