Skip to content

Instantly share code, notes, and snippets.

@bfcamara
Last active August 29, 2015 14:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bfcamara/6aab0858ebda2db435a9 to your computer and use it in GitHub Desktop.
Save bfcamara/6aab0858ebda2db435a9 to your computer and use it in GitHub Desktop.
Consuming VS Online REST API using a Service Account
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Http;
using System.Diagnostics;
using System.Net.Http.Headers;
using Newtonsoft;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Utilities;
using Newtonsoft.Json.Linq;
namespace VsoRestAPiWithServiceAccount
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main start");
Task t = AsyncMain();
t.ContinueWith((str) =>
{
Console.WriteLine(str.Status.ToString());
Console.WriteLine("Main end");
});
t.Wait();
}
public static async Task AsyncMain()
{
string accountName = "your account goes here";
string urlAccount = string.Format("https://{0}.visualstudio.com", accountName);
string serviceAccountUsername = "your service account username goes here";
string servviceAccountPassword = "your service account password goes here";
//1 - Hit VSOnline unauthenticated
var client = HttpClientFactory.Create(new HttpClientHandler() { AllowAutoRedirect = false });
var resp = await client.GetAsync(urlAccount, HttpCompletionOption.ResponseHeadersRead);
Console.WriteLine("Status Code = " + resp.StatusCode);
Debug.Assert(resp.StatusCode == HttpStatusCode.Redirect);
if (!resp.Headers.Contains("x-tfs-fedauthrealm") ||
!resp.Headers.Contains("x-tfs-fedauthissuer"))
{
Console.WriteLine("Cannot determine federation data");
return;
}
string realm = resp.Headers.GetValues("x-tfs-fedauthrealm").First();
string issuer = resp.Headers.GetValues("x-tfs-fedauthissuer").First();
Console.WriteLine("Federation Data:Realm={0}; Issuer={1}", realm, issuer);
//2 - Get an access token from ACS using WRAP protocol
string acsHost = new Uri(issuer).Host;
string acsRequestTokenUrl = string.Format("https://{0}/WRAPv0.9", acsHost);
resp = await client.PostAsync(acsRequestTokenUrl, new FormUrlEncodedContent(
new KeyValuePair<string, string>[] {
new KeyValuePair<string, string>("wrap_scope", realm),
new KeyValuePair<string, string>("wrap_name", serviceAccountUsername),
new KeyValuePair<string, string>("wrap_password", servviceAccountPassword)
}
));
resp.EnsureSuccessStatusCode();
var acsTokenData = await resp.Content.ReadAsFormDataAsync();
var accessToken = acsTokenData["wrap_access_token"];
var accessTokenExpiredInSecs = int.Parse(acsTokenData["wrap_access_token_expires_in"]);
Console.WriteLine("Your access token expires in {0}: {1}",
accessTokenExpiredInSecs,
accessToken);
//3 - Let's use the access token to consumer the REST api
var request = new HttpRequestMessage(
HttpMethod.Get,
urlAccount + "/DefaultCollection/_apis/projects?api-version=1.0-preview.1");
request.Headers.Authorization = new AuthenticationHeaderValue(
"WRAP",
string.Format("access_token=\"{0}\"", accessToken));
resp = await client.SendAsync(request);
resp.EnsureSuccessStatusCode();
JObject jsonResult = await resp.Content.ReadAsAsync<JObject>();
var projects = jsonResult.SelectTokens("$.value[*].name");
Console.WriteLine("Here is the list of your pojects");
foreach (var p in projects)
{
Console.WriteLine(p);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment