使用 Azure DevOps OAuth 2.0 建立 Web 應用程式

Azure DevOps Services

重要

此資訊僅適用於現有的 Azure DevOps OAuth 應用程式。 新的應用程式開發人員應該使用 Microsoft Entra ID OAuth 來與 Azure DevOps 整合。

Azure DevOps 是 OAuth 2.0 應用程式的識別提供者。 我們的 OAuth 2.0 實作可讓開發人員授權其應用程式給使用者,並取得 Azure DevOps 資源的存取令牌。

開始使用 Azure DevOps OAuth

1.註冊您的應用程式

  1. 移至 以 https://app.vsaex.visualstudio.com/app/register 註冊您的應用程式。

  2. 選取應用程式所需的範圍,然後在您授權應用程式時使用相同的範圍。 如果您使用預覽 API 註冊應用程式,請重新註冊,因為您所使用的範圍現在已被取代。

  3. 選取 [ 建立應用程式]。

    應用程式設定頁面隨即顯示。

    Screenshot showing Applications settings for your app.

    • 當 Azure DevOps Services 向使用者顯示授權核准頁面時,它會使用您的公司名稱、應用程式名稱和描述。 它也會使用公司網站的 URL、應用程式網站,以及服務條款和隱私聲明。

      Screenshot showing Visual Studio Codespaces authorization page with your company and app information.

    • 當 Azure DevOps Services 要求使用者的授權,而使用者授與授權時,使用者的瀏覽器會以授權碼重新導向至您的授權回呼 URL。 回呼 URL 必須是安全連線(https),才能將程式代碼傳輸回應用程式,並完全符合您應用程式中註冊的 URL。 如果沒有,則會顯示 400 錯誤頁面,而不是要求使用者將授權授與您的應用程式的頁面。

  4. 當您想要讓使用者授權您的應用程式存取其組織時,請呼叫授權 URL 並傳遞您的應用程式識別碼和授權範圍。 當您想要取得存取令牌來呼叫 Azure DevOps Services REST API 時,請呼叫存取令牌 URL。

您註冊的每個應用程式設定都可從您的設定檔 https://app.vssps.visualstudio.com/profile/view取得。

2.授權您的應用程式

  1. 如果使用者未授權您的應用程式存取其組織,請呼叫授權 URL。 如果使用者核准授權,它會以授權碼呼叫您。
https://app.vssps.visualstudio.com/oauth2/authorize
        ?client_id={app ID}
        &response_type={Assertion}
        &state={state}
        &scope={scope}
        &redirect_uri={callback URL}
參數 類型 備註
client_id GUID 註冊應用程式時指派給應用程式的標識碼。
response_type string Assertion
State 字串 可以是任何值。 通常產生的字串值,將回呼與其相關聯的授權要求相互關聯。
範圍 (scope) string 向應用程式註冊的範圍。 以空格分隔。 請參閱 可用的範圍
redirect_uri URL 應用程式的回呼 URL。 必須與向應用程式註冊的URL完全相符。
  1. 將連結或按鈕新增至您的網站,以將使用者帶到 Azure DevOps Services 授權端點:
https://app.vssps.visualstudio.com/oauth2/authorize
        ?client_id=88e2dd5f-4e34-45c6-a75d-524eb2a0399e
        &response_type=Assertion
        &state=User1
        &scope=vso.work%20vso.code_write
        &redirect_uri=https://fabrikam.azurewebsites.net/myapp/oauth-callback

Azure DevOps Services 會要求使用者授權您的應用程式。

假設使用者接受,Azure DevOps Services 會將使用者的瀏覽器重新導向至您的回呼 URL,包括短期授權碼和授權 URL 中提供的狀態值:

https://fabrikam.azurewebsites.net/myapp/oauth-callback
        ?code={authorization code}
        &state=User1

3.取得使用者的存取權和重新整理令牌

使用授權碼來要求使用者的存取令牌(並重新整理令牌)。 您的服務必須對 Azure DevOps Services 提出服務對服務 HTTP 要求。

URL - 授權應用程式

POST https://app.vssps.visualstudio.com/oauth2/token

HTTP 要求標頭 - 授權應用程式

頁首
內容-類型 application/x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded

HTTP 要求本文 - 授權應用程式

client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={1}&redirect_uri={2}

取代先前範例要求本文中的佔位元值:

  • {0}:註冊應用程式時取得的 URL 編碼客戶端密碼
  • {1}:透過查詢參數提供給回呼 URL 的 code URL 編碼“程序代碼”
  • {2}:向應用程式註冊的回呼 URL

形成要求本文的 C# 範例 - 授權應用程式

public string GenerateRequestPostData(string appSecret, string authCode, string callbackUrl)
{
   return String.Format("client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion={1}&redirect_uri={2}",
               HttpUtility.UrlEncode(appSecret),
               HttpUtility.UrlEncode(authCode),
               callbackUrl
        );
}

回應 - 授權應用程式

{
    "access_token": { access token for the user },
    "token_type": { type of token },
    "expires_in": { time in seconds that the token remains valid },
    "refresh_token": { refresh token to use to acquire a new access token }
}

重要

