คู่มือ

GitHub token และการยืนยันตัวตน Git: personal access token, Git Credential Manager และ push โดยไม่ใช้รหัสผ่าน

อัปเดต: · Skillaria.Top

ตั้งแต่เดือนสิงหาคม 2021 GitHub ไม่รับรหัสผ่านบัญชีสำหรับการทำงาน Git ผ่าน HTTPS อีกต่อไป แต่ใช้ personal access token (token) หรือการล็อกอินผ่านเบราว์เซอร์ด้วย Git Credential Manager สร้าง token ได้ที่ Settings → Developer settings บน github.com แล้วกรอกแทนรหัสผ่านตอน git push หรือ git clone ส่วน credential.helper จะเป็นตัวบันทึกไว้

ทำไม Git จึงไม่รับรหัสผ่าน GitHub อีกต่อไป

หากคุณกรอกชื่อผู้ใช้และรหัสผ่าน github.com ตอน git push แล้วถูกปฏิเสธ นั่นไม่ได้เกิดจากการพิมพ์ผิด ตั้งแต่วันที่ 13 สิงหาคม 2021 GitHub ปิดการล็อกอินด้วยรหัสผ่านสำหรับการทำงาน Git ผ่าน HTTPS ปัจจุบันต้องใช้ personal access token (PAT) หรือการยืนยันตัวตนผ่านเบราว์เซอร์ที่ Git Credential Manager ดำเนินการให้

ข้อความผิดพลาดจะหน้าตาประมาณนี้:

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/... for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/user/project.git/'

เหตุผลตรงไปตรงมา รหัสผ่านบัญชีให้สิทธิ์เต็มกับทุกอย่าง จำกัดให้ใช้กับรีโพเดียวไม่ได้ และเพิกถอนยาก ส่วน token ถูกสร้างขึ้นเพื่องานเฉพาะอย่าง มีวันหมดอายุและชุดสิทธิ์ของตัวเอง เมื่อรั่วไหล ก็ลบทิ้งได้ในไม่กี่นาทีโดยไม่ต้องเปลี่ยนรหัสผ่าน GitLab และ Bitbucket ก็เดินตามแนวทางเดียวกัน ดังนั้นสิ่งที่อธิบายด้านล่างจึงใช้ได้โดยหลักการกับทั้งสองบริการด้วย

สองวิธีการยืนยันตัวตน: HTTPS และ SSH

Git สื่อสารกับรีโพระยะไกลผ่านโปรโตคอลใดโปรโตคอลหนึ่งในสองแบบ และการยืนยันตัวตนขึ้นอยู่กับโปรโตคอลนั้น

โปรโตคอลที่อยู่รีโพยืนยันตัวตนด้วยอะไร
HTTPShttps://github.com/user/project.gitToken หรือ Git Credential Manager (ล็อกอินผ่านเบราว์เซอร์)
SSHgit@github.com:user/project.gitคู่กุญแจ SSH: กุญแจส่วนตัวอยู่ที่เครื่องคุณ กุญแจสาธารณะเพิ่มไว้ในการตั้งค่า GitHub

กุญแจ SSH ตั้งค่าเพียงครั้งเดียว หลังจากนั้น Git จะไม่ถามชื่อผู้ใช้หรือรหัสผ่านอีกเลย การสร้างและเพิ่มกุญแจ SSH ได้อธิบายไว้ในบทความเรื่องการตั้งค่า Git แล้ว ที่นี่เราจะเน้น HTTPS เพราะเป็นจุดที่มือใหม่มักพบการขอรหัสผ่านบ่อยที่สุด หากต้องการดูว่ารีโพของคุณใช้โปรโตคอลใด ให้รัน:

git remote -v
origin  https://github.com/user/project.git (fetch)
origin  https://github.com/user/project.git (push)

วิธีสร้าง token ของ GitHub (personal access token)

Personal access token คือสตริงสุ่มยาวที่ GitHub ออกให้เพื่อใช้แทนรหัสผ่านสำหรับการเข้าถึงโดยโปรแกรม Classic token ขึ้นต้นด้วย ghp_ ส่วน fine-grained token ขึ้นต้นด้วย github_pat_ Token จะแสดงเพียงครั้งเดียวหลังสร้าง จึงควรคัดลอกไปเก็บไว้ในตัวจัดการรหัสผ่านทันที

