Skip to content

Commit 3f34434

Browse files
committed
adding VstsTfsSample
1 parent 1ec2ce8 commit 3f34434

File tree

9 files changed

+436
-5
lines changed

9 files changed

+436
-5
lines changed

JavascriptWebAppSample/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ To run this sample you will need:
1010
* Http-server. You can download [NPM http server](https://www.npmjs.com/package/http-server) if you need one.
1111
* An Azure Active Directory (AAD) tenant. If you do not have one, follow these [steps to set up an AAD](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-howto-tenant)
1212
* A user account in your AAD tenant
13-
* A VSTS account backed by your AAD tenant where your user account has access. If you have an existing VSTS account not connected to your AAD tenant follow these [steps to connect you AAD tenant to your VSTS account](https://www.visualstudio.com/en-us/docs/setup-admin/team-services/manage-organization-access-for-your-account-vs)
13+
* A VSTS account backed by your AAD tenant where your user account has access. If you have an existing VSTS account not connected to your AAD tenant follow these [steps to connect your AAD tenant to your VSTS account](https://www.visualstudio.com/en-us/docs/setup-admin/team-services/manage-organization-access-for-your-account-vs)
1414

1515
## Step 1: Clone or download vsts-auth-samples repository
1616

ManagedClientConsoleAppSample/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ To run this sample you will need:
1212
* [Visual Studio IDE](https://www.visualstudio.com/vs/)
1313
* An Azure Active Directory (AAD) tenant. If you do not have one, follow these [steps to set up an AAD](https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-howto-tenant)
1414
* A user account in your AAD tenant
15-
* A VSTS account backed by your AAD tenant where your user account has access. If you have an existing VSTS account not connected to your AAD tenant follow these [steps to connect you AAD tenant to your VSTS account](https://www.visualstudio.com/en-us/docs/setup-admin/team-services/manage-organization-access-for-your-account-vs)
15+
* A VSTS account backed by your AAD tenant where your user account has access. If you have an existing VSTS account not connected to your AAD tenant follow these [steps to connect your AAD tenant to your VSTS account](https://www.visualstudio.com/en-us/docs/setup-admin/team-services/manage-organization-access-for-your-account-vs)
1616

1717
## Step 1: Clone or download vsts-auth-samples repository
1818

@@ -26,8 +26,8 @@ git clone https://github.com/Microsoft/vsts-auth-samples.git
2626
1. Sign in to the [Azure Portal](https://portal.azure.com).
2727
2. On the top bar, click on your account and under the Directory list, choose the Active Directory tenant where you wish to register your application.
2828
3. On the left hand navigation menu, select `Azure Active Directory`.
29-
4. Click on `App registrations` and select `New application regirstation` from the top bar.
30-
5. Enter a `name` for you application, ex. "Adal native app sample", choose `Native` for `application type`, and enter `http://adaljssample` for the `Redirect URI`. Finally click `create` at the bottom of the screen.
29+
4. Click on `App registrations` and select `New application registration` from the top bar.
30+
5. Enter a `name` for you application, ex. "Adal native app sample", choose `Native` for `application type`, and enter `http://adalsample` for the `Redirect URI`. Finally click `create` at the bottom of the screen.
3131
6. Save the `Application ID` from your new application registration. You will need it later in this sample.
3232
7. Grant Permissions for VSTS. Click `Required permissions` -> `add` -> `1 Select an API` -> type in and select `Microsoft Visual Studio Team Services` -> check the box for `Have full access to...` -> click `Save` -> click `Grant Permissions` -> click `Yes`.
3333

@@ -43,6 +43,6 @@ Package: `Microsoft.Identity.Model.Clients.ActiveDirectory` has already been ins
4343
4. Open CS file `Program.cs` and there is a section with input values to change at the top of the class:
4444
* `vstsCollectionUrl` - update this with the url to your VSTS/TFS collection, e.g. http://myaccount.visualstudio.com for VSTS or http://myserver:8080/tfs/DefaultCollection for TFS.
4545
* `clientId` - update this with the `application id` you saved from `portal.azure.com`
46-
* `replyUri` - we have set this to `http://adaljssample`, but please update it as necessary for your own app.
46+
* `replyUri` - we have set this to `http://adalsample`, but please update it as necessary for your own app.
4747
5. Build and run solution. After running you should see an interactive login prompt. Then after authentication and authorization, a list of all projects inside of your account.
4848

VstsTfsSample/App.config

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
5+
</startup>
6+
<system.serviceModel>
7+
<extensions>
8+
<!-- In this extension section we are introducing all known service bus extensions. User can remove the ones they don't need. -->
9+
<behaviorExtensions>
10+
<add name="connectionStatusBehavior" type="Microsoft.ServiceBus.Configuration.ConnectionStatusElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
11+
<add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
12+
<add name="serviceRegistrySettings" type="Microsoft.ServiceBus.Configuration.ServiceRegistrySettingsElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
13+
</behaviorExtensions>
14+
<bindingElementExtensions>
15+
<add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
16+
<add name="tcpRelayTransport" type="Microsoft.ServiceBus.Configuration.TcpRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
17+
<add name="httpRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
18+
<add name="httpsRelayTransport" type="Microsoft.ServiceBus.Configuration.HttpsRelayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
19+
<add name="onewayRelayTransport" type="Microsoft.ServiceBus.Configuration.RelayedOnewayTransportElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
20+
</bindingElementExtensions>
21+
<bindingExtensions>
22+
<add name="basicHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.BasicHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
23+
<add name="webHttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WebHttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
24+
<add name="ws2007HttpRelayBinding" type="Microsoft.ServiceBus.Configuration.WS2007HttpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
25+
<add name="netTcpRelayBinding" type="Microsoft.ServiceBus.Configuration.NetTcpRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
26+
<add name="netOnewayRelayBinding" type="Microsoft.ServiceBus.Configuration.NetOnewayRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
27+
<add name="netEventRelayBinding" type="Microsoft.ServiceBus.Configuration.NetEventRelayBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
28+
<add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
29+
</bindingExtensions>
30+
</extensions>
31+
</system.serviceModel>
32+
<appSettings>
33+
<!-- Service Bus specific app setings for messaging connections -->
34+
<add key="Microsoft.ServiceBus.ConnectionString" value="Endpoint=sb://[your namespace].servicebus.windows.net;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=[your secret]" />
35+
</appSettings>
36+
<runtime>
37+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
38+
<dependentAssembly>
39+
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
40+
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
41+
</dependentAssembly>
42+
<dependentAssembly>
43+
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
44+
<bindingRedirect oldVersion="0.0.0.0-3.13.8.999" newVersion="3.13.8.999" />
45+
</dependentAssembly>
46+
<dependentAssembly>
47+
<assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory.Platform" publicKeyToken="31bf3856ad364e35" culture="neutral" />
48+
<bindingRedirect oldVersion="0.0.0.0-3.13.8.999" newVersion="3.13.8.999" />
49+
</dependentAssembly>
50+
</assemblyBinding>
51+
</runtime>
52+
</configuration>

VstsTfsSample/Program.cs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
using Microsoft.IdentityModel.Clients.ActiveDirectory;
2+
using System;
3+
using System.Linq;
4+
using System.Net.Http;
5+
using System.Net.Http.Headers;
6+
using System.Text.RegularExpressions;
7+
using Microsoft.VisualStudio.Services.Client;
8+
using Microsoft.VisualStudio.Services.WebApi;
9+
using Microsoft.TeamFoundation.Core.WebApi;
10+
using System.Collections.Generic;
11+
12+
namespace VstsTfsSample
13+
{
14+
class Program
15+
{
16+
//============= Config [Edit these with your settings] =====================
17+
internal const string vstsOrTfsCollectionUrl = "https://myaccount.visualstudio.com"; //change to the URL of your VSTS or TFS account
18+
internal const string clientId = "0fa17cf4-f75c-4185-ab9a-7c5ea47ca073"; //change to your app registration's Application ID (For VSTS ADAL authentication)
19+
internal const string replyUri = "http://adalsample"; //change to your app registration's reply URI. (For VSTS ADAL authentication)
20+
//==========================================================================
21+
22+
internal const string VSTSResourceId = "499b84ac-1321-427f-aa17-267ca6975798"; //Constant value to target VSTS. Do not change
23+
24+
public static void Main(string[] args)
25+
{
26+
//Decipher VSTS or TFS collection
27+
if (isVsts(vstsOrTfsCollectionUrl))
28+
{
29+
//VSTS ADAL authentication
30+
AuthenticationContext ctx = GetAuthenticationContext(null);
31+
AuthenticationResult result = null;
32+
try
33+
{
34+
//PromptBehavior.RefreshSession will enforce an authn prompt every time. NOTE: Auto will take your windows login state if possible
35+
result = ctx.AcquireTokenAsync(VSTSResourceId, clientId, new Uri(replyUri), new PlatformParameters(PromptBehavior.Always)).Result;
36+
Console.WriteLine("Token expires on: " + result.ExpiresOn);
37+
38+
var bearerAuthHeader = new AuthenticationHeaderValue("Bearer", result.AccessToken);
39+
//using access token to call REST endpoint
40+
ListProjects(bearerAuthHeader);
41+
}
42+
catch (UnauthorizedAccessException)
43+
{
44+
// If the token has expired, prompt the user with a login prompt
45+
result = ctx.AcquireTokenAsync(VSTSResourceId, clientId, new Uri(replyUri), new PlatformParameters(PromptBehavior.Always)).Result;
46+
}
47+
catch (Exception ex)
48+
{
49+
Console.WriteLine("{0}: {1}", ex.GetType(), ex.Message);
50+
}
51+
} else
52+
{
53+
//TFS Windows credential authentication
54+
VssConnection connection = new VssConnection(new Uri(vstsOrTfsCollectionUrl), new VssClientCredentials());
55+
56+
ProjectHttpClient projectClient = connection.GetClient<ProjectHttpClient>();
57+
IEnumerable<TeamProjectReference> projects = projectClient.GetProjects().Result;
58+
foreach (TeamProjectReference p in projects)
59+
{
60+
Console.WriteLine(p.Name);
61+
}
62+
}
63+
}
64+
65+
private static bool isVsts(string collectionUrl)
66+
{
67+
string regexPattern = @"\w+(.visualstudio.com)";
68+
Match m = Regex.Match(collectionUrl, regexPattern);
69+
return m.Success;
70+
}
71+
72+
private static AuthenticationContext GetAuthenticationContext(string tenant)
73+
{
74+
AuthenticationContext ctx = null;
75+
if (tenant != null)
76+
ctx = new AuthenticationContext("https://login.microsoftonline.com/" + tenant);
77+
else
78+
{
79+
ctx = new AuthenticationContext("https://login.windows.net/common");
80+
if (ctx.TokenCache.Count > 0)
81+
{
82+
string homeTenant = ctx.TokenCache.ReadItems().First().TenantId;
83+
ctx = new AuthenticationContext("https://login.microsoftonline.com/" + homeTenant);
84+
}
85+
}
86+
87+
return ctx;
88+
}
89+
90+
private static void ListProjects(AuthenticationHeaderValue authHeader)
91+
{
92+
// use the httpclient
93+
using (var client = new HttpClient())
94+
{
95+
client.BaseAddress = new Uri(vstsOrTfsCollectionUrl);
96+
client.DefaultRequestHeaders.Accept.Clear();
97+
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
98+
client.DefaultRequestHeaders.Add("User-Agent", "ManagedClientConsoleAppSample");
99+
client.DefaultRequestHeaders.Add("X-TFS-FedAuthRedirect", "Suppress");
100+
client.DefaultRequestHeaders.Authorization = authHeader;
101+
102+
// connect to the REST endpoint
103+
HttpResponseMessage response = client.GetAsync("_apis/projects?stateFilter=All&api-version=2.2").Result;
104+
105+
// check to see if we have a succesfull respond
106+
if (response.IsSuccessStatusCode)
107+
{
108+
Console.WriteLine("\tSuccesful REST call");
109+
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
110+
}
111+
else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
112+
{
113+
throw new UnauthorizedAccessException();
114+
}
115+
else
116+
{
117+
Console.WriteLine("{0}:{1}", response.StatusCode, response.ReasonPhrase);
118+
}
119+
}
120+
}
121+
}
122+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using System.Reflection;
2+
using System.Runtime.CompilerServices;
3+
using System.Runtime.InteropServices;
4+
5+
// General Information about an assembly is controlled through the following
6+
// set of attributes. Change these attribute values to modify the information
7+
// associated with an assembly.
8+
[assembly: AssemblyTitle("SimpleAdalConsoleApp")]
9+
[assembly: AssemblyDescription("")]
10+
[assembly: AssemblyConfiguration("")]
11+
[assembly: AssemblyCompany("")]
12+
[assembly: AssemblyProduct("SimpleAdalConsoleApp")]
13+
[assembly: AssemblyCopyright("Copyright © 2017")]
14+
[assembly: AssemblyTrademark("")]
15+
[assembly: AssemblyCulture("")]
16+
17+
// Setting ComVisible to false makes the types in this assembly not visible
18+
// to COM components. If you need to access a type in this assembly from
19+
// COM, set the ComVisible attribute to true on that type.
20+
[assembly: ComVisible(false)]
21+
22+
// The following GUID is for the ID of the typelib if this project is exposed to COM
23+
[assembly: Guid("755bc9ef-a095-48dc-bbf6-af39f8c3363e")]
24+
25+
// Version information for an assembly consists of the following four values:
26+
//
27+
// Major Version
28+
// Minor Version
29+
// Build Number
30+
// Revision
31+
//
32+
// You can specify all the values or you can default the Build and Revision Numbers
33+
// by using the '*' as shown below:
34+
// [assembly: AssemblyVersion("1.0.*")]
35+
[assembly: AssemblyVersion("1.0.0.0")]
36+
[assembly: AssemblyFileVersion("1.0.0.0")]

0 commit comments

Comments
 (0)