<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Auth on Tarragon</title><link>https://tarrragon.github.io/blog/tags/auth/</link><description>Recent content in Auth on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Thu, 09 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/auth/index.xml" rel="self" type="application/rss+xml"/><item><title>git credential helper</title><link>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/git-credential-helper/</link><pubDate>Thu, 09 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/git-credential-helper/</guid><description>&lt;p>git credential helper 是一個 git 用來取得 HTTPS 認證的&lt;strong>可替換外部程式&lt;/strong>：git 自己不儲存也不硬編任何帳密，每次要對遠端認證時把要求交給設定好的 helper、由它回傳使用者名與密碼。這讓「認證從哪來、存在哪」跟 git 本身解耦——換一個 helper 就換一套憑證來源，git 的其餘行為不動。理解這一點，就看得出「&lt;code>gh auth login&lt;/code> 幫你設好」跟「手動把 helper 指到某個程式」是同一個機制的兩種配置，而不是兩件不相關的事。這條路徑只管 HTTPS；SSH 走的是另一條認證路，見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/ssh-key-storage/" data-link-title="SSH Key Storage（SSH 金鑰儲放與 authorized_keys）" data-link-desc="配置 SSH 免密碼登入、要知道私鑰放哪、公鑰怎麼授權、多裝置各自的鑰匙怎麼管、或高權限操作該不該給完整金鑰時回來讀">SSH 金鑰儲放與 authorized_keys&lt;/a>。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>HTTPS + token 走 credential helper，跟 SSH 走金鑰是兩條平行的 git 認證路（SSH 端的金鑰儲放見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/ssh-key-storage/" data-link-title="SSH Key Storage（SSH 金鑰儲放與 authorized_keys）" data-link-desc="配置 SSH 免密碼登入、要知道私鑰放哪、公鑰怎麼授權、多裝置各自的鑰匙怎麼管、或高權限操作該不該給完整金鑰時回來讀">SSH 金鑰儲放與 authorized_keys&lt;/a>）。&lt;/p>
&lt;h2 id="機制git-把認證外包給一個程式">機制：git 把認證外包給一個程式&lt;/h2>
&lt;p>git 對 HTTPS 遠端操作（clone / fetch / push）需要憑證時，不自己去記，而是走一個標準協定呼叫 helper：git 把 &lt;code>protocol=https&lt;/code>、&lt;code>host=github.com&lt;/code> 這些欄位從 stdin 餵給 helper，helper 把 &lt;code>username=...&lt;/code>、&lt;code>password=...&lt;/code> 從 stdout 回傳，git 拿去組認證。整個過程不需要人打字，也不把憑證留在 git 的設定裡。&lt;/p>
&lt;h2 id="helper-是可替換的換-helper-就換憑證後端">helper 是可替換的：換 helper 就換憑證後端&lt;/h2>
&lt;p>&lt;code>credential.helper&lt;/code> 設定值決定用哪個 helper，每個對應一種憑證儲存後端：&lt;/p>
&lt;ul>
&lt;li>&lt;code>cache&lt;/code> 存在記憶體、限時；&lt;code>store&lt;/code> 明文存 &lt;code>~/.git-credentials&lt;/code>（方便但不安全）。&lt;/li>
&lt;li>平台鑰匙圈：macOS 的 &lt;code>osxkeychain&lt;/code>、Windows 的 &lt;code>manager&lt;/code>。&lt;/li>
&lt;li>&lt;code>!&amp;lt;command&amp;gt;&lt;/code>：驚嘆號開頭表示「把後面當 shell 命令執行」，可指到任意程式。例如 &lt;code>!gh auth git-credential&lt;/code> 把認證外包給 GitHub CLI、由它現讀 &lt;code>GH_TOKEN&lt;/code> 環境變數回傳。&lt;/li>
&lt;/ul>
&lt;p>因為 helper 可替換，同一個「git 怎麼拿到 GitHub 憑證」的問題可以用不同後端解：互動式 &lt;code>gh auth login&lt;/code> 會自動幫你把 helper 設成 gh、憑證存進 gh 的登入檔；容器化無人值守則手動設 &lt;code>!gh auth git-credential&lt;/code> 配注入的 &lt;code>GH_TOKEN&lt;/code>，讓憑證每次現讀環境變數、不落任何檔（機密怎麼注入見 &lt;a href="https://tarrragon.github.io/blog/linux/dotfile/knowledge-cards/runtime-secret-injection/" data-link-title="Runtime Secret Injection（機密注入）" data-link-desc="要決定 token / 金鑰放哪、能不能烤進 image 或提交進（即使私有的）repo 時回來讀">機密 runtime 注入&lt;/a>）。兩者設定形式不同，但都是「配置 credential helper」這一件事。&lt;/p>
&lt;h2 id="為什麼認證不落在-git-本身">為什麼認證不落在 git 本身&lt;/h2>
&lt;p>git 的設定檔（&lt;code>.gitconfig&lt;/code>）只存「用哪個 helper」這個指標、不存憑證本身。這條分工讓憑證的儲存策略獨立於 git：要更安全就指到鑰匙圈或現讀環境變數的 helper、要方便就用 &lt;code>store&lt;/code>，換策略只改一行 &lt;code>credential.helper&lt;/code>、不動 git 的其他設定，也不會把 token 硬編進版控的檔案。&lt;/p>
&lt;h2 id="判讀訊號--邊界">判讀訊號 / 邊界&lt;/h2>
&lt;ul>
&lt;li>git 對私有 repo 要求輸入帳號密碼、或非互動下回 &lt;code>could not read Username&lt;/code>，是「沒有 helper 回得出憑證」的訊號——不是網路問題，是認證來源沒設好。&lt;/li>
&lt;li>helper 可以疊：git 依序問每個設定的 helper、第一個回得出憑證的勝出。&lt;code>gh auth setup-git&lt;/code> 產生的設定會先放一行空 &lt;code>helper=&lt;/code> 清掉繼承的 helper、再指到 gh，避免別的 helper（如系統鑰匙圈）先攔。乾淨環境沒有繼承 helper 時單行就夠。&lt;/li>
&lt;li>helper 只管 HTTPS 這條路。git submodule 或 remote 走 SSH（&lt;code>git@github.com:&lt;/code>）時不經 credential helper、走的是 SSH 金鑰那條路。&lt;/li>
&lt;li>helper 回傳的是「當下這次操作」的憑證，不改變遠端的授權範圍——token 本身權限不足（如只有讀權限卻要 push）不是 helper 的問題，helper 已經把 token 正確帶到了。&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>git credential helper 是一個 git 用來取得 HTTPS 認證的<strong>可替換外部程式</strong>：git 自己不儲存也不硬編任何帳密，每次要對遠端認證時把要求交給設定好的 helper、由它回傳使用者名與密碼。這讓「認證從哪來、存在哪」跟 git 本身解耦——換一個 helper 就換一套憑證來源，git 的其餘行為不動。理解這一點，就看得出「<code>gh auth login</code> 幫你設好」跟「手動把 helper 指到某個程式」是同一個機制的兩種配置，而不是兩件不相關的事。這條路徑只管 HTTPS；SSH 走的是另一條認證路，見 <a href="/blog/linux/dotfile/knowledge-cards/ssh-key-storage/" data-link-title="SSH Key Storage（SSH 金鑰儲放與 authorized_keys）" data-link-desc="配置 SSH 免密碼登入、要知道私鑰放哪、公鑰怎麼授權、多裝置各自的鑰匙怎麼管、或高權限操作該不該給完整金鑰時回來讀">SSH 金鑰儲放與 authorized_keys</a>。</p>
<h2 id="概念位置">概念位置</h2>
<p>HTTPS + token 走 credential helper，跟 SSH 走金鑰是兩條平行的 git 認證路（SSH 端的金鑰儲放見 <a href="/blog/linux/dotfile/knowledge-cards/ssh-key-storage/" data-link-title="SSH Key Storage（SSH 金鑰儲放與 authorized_keys）" data-link-desc="配置 SSH 免密碼登入、要知道私鑰放哪、公鑰怎麼授權、多裝置各自的鑰匙怎麼管、或高權限操作該不該給完整金鑰時回來讀">SSH 金鑰儲放與 authorized_keys</a>）。</p>
<h2 id="機制git-把認證外包給一個程式">機制：git 把認證外包給一個程式</h2>
<p>git 對 HTTPS 遠端操作（clone / fetch / push）需要憑證時，不自己去記，而是走一個標準協定呼叫 helper：git 把 <code>protocol=https</code>、<code>host=github.com</code> 這些欄位從 stdin 餵給 helper，helper 把 <code>username=...</code>、<code>password=...</code> 從 stdout 回傳，git 拿去組認證。整個過程不需要人打字，也不把憑證留在 git 的設定裡。</p>
<h2 id="helper-是可替換的換-helper-就換憑證後端">helper 是可替換的：換 helper 就換憑證後端</h2>
<p><code>credential.helper</code> 設定值決定用哪個 helper，每個對應一種憑證儲存後端：</p>
<ul>
<li><code>cache</code> 存在記憶體、限時；<code>store</code> 明文存 <code>~/.git-credentials</code>（方便但不安全）。</li>
<li>平台鑰匙圈：macOS 的 <code>osxkeychain</code>、Windows 的 <code>manager</code>。</li>
<li><code>!&lt;command&gt;</code>：驚嘆號開頭表示「把後面當 shell 命令執行」，可指到任意程式。例如 <code>!gh auth git-credential</code> 把認證外包給 GitHub CLI、由它現讀 <code>GH_TOKEN</code> 環境變數回傳。</li>
</ul>
<p>因為 helper 可替換，同一個「git 怎麼拿到 GitHub 憑證」的問題可以用不同後端解：互動式 <code>gh auth login</code> 會自動幫你把 helper 設成 gh、憑證存進 gh 的登入檔；容器化無人值守則手動設 <code>!gh auth git-credential</code> 配注入的 <code>GH_TOKEN</code>，讓憑證每次現讀環境變數、不落任何檔（機密怎麼注入見 <a href="/blog/linux/dotfile/knowledge-cards/runtime-secret-injection/" data-link-title="Runtime Secret Injection（機密注入）" data-link-desc="要決定 token / 金鑰放哪、能不能烤進 image 或提交進（即使私有的）repo 時回來讀">機密 runtime 注入</a>）。兩者設定形式不同，但都是「配置 credential helper」這一件事。</p>
<h2 id="為什麼認證不落在-git-本身">為什麼認證不落在 git 本身</h2>
<p>git 的設定檔（<code>.gitconfig</code>）只存「用哪個 helper」這個指標、不存憑證本身。這條分工讓憑證的儲存策略獨立於 git：要更安全就指到鑰匙圈或現讀環境變數的 helper、要方便就用 <code>store</code>，換策略只改一行 <code>credential.helper</code>、不動 git 的其他設定，也不會把 token 硬編進版控的檔案。</p>
<h2 id="判讀訊號--邊界">判讀訊號 / 邊界</h2>
<ul>
<li>git 對私有 repo 要求輸入帳號密碼、或非互動下回 <code>could not read Username</code>，是「沒有 helper 回得出憑證」的訊號——不是網路問題，是認證來源沒設好。</li>
<li>helper 可以疊：git 依序問每個設定的 helper、第一個回得出憑證的勝出。<code>gh auth setup-git</code> 產生的設定會先放一行空 <code>helper=</code> 清掉繼承的 helper、再指到 gh，避免別的 helper（如系統鑰匙圈）先攔。乾淨環境沒有繼承 helper 時單行就夠。</li>
<li>helper 只管 HTTPS 這條路。git submodule 或 remote 走 SSH（<code>git@github.com:</code>）時不經 credential helper、走的是 SSH 金鑰那條路。</li>
<li>helper 回傳的是「當下這次操作」的憑證，不改變遠端的授權範圍——token 本身權限不足（如只有讀權限卻要 push）不是 helper 的問題，helper 已經把 token 正確帶到了。</li>
</ul>
]]></content:encoded></item></channel></rss>