ขั้นตอน

  1. ล็อกอินที่ github.com กดรูปโปรไฟล์มุมขวาบน แล้วเปิด Settings
  2. ที่ด้านล่างของเมนูซ้าย เลือก Developer settings แล้วเลือก Personal access tokens
  3. เลือกประเภท: Fine-grained tokens (แนะนำ) หรือ Tokens (classic) แล้วกดสร้าง token ใหม่
  4. ตั้งชื่อที่จำง่าย (เช่น «โน้ตบุ๊ก งาน») วันหมดอายุ และสิทธิ์
  5. กดสร้าง แล้วคัดลอก token ทันที

Fine-grained หรือ classic

Fine-grained token จำกัดให้ใช้กับรีโพที่กำหนดเท่านั้น และให้สิทธิ์แยกย่อยได้ สำหรับการทำงานปกติกับโค้ด ให้เลือกรีโพที่ต้องการ แล้วให้สิทธิ์ Contents: Read and write ในส่วนสิทธิ์ของรีโพ ซึ่งเพียงพอสำหรับ clone, pull และ push หากคุณแค่อ่านรีโพส่วนตัว ตั้งเป็นอ่านอย่างเดียวก็พอ

Classic token ใช้ได้กับรีโพทั้งหมดของคุณพร้อมกัน การ push ไปยังรีโพต้องใช้ขอบเขต repo และหากต้องแก้ไฟล์ใน .github/workflows ต้องเพิ่มขอบเขต workflow Classic ใช้ง่ายกว่า แต่อันตรายกว่า เพราะหากรั่วไหล บัญชีทั้งบัญชีจะถูกเปิดเผย

วันหมดอายุ

GitHub มีตัวเลือกวันหมดอายุหลายแบบ และกำหนดวันที่เองได้ สามารถสร้าง token ที่ไม่มีวันหมดอายุได้ แต่ไม่แนะนำ เพราะ token ถาวรที่ถูกลืมเป็นช่องโหว่ด้านความปลอดภัยที่พบบ่อย การตั้ง 30 ถึง 90 วัน และสร้างใหม่เมื่อได้รับการแจ้งเตือนทางอีเมลจาก GitHub ก่อนหมดอายุ เป็นแนวทางที่เหมาะสม

git push และ git clone ด้วย token

การใช้ token ง่ายกว่าที่คิด Git จะถามว่า «Password» คุณเพียงวาง token ลงไปแทนรหัสผ่าน

$ git push origin main
Username for 'https://github.com': your-login
Password for 'https://your-login@github.com': <วาง token>

ในเทอร์มินัลจะไม่แสดงตัวอักษรของรหัสผ่านเลย ซึ่งเป็นเรื่องปกติ เพียงวาง token แล้วกด Enter ใน Git Bash บน Windows การวางทำได้ด้วย Shift+Insert หรือคลิกขวาเมาส์

Git clone with token

รีโพส่วนตัวก็โคลนได้ในลักษณะเดียวกัน git clone จะถามชื่อผู้ใช้และ token หากต้องการให้ทำงานโดยไม่ต้องถาม เช่นในสคริปต์ คุณสามารถใส่ token ลงในที่อยู่โดยตรง:

git clone https://your-login:<TOKEN>@github.com/user/project.git

ข้อเสียที่ต้องระวังคือ ที่อยู่ที่มี token จะถูกบันทึกไว้ใน .git/config และอาจไปปรากฏในประวัติของ shell หลังโคลนเสร็จ ควรลบ token ออกจากที่อยู่:

git remote set-url origin https://github.com/user/project.git

ในระบบ CI ให้ส่ง token ผ่านตัวแปรสภาพแวดล้อมแบบลับ ไม่ควรเขียนลงไฟล์ ใน GitHub Actions รีโพปัจจุบันมี GITHUB_TOKEN มาให้อยู่แล้ว มักไม่จำเป็นต้องใช้ PAT แยก

GitLab: git clone ด้วย token

ใน GitLab สร้าง token ในการตั้งค่าโปรไฟล์ที่ส่วน Access tokens สำหรับการทำงานกับโค้ดต้องใช้ขอบเขต read_repository และ write_repository หลักการเหมือนกัน: ใช้ชื่อผู้ใช้ GitLab เป็นชื่อผู้ใช้ และ token เป็นรหัสผ่าน

