Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AJAX cross domain issue with Visual Studio Team Services REST API

I'm trying to write a JavaScript client for Visual Studio Team Services REST API which send AJAX requests to our self hosted Team Foundation Server 2015 but I'm facing to a cross domain issue.

The API requires credentials to authenticate but due to security reasons, the browser blocks my requests because the parameter Access-Control-Allow-Origin is set with the wildcard *.

I tried to add this parameter in HTTP Response Headers in IIS Manager and also in the TFS web.config file (which is actually the same) but I got an error telling me that this parameter has two different value (eg: * and http://localhost:58785) and should have only one. I guess this value is already defined in libraries's code which I can't access because the TFS web service is already compiled and running on IIS.

I also tried to use the markup <location allowOverride="false"> in web.config, to forbid configuration override but in that case TFS won't start.

Somebody already asked about this issue here and also posted a ticket on uservoice but as the name of the API is really ambiguous (Visual Studio Online REST API), I don't know if this guy talks about the real Visual Studio online or if his case is the same as mine (self hosted TFS Server).

We already implemented some features in C# which are working well but now we really need to implement a JavaScript client. Writing a web service and use it as a proxy to query the API is for us a real mess and we don't want to do this.

This is so sad we can't send AJAX requests to the API because of a configuration we aren't able to change.

like image 303
Jérôme MEVEL Avatar asked Jun 02 '15 15:06

Jérôme MEVEL


1 Answers

Somebody at Microsoft finally gave me the solution, so here it is:

In PowerShell, run these commands:

[Reflection.Assembly]::LoadFrom("C:\Program Files\Microsoft Team Foundation Server 14.0\Tools\Microsoft.TeamFoundation.Client.dll")

$configServer = new-object Microsoft.TeamFoundation.Client.TfsConfigurationServer "http://localhost:8080/tfs/"

$configHive = $configServer.GetService([Microsoft.TeamFoundation.Framework.Client.ITeamFoundationRegistry])

$configHive.SetValue("/Configuration/WebSecurity/AllowedOrigins", "domain1;domain2")

So you can specify several domains and you can also restrict to a given port and/or scheme like this:

$configHive.SetValue("/Configuration/WebSecurity/AllowedOrigins", "localhost,port=58785,scheme=http;")

Here is an old blog post about Updating the TF Registry using Powershell

Then you can finally send authenticated AJAX requests to the API.

[EDIT]: At this point, if you are running it in Windows it may be working, however it doesn't use Basic Authentication.

Two options:

1. It uses Generic Credentials automatically added in the Credential Manager (Sorry it's in French)

enter image description here

2. Or it could also use your Windows session credentials.

So to get it working in a non-Windows environment, you still need few more steps.

On your TFS server, run this PowerShell command to add Basic Authentication feature:

dism /online /enable-feature /featurename:IIS-BasicAuthentication

Then in IIS Manager click "Authentication" on your TFS site node. You should now see Basic Authentication, just enable it.

enter image description here

Finally in your JavaScript code convert the string

DOMAIN\username:password

to Base64 and add it to the request's header (assuming you use XMLHttpRequest):

client.setRequestHeader('Authorization', 'Basic ' + myBase64AuthString);

NOTE: Be careful with the pure JavaScript Base64 converter you may find on internet. The converted string could be wrong due to encoding. Compare your string with some online Base64 converters to be sure.

Hope this will help other people.

like image 75
Jérôme MEVEL Avatar answered Nov 05 '22 08:11

Jérôme MEVEL