3
votes

I have created my application in AzureAD with the permission "Azure DevOps".

Below is my code to fetch project list from Azure DevOps

 using (HttpClient client = new HttpClient())
            {

                HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, "https://login.microsoftonline.com/21d63aec-6502-4638-98f3-04587e69d53b/oauth2/v2.0/token");
                requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                Dictionary<String, String> form = new Dictionary<String, String>()
            {
                { "grant_type", "client_credentials" },
                { "client_id", "ac313ad2...." },
                { "scope", "https://app.vssps.visualstudio.com/.default" },
                { "client_secret", "BX0RldhqL...." }
            };
                requestMessage.Content = new FormUrlEncodedContent(form);

                HttpResponseMessage responseMessage = client.SendAsync(requestMessage).Result;

                if (responseMessage.IsSuccessStatusCode)
                {
                    String body = responseMessage.Content.ReadAsStringAsync().Result;

                    JsonConvert.PopulateObject(body, tokenModel);

                }
            }


using (ProjectHttpClient projectHttpClient = new ProjectHttpClient(new Uri("https://dev.azure.com/AlfabetChennaiDev"), new VssOAuthAccessTokenCredential(tokenModel.AccessToken)))
            {
                IEnumerable<TeamProjectReference> projects = projectHttpClient.GetProjects().Result;
            }

But I'm getting error as "You are not authorized to access https://dev.azure.com."

I am using oAuth 2.0 Client Credential flow to get access token. What could be the reason

1
When I googled, I stumbled across these posts on Microsoft Developers Community, maybe that can help you. They have some suggestions. developercommunity.visualstudio.com/content/problem/370982/… developercommunity.visualstudio.com/content/problem/222842/…fluidguid
For you now deleted question, stackoverflow.com/questions/6428940/…. consider edit and undeletion at some point.xdtTransform

1 Answers

4
votes

Typically you'd use the REST API using oAuth when you want your application to communicate with Azure DevOps API on behalf of the calling user without having to prompt for usernames and passwords each time. To do this, the user will need to authorize the application to communicate to the Azure DevOps API on their behalf.

The following page provides a good overview of this process.

User Authorizes your Application

At a high-level, you call the "authorize" endpoint and provide a callback. The callback must be a secure url (https) in your application:

https://app.vssps.visualstudio.com/oauth2/authorize
    ?client_id={app ID}
    &response_type=Assertion
    &state={state}
    &scope={scope}
    &redirect_uri={callback URL}

Assuming the user accepts the authorization, Azure DevOps redirects to your callback location with the authorization code in the URL.

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

Obtain an Access Token

Now that your application is authorized, you need to obtain an access token:

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

The application/x-www-form-urlencoded form has the following body with the application secret when you created the application, the authorization code you just received when the user authorized your app, and the secure callback.

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
    );
}

The response will contain the access token in the JSON response.

{
   "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 }
}

Note that the token isn't permanent and may need to be refreshed.

Use the Authorization Header

Lastly, now that you have a user-access token, you can include it in the Authorization header in your requests to the server.

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

For example:

httpClient.DefaultRequestHeaders.Authorization =
   new AuthenticationHeaderValue("Bearer", "{access_token}");

If you're not using a dedicated application and you just want to query the API with credentials you control -- use a Personal Access Token, as it's a lot easier:

httpClient.DefaultRequestHeaders.Authorization =
   new AuthenticationHeaderValue("Basic {base-64-encoded-string of username:PAT}");