git clone https://oauth2:<TOKEN>@gitlab.com/group/project.git

GitLab รับ oauth2 เป็นชื่อผู้ใช้สำหรับ personal token ใดก็ได้ หรือจะใช้ชื่อผู้ใช้ของคุณเองก็ได้

Git pull และ fetch

สำหรับรีโพสาธารณะ git pull และ git clone ใช้ได้โดยไม่ต้องยืนยันตัวตน จะถามชื่อผู้ใช้และ token เฉพาะกับรีโพส่วนตัวหรือเมื่อ git push หากการ pull ในโปรเจกต์สาธารณะถามรหัสผ่านขึ้นมา ส่วนใหญ่มักเป็นที่อยู่ที่พิมพ์ผิด เพราะ GitHub ตอบสนองต่อรีโพที่ไม่มีอยู่จริงเหมือนกับรีโพส่วนตัว

Git Credential Manager คืออะไร

การกรอก token ทุกครั้งที่ push เป็นเรื่องน่ารำคาญ งานนี้ถูกมอบให้ credential helper ซึ่งเป็นโปรแกรมช่วยที่ Git เรียกใช้เมื่อต้องการข้อมูลการยืนยันตัวตน Git ส่งที่อยู่เซิร์ฟเวอร์ให้ แล้วโปรแกรมจะคืนชื่อผู้ใช้และรหัสผ่าน (หรือ token) จากที่เก็บของมัน

Git Credential Manager (GCM) เป็นตัวช่วยที่สะดวกที่สุดในกลุ่มนี้ เป็นโปรแกรมข้ามแพลตฟอร์มจาก GitHub และ Microsoft: ตอน push ครั้งแรกจะเปิดหน้าต่างหรือเบราว์เซอร์สำหรับล็อกอิน คุณยืนยันตัวตนบน GitHub (รวมถึงการยืนยันตัวตนสองขั้นตอน) จากนั้น GCM จะรับ token มาเองและเก็บไว้ในที่เก็บที่ปลอดภัยของระบบ ในกรณีนี้ไม่ต้องสร้าง PAT ด้วยตนเอง

GCM รองรับ GitHub, GitLab, Bitbucket และ Azure DevOps ใน Git for Windows มันถูกติดตั้งมาให้เป็นค่าเริ่มต้น และเป็นตัวเลือก credential helper ในตัวติดตั้งนั่นเอง

ค่า credential.helper ที่ใช้บ่อย

ค่าเก็บไว้ที่ไหนเหมาะกับเมื่อไร
managerGit Credential Manager: Windows Credential Manager, macOS Keychain, Secret Service บน Linuxแนะนำสำหรับเครื่องทำงาน
osxkeychainmacOS Keychainhelper มาตรฐานของ Git บน Mac
cacheในหน่วยความจำ ค่าเริ่มต้น 15 นาทีเซิร์ฟเวอร์ Linux ที่ไม่ต้องการเก็บ token ไว้ในดิสก์
storeเก็บเป็นข้อความธรรมดาใน ~/.git-credentialsใช้เฉพาะเครื่องที่แยกจากเครือข่าย ผู้ใดก็ตามที่อ่านไฟล์ได้จะเห็น token

ตั้งค่าการยืนยันตัวตน Git บน Windows, macOS และ Linux

ดูว่า helper ใดถูกตั้งค่าอยู่แล้ว:

git config --show-origin --get-all credential.helper

Windows

หากคุณเก็บการตั้งค่าเริ่มต้นตอนติดตั้ง Git แล้ว GCM ก็ใช้งานได้ทันที: การ push ครั้งแรกใน Git Bash, PowerShell หรือ VS Code จะเปิดหน้าต่างล็อกอิน GitHub หากยังไม่ได้ตั้งค่า helper ให้เปิดใช้งานด้วยตนเอง:

git config --global credential.helper manager

macOS

Git บน Mac มักใช้ osxkeychain อยู่แล้ว token ที่กรอกไว้ครั้งเดียวจะถูกเก็บใน Keychain หากต้องการล็อกอินผ่านเบราว์เซอร์ ให้ติดตั้ง Git Credential Manager (เช่นผ่าน Homebrew: brew install --cask git-credential-manager) มันจะตั้งค่าตัวเองในการตั้งค่า Git ให้