安全地保存refresh_token讓您的應用程式不需要提示使用者再次授權。 存取令牌會快速過期,且不應該保存。

4.使用存取令牌

若要使用存取令牌,請在 HTTP 要求的授權標頭中包含它作為持有人令牌:

Authorization: Bearer {access_token}

例如,要 取得專案最近組建 的 HTTP 要求:

GET https://dev.azure.com/myaccount/myproject/_apis/build-release/builds?api-version=3.0
Authorization: Bearer {access_token}

5.重新整理過期的存取令牌

如果使用者的存取令牌過期,您可以使用他們在授權流程中取得的重新整理令牌來取得新的存取令牌。 就像交換存取和重新整理令牌授權碼的原始程序一樣。

URL - 重新整理令牌

POST https://app.vssps.visualstudio.com/oauth2/token

HTTP 要求標頭 - 重新整理令牌

頁首
內容-類型 application/x-www-form-urlencoded
Content-Length 要求本文的匯出字串長度(請參閱下列範例)
Content-Type: application/x-www-form-urlencoded
Content-Length: 1654

HTTP 要求本文 - 重新整理令牌

client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion={0}&grant_type=refresh_token&assertion={1}&redirect_uri={2}

取代先前範例要求本文中的佔位元值:

  • {0}:註冊應用程式時取得的 URL 編碼客戶端密碼
  • {1}:使用者 URL 編碼的重新整理令牌
  • {2}:向應用程式註冊的回呼 URL

回應 - 重新整理令牌

{
    "access_token": { access token for this user },
    "token_type": { type of token },
    "expires_in": { time in seconds that the token remains valid },
    "refresh_token": { new refresh token to use when the token has timed out }
}

重要

系統會為用戶發出新的重新整理令牌。 保存這個新的令牌,並在下次您需要為使用者取得新的存取令牌時使用它。

範例

您可以在 C# OAuth GitHub 範例中找到 實作 OAuth 的 C# 範例,以呼叫 Azure DevOps Services REST API。

重新產生客戶端密碼

每 5 年,您的應用程式密碼將會過期。 您應該重新產生應用程式秘密,才能繼續建立和使用存取令牌和重新整理令牌。 若要這樣做,您可以按兩下 [重新產生秘密] 按鈕,這會快顯對話框以確認您想要完成此動作。

Screenshot confirming secret regeneration.

當您確認要重新產生時,先前的應用程式密碼將無法再運作,而且所有使用此秘密所繪製的先前令牌也會停止運作。 請務必讓此用戶端秘密輪替順利進行,以將任何客戶停機時間降到最低。

常見問題集 (FAQ)

問:是否可以將 OAuth 與我的行動電話應用程式搭配使用?

A: 不可以。 Azure DevOps Services 僅支援 Web 伺服器流程,因此無法實作 OAuth,因為您無法安全地儲存應用程式密碼。

問:我需要在程式代碼中處理哪些錯誤或特殊狀況?

答:請確定您處理下列條件:

  • 如果您的使用者拒絕應用程式存取權,則不會傳回任何授權碼。 請勿在沒有檢查拒絕的情況下使用授權碼。
  • 如果使用者撤銷應用程式的授權,存取令牌就不再有效。 當您的應用程式使用令牌來存取數據時,會傳回 401 錯誤。 再次要求授權。

問:我想在本機對 Web 應用程式進行偵錯。 當我註冊應用程式時,是否可以將localhost用於回呼URL?

A: 可以。 Azure DevOps Services 現在可在回呼 URL 中允許 localhost。 當您註冊應用程式時,請務必使用 https://localhost 作為回呼 URL 的開頭。

問:當我嘗試取得存取令牌時,我會收到 HTTP 400 錯誤。 可能出了什麼問題?

答:請檢查您是否在要求標頭中將內容類型設定為 application/x-www-form-urlencoded。

問:當我使用 OAuth 型存取令牌時,我會收到 HTTP 401 錯誤,但具有相同範圍的 PAT 運作正常。 為什麼?

答:確認貴組織的系統管理員https://dev.azure.com/{your-org-name}/_settings/organizationPolicy未停用透過 OAuth 的第三方應用程式存取權。 在此案例中,授權應用程式併產生存取令牌的流程可運作,但所有 REST API 只會傳回錯誤,例如 TF400813: The user "<GUID>" is not authorized to access this resource.

問:我可以搭配 SOAP 端點和 REST API 使用 OAuth 嗎?

A: 不可以。 目前只有 REST API 支援 OAuth。

問:如何使用 Azure DevOps REST API 取得工作專案的附件詳細數據?

答:首先,使用 工作專案取得工作專案詳細數據 - 取得工作專案 REST API:

GET https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{id}

若要取得附件詳細數據,您必須將下列參數新增至URL:

$expand=all

使用結果時,您會取得關聯屬性。 您可以在該處找到附件 URL,並在 URL 內找到識別碼。 例如:

$url = https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/434?$expand=all&api-version=5.0

$workItem = Invoke-RestMethod -Uri $url -Method Get -ContentType application/json

$split = ($workitem.relations.url).Split('/')

$attachmentId = $split[$split.count - 1]

# Result: 1244nhsfs-ff3f-25gg-j64t-fahs23vfs