다음을 통해 공유


Azure DevOps OAuth 2.0을 사용하여 웹앱 만들기

Azure DevOps Services

Important

이 정보는 기존 Azure DevOps OAuth 앱에만 해당됩니다. 새 앱 개발자는 Microsoft Entra ID OAuth를 사용하여 Azure DevOps와 통합해야 합니다.

Azure DevOps는 OAuth 2.0 앱용 ID 공급자입니다. 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은 코드를 앱으로 다시 전송하고 앱에 등록된 URL과 정확히 일치하려면 보안 연결(https)이어야 합니다. 그렇지 않으면 사용자에게 앱에 대한 권한 부여를 요청하는 페이지 대신 400 오류 페이지가 표시됩니다.

  4. 사용자가 조직에 액세스하도록 앱에 권한을 부여하려는 경우 권한 부여 URL을 호출하고 앱 ID 및 권한 있는 범위를 전달합니다. 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 앱이 등록되었을 때 할당된 ID입니다.
response_type string Assertion
state string 임의의 값일 수 있습니다. 일반적으로 콜백과 연결된 권한 부여 요청의 상관 관계를 지정하는 생성된 문자열 값입니다.
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}: 쿼리 매개 변수를 통해 code 콜백 URL로 제공된 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 }
}

Important

앱에서 사용자에게 다시 권한을 부여하라는 메시지를 표시할 필요가 없도록 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 }
}

Important

사용자에 대해 새 새로 고침 토큰이 발급됩니다. 이 새 토큰을 보관하고 다음에 사용자에 대한 새 액세스 토큰을 획득해야 할 때 사용합니다.

샘플

C# OAuth GitHub 샘플에서 Azure DevOps Services REST API를 호출하는 OAuth를 구현하는 C# 샘플을 찾을 수 있습니다.

클라이언트 암호 다시 생성

5년마다 애플리케이션 비밀이 만료됩니다. 액세스 토큰 및 새로 고침 토큰을 계속 만들고 사용할 수 있도록 앱 비밀을 다시 생성해야 합니다. 이렇게 하려면 "비밀 다시 생성" 단추를 클릭하면 대화 상자가 표시되어 이 작업을 완료할 것인지 확인할 수 있습니다.

Screenshot confirming secret regeneration.

다시 생성하려는 경우 이전 앱 비밀이 더 이상 작동하지 않으며 이 비밀로 채굴된 모든 이전 토큰도 작동을 중지합니다. 고객 가동 중지 시간을 최소화하려면 이 클라이언트 비밀 회전 시간을 잘 지정해야 합니다.

FAQ(질문과 대답)

Q: 휴대폰 앱에서 OAuth를 사용할 수 있나요?

A: 아니요. Azure DevOps Services는 웹 서버 흐름만 지원하므로 앱 비밀을 안전하게 저장할 수 없으므로 OAuth를 구현할 방법이 없습니다.

Q: 코드에서 처리해야 하는 오류 또는 특별한 조건은 무엇인가요?

A: 다음 조건을 처리해야 합니다.

  • 사용자가 앱 액세스를 거부하는 경우 권한 부여 코드가 반환되지 않습니다. 거부를 위해 검사 않고 권한 부여 코드를 사용하지 마세요.
  • 사용자가 앱의 권한 부여를 취소하면 액세스 토큰이 더 이상 유효하지 않습니다. 앱이 토큰을 사용하여 데이터에 액세스하면 401 오류가 반환됩니다. 권한 부여를 다시 요청합니다.

Q: 웹앱을 로컬로 디버그하려고 합니다. 앱을 등록할 때 콜백 URL에 localhost를 사용할 수 있나요?

A: 예. 이제 Azure DevOps Services는 콜백 URL에서 localhost를 허용합니다. 앱을 등록할 때 콜백 URL의 시작 부분으로 사용해야 https://localhost 합니다.

Q: 액세스 토큰을 가져오려고 할 때 HTTP 400 오류가 발생합니다. 무엇이 잘못되었을 수 있습니까?

A: 요청 헤더에서 콘텐츠 형식을 application/x-www-form-urlencoded로 설정해야 합니다.

Q: OAuth 기반 액세스 토큰을 사용할 때 HTTP 401 오류가 발생하지만 동일한 범위의 PAT가 정상적으로 작동합니다. 그 이유는

A: 조직의 관리자https://dev.azure.com/{your-org-name}/_settings/organizationPolicyOAuth를 통한 타사 애플리케이션 액세스를 사용하지 않도록 설정하지 않았는지 확인합니다. 이 시나리오에서는 앱에 권한을 부여하고 액세스 토큰을 생성하는 흐름이 작동하지만 모든 REST API는 다음과 같은 오류만 반환합니다. TF400813: The user "<GUID>" is not authorized to access this resource.

Q: SOAP 엔드포인트 및 REST API와 함께 OAuth를 사용할 수 있나요?

A: 아니요. OAuth는 현재 REST API에서만 지원됩니다.

Q: Azure DevOps REST API를 사용하여 작업 항목에 대한 첨부 파일 세부 정보를 얻으려면 어떻게 해야 하나요?

A: 먼저 작업 항목을 사용하여 작업 항목 세부 정보 가져오기 - 작업 항목 REST API 가져오기:

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

첨부 파일 세부 정보를 얻으려면 URL에 다음 매개 변수를 추가해야 합니다.

$expand=all

결과와 함께 관계 속성을 가져옵니다. 그곳에서 첨부 파일 URL을 찾을 수 있으며 URL 내에서 ID를 찾을 수 있습니다. 예시:

$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