Linux

บน Linux ต้องติดตั้ง GCM แยกต่างหาก (แพ็กเกจ .deb หรือไฟล์บีบอัดจากหน้าปล่อยเวอร์ชันของโปรเจกต์) จากนั้นตั้งค่าและเลือกที่เก็บ:

git-credential-manager configure
git config --global credential.credentialStore secretservice

บนเซิร์ฟเวอร์ที่ไม่มี GUI วิธีที่ง่ายกว่าคือแคชชั่วคราว:

git config --global credential.helper 'cache --timeout=3600'

ทางเลือกสำหรับ GitHub: gh auth login

หากติดตั้ง GitHub CLI ไว้ คำสั่ง gh auth login จะพาคุณล็อกอินผ่านเบราว์เซอร์ และ gh auth setup-git จะตั้งค่า Git ให้ไปดึงข้อมูลการยืนยันตัวตนจาก gh นี่เป็นวิธีที่สะดวกในการ «ล็อกอินใน Git Bash» ด้วยคำสั่งเดียว

วิธีล้างหรืออัปเดตรหัสผ่าน Git ที่บันทึกไว้

สถานการณ์ที่พบบ่อยที่สุดคือ token หมดอายุ หรือคุณเปลี่ยนบัญชี แต่ Git ยังใช้ข้อมูลเก่าอยู่ ผลคือ Authentication failed ต้องลบข้อมูลที่บันทึกไว้ แล้ว Git จะถามใหม่ในการ push ครั้งถัดไป

คำสั่งทั่วไป

ใช้ได้กับ helper ทุกตัว:

printf "protocol=https\nhost=github.com\n\n" | git credential reject

Git reset credentials บน Windows

เปิด «Control Panel» → «Credential Manager» → «Windows Credentials» หาแถวที่ขึ้นต้นด้วย git:https://github.com แล้วลบ หรือทำในบรรทัดคำสั่ง:

cmdkey /list | findstr git
cmdkey /delete:git:https://github.com

หากใช้ GCM ก็มีคำสั่งออกจากระบบของตัวเองด้วย: git credential-manager github logout <ชื่อผู้ใช้>

macOS

เปิด «Keychain Access» หารายการ github.com ประเภท «Internet password» แล้วลบ หรือทำในเทอร์มินัล:

git credential-osxkeychain erase
host=github.com
protocol=https

หลังบรรทัดสุดท้าย กด Enter อีกครั้งเพื่อส่งบรรทัดว่าง

Linux และ store

สำหรับ store ให้ลบบรรทัดที่มี github.com ออกจาก ~/.git-credentials สำหรับ cache รัน git credential-cache exit

ข้อผิดพลาดการยืนยันตัวตนและวิธีแก้

Support for password authentication was removed

คุณกรอกรหัสผ่านบัญชี ให้สร้าง token แล้ววางลงในช่อง Password หรือตั้งค่า Git Credential Manager หากข้อผิดพลาดยังเกิดซ้ำโดยไม่มีการขอรหัสผ่าน แสดงว่ารหัสผ่านเก่ายังค้างอยู่ในที่เก็บ ให้ลบตามวิธีข้างต้น

git push: Authentication failed

สาเหตุเรียงตามความถี่: token หมดอายุแล้ว; token ถูกเพิกถอน; token แบบ fine-grained ไม่มีสิทธิ์เข้าถึงรีโพนี้ หรือ Contents ให้สิทธิ์อ่านอย่างเดียว; ที่เก็บมีข้อมูลของบัญชีอื่นค้างอยู่ ตรวจสอบวันหมดอายุและสิทธิ์ของ token ใน Developer settings แล้วล้างข้อมูลที่บันทึกไว้

remote: Permission denied (403)

การยืนยันตัวตนผ่านแล้ว แต่บัญชีของคุณไม่มีสิทธิ์เขียนในรีโพนี้ เจ้าของต้องเพิ่มคุณเป็น Collaborators หรือคุณทำงานผ่าน fork ของตัวเองและส่ง pull request

Repository not found

สำหรับรีโพส่วนตัว GitHub จะไม่เปิดเผยว่ารีโพมีอยู่จริงหรือไม่ ดังนั้นหาก token ผิด ก็จะแสดง «not found» ตรวจที่อยู่ด้วย git remote -v และสิทธิ์ของ token

Git clone ขอรหัสผ่านทุกครั้ง

แปลว่ายังไม่ได้ตั้งค่า credential helper ให้เปิดใช้ manager หรือ osxkeychain เมื่อกรอกสำเร็จครั้งแรก Git จะหยุดถาม อีกทางเลือกคือเปลี่ยนไปใช้ SSH

วิธีเก็บ token อย่างปลอดภัย

  • ให้สิทธิ์น้อยที่สุด: ใช้ fine-grained token ที่จำกัดเฉพาะรีโพที่ต้องการ แทนที่ classic token ที่มีขอบเขต repo
  • ตั้งวันหมดอายุ และสร้าง token ใหม่เมื่อหมดอายุ ไม่ใช่ต่ออายุไปเรื่อย ๆ
  • อย่า commit token และอย่าใส่ลงในที่อยู่ remote หาก token หลุดไปยังรีโพสาธารณะ GitHub อาจเพิกถอนให้อัตโนมัติ แต่คุณควรถือว่ามันรั่วแล้วและลบด้วยตัวเอง
  • ใช้ที่เก็บของระบบ (GCM, Keychain) แทน store
  • หนึ่ง token ต่อหนึ่งเครื่องหรือหนึ่งงาน: เมื่อหลุด คุณจะเพิกถอนเฉพาะ token นั้น

สรุป

รหัสผ่าน GitHub ใช้กับ Git ผ่าน HTTPS ไม่ได้ตั้งแต่ปี 2021 มีสามทางที่ใช้ได้: ล็อกอินผ่านเบราว์เซอร์ด้วย Git Credential Manager สร้าง token ของ GitHub แล้วกรอกแทนรหัสผ่าน หรือเปลี่ยนไปใช้กุญแจ SSH token สร้างได้ที่ Settings → Developer settings และ credential.helper เป็นผู้บันทึกไว้ เมื่อเจอ Authentication failed มักแก้ได้ด้วยการสร้าง token ใหม่และล้างข้อมูลเก่า การเชื่อมต่อกับ GitHub และการทำงานกับรีโพระยะไกลมีการอธิบายโดยละเอียดในคอร์ส Git ด้วย

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

หลังสร้างแล้วดู token ของ GitHub อีกครั้งได้หรือไม่?

ไม่ได้ GitHub แสดง token เพียงครั้งเดียว หากยังไม่ได้บันทึกไว้ ให้ลบ token เดิมแล้วสร้างใหม่

การ git clone รีโพสาธารณะต้องใช้ token หรือไม่?

ไม่ต้อง รีโพสาธารณะสามารถ clone ด้วย git clone และอัปเดตด้วย git pull ได้โดยไม่ต้องยืนยันตัวตน token จำเป็นเฉพาะกับรีโพส่วนตัวและ git push

เกิดอะไรขึ้นเมื่อ token หมดอายุ?

Git จะเริ่มแสดง Authentication failed ให้สร้าง token ใหม่ (หรือกด Regenerate กับ token เดิม) ลบข้อมูลที่บันทึกไว้ และกรอก token ใหม่ในการ push ครั้งถัดไป

token ของ GitHub ใช้กับบัญชีที่เปิดการยืนยันตัวตนสองขั้นตอนได้หรือไม่?

ได้ และจำเป็นเมื่อเปิด 2FA เพราะ token ใช้แทนทั้งรหัสผ่านและรหัสยืนยันสำหรับการทำงานของ Git Git Credential Manager ที่ล็อกอินผ่านเบราว์เซอร์จะผ่าน 2FA ให้เอง

Git เก็บชื่อผู้ใช้และรหัสผ่านไว้ที่ไหน?

Git ไม่ได้เก็บเอง แต่ credential helper เป็นผู้เก็บ ได้แก่ Windows Credential Manager, macOS Keychain, Secret Service บน Linux หรือไฟล์ ~/.git-credentials เมื่อใช้ helper แบบ store

เรียนหัวข้อนี้ผ่านวิดีโอ

หัวข้อนี้สอนอย่างละเอียดพร้อมฝึกปฏิบัติในคอร์ส “Git с нуля до уверенного разработчика”

ไปที่คอร์ส