Getting Error 401 when calling the REST API from a different server

Hi there, 

so i try to build a small application that shows the build status of all builds. 
I added this to the internal properties

rest.cors.optionsRequest.allowUnauthorized=true
rest.cors.origins=https://app.mydomain.live

and this is how i try to call the rest api with javascript: 
 
function fetchBuild(url) {
  var xhttp = new XMLHttpRequest();
  var auth = btoa(username + ":" + password);
  xhttp.open("GET", url, true);
  xhttp.setRequestHeader("Content-type", "application/json");
  xhttp.setRequestHeader("Authorization", "Basic " + auth);
  xhttp.setRequestHeader("Accept", "application/json");
 

  //var getUrl = window.location;
  // var baseUrl = getUrl.protocol + "//" + getUrl.host
  //xhttp.setRequestHeader('Access-Control-Allow-Origin', baseUrl);
  //xhttp.setRequestHeader('Access-Control-Allow-Credentials', 'true');
  // xhttp.withCredentials = true;
  xhttp.send();
  var ret = xhttp.responseText;
  var response = "";
  if (ret.length > 0) {
    response = JSON.parse(xhttp.responseText);
  }
  return response;
}
 
The thing is i always end up getting this error: 
 

Failed to load https://teamcity.bla.com/httpAuth/app/rest/latest/builds/buildType:MYBUILDID/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://app.mydomain.live' is therefore not allowed access. The response had HTTP status code 401.
 
With Postman from my local machine it works. But not from the Server in the Cloud where my Javascript Widget is hosted...  What am i doing wrong?
13 comments
Comment actions Permalink

Make sure you restart the TeamCity server after adding "rest.cors.optionsRequest.allowUnauthorized=true" internal property.
Also, it seems you should not be adding Access-Control-Allow-* headers in your script.

1
Comment actions Permalink

Hi Yegor,

i restarted already after adding the property. Also as you can see in the code of my script that the part you mentioned is commented out.

0
Comment actions Permalink

Try enabling "debug-rest" logging preset and checking the teamcity-rest.log for related entries. If it's not clear what is going on, attach the log here and provide a dump of the actual HTTP request sent and response received.

0
Comment actions Permalink

Alright i did what you requested and it seemed like i had to add my own domain name because that's what the log said:

[2018-01-15 12:51:04,623]  DEBUG [-nio-443-exec-1] - er.rest.APIController/rest-api - Got CORS request from origin 'https://teamcity.myteamcity.com', but this origin is not allowed. Add the origin to 'rest.cors.origins' internal property (comma-separated) to trust the applications hosted on the domain. Current allowed origins are: Enabled CORS Origins: [https://app.mydomain.live] 

But that sadly didn't help.

Actually when i make a request from my local machine i'm on right now with postman - and the same url i give the XmlHttpRequest (now changed to jquery/ajax but that didn't help either...) it works and i get a good json response from teamcity. But everytime i do it on a remote machine (it's a website calling a js file which gets executed - i edit the js file and that's where the code for getting the rest data is in.) i only get errors :/
Like these:

OPTIONS https://teamcity.myteamcity.com/httpAuth/app/rest/latest/builds/buildType:CompileTests/ 401 ()

Failed to load https://teamcity.myteamcity.com/httpAuth/app/rest/latest/builds/buildType:CompileTests/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://app.mydomain.live' is therefore not allowed access. The response had HTTP status code 401.

 

I added https://app.mydomain.live already to the origin....

 

Also i changed my code to this:

function fetchBuild(theurl) {

            var getUrl = window.location;
            var baseUrl = getUrl.protocol + "//" + getUrl.host
            var auth = btoa(username + ":" + password);
            var response = "";

            jQuery.support.cors = true;
            $.ajax({
                type: "GET",
                url: theurl,
                headers: {
                    Accept: "text/plain; charset=utf-8",
                    "Content-Type": "text/plain; charset=utf-8"
                },
                beforeSend: function(xhr) {
                    xhr.setRequestHeader("Authorization", "Basic " + auth);
                },
                success: function(data) {

                    //alert('success');
                    alert("succsessfull " + data);
                    if (ret.length > 0) {
                        response = JSON.parse(data);
                    }

                },
                error: function(msg, url, line) {
                    alert('error trapped in error: function(msg, url, line)');
                    alert('msg = ' + msg + ', url = ' + url + ', line = ' + line);

                }
            });


            return response;
        }

This is the only log entry my call is creating:

[2018-01-15 13:39:20,615]  DEBUG [nio-443-exec-14] - er.rest.APIController/rest-api - REST API request received: GET '/app/rest/latest/users/current?fields=id%2Cproperties%28property%29', from client 91.65.209.206:29807, authenticated as 'user' (Vorname Nachname) {id=2}, plugin 'rest-api' 
[2018-01-15 13:39:20,616]  DEBUG [nio-443-exec-14] - ver.server.rest.RequestWrapper - Establishing request mapping: '/app/rest/latest/users/current' -> '/app/rest/users/current' 
[2018-01-15 13:39:20,618]  DEBUG [nio-443-exec-14] - erver.rest.data.AbstractFinder - While processing locator 'current', 1 items were matched by the filter from 1 processed in total, took 0 ms 
[2018-01-15 13:39:20,621]  DEBUG [nio-443-exec-14] - er.rest.APIController/rest-api - REST API request processing finished in 6ms, status code: 200, plugin 'rest-api' 
[2018-01-15 13:39:20,922]  DEBUG [-nio-443-exec-6] - er.rest.APIController/rest-api - REST API request received: GET '/app/rest/federation/servers', from client 91.65.209.206:29807, authenticated as 'user' (Vorname Nachname) {id=2}, plugin 'rest-api' 
[2018-01-15 13:39:20,922]  DEBUG [-nio-443-exec-6] - ver.server.rest.RequestWrapper - Establishing request mapping: '/app/rest/federation/servers' -> '/app/rest/federation/servers' 
[2018-01-15 13:39:20,922]  DEBUG [-nio-443-exec-6] - er.rest.APIController/rest-api - REST API request processing finished in 1ms, status code: 200, plugin 'rest-api' 
0
Comment actions Permalink

Hello,

The first log entry you included with "Got CORS request from origin 'https://teamcity.myteamcity.com'" seems to indicate some misconfiguration of the proxy or TeamCity's Tomcat as the URL noted is the URL of the server as I understand it.

Try using direct TeamCity server port, not one of the (transparent) proxy and review the proxy configuration. (see also related notes).

The later log lines indicate successful requests, but they might also be created by TeamCity Web UI.

One more note is that REST API does not support "text/plain", so Accept header should include "application/xml" or "application/json".

1
Comment actions Permalink

Well i set up a auto redirect to https. I had port 777 used before but now when i enter teamcity.myteamcity.com:777 i get forwarded to https://teamcity.myteamcity.com.  Can i supply you with anything to further help you assisting fixing my problem?  I will change the text/plain to application/json accordingly - forgot to change that in the new method...

 

This are my connectors inside the TeamCity\conf\server.xml and i can reach the server properly with the browser  

<Connector port="777" protocol="org.apache.coyote.http11.Http11NioProtocol" redirectPort="443" />

<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" scheme="https" secure="true" connectionTimeout="60000" redirectPort="8543" clientAuth="false" sslProtocol="TLS" useBodyEncodingForURI="true" keystoreFile="C:\ProgramData\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org\mycert.pfx" keystorePass="" socket.txBufSize="64000" socket.rxBufSize="64000" tcpNoDelay="1" />

0
Comment actions Permalink

I really can't figure out why this doesn't work :/ Please help me Yegor!

0
Comment actions Permalink

I changed the text/plain with application/json but it won't help. Also we don't have a proxy. I just have this subdomain pointing to the server, a windows 2016 server and teamcity installed on it.  I just changed the server.xml for the connectors so https would work but i don't know if i introduced this bug or not...

0
Comment actions Permalink

I solved it. changed the port to 80, also removed httpauth from the url calling the rest api. 

0
Comment actions Permalink

hi,

 

I am trying to fetch the visible artifact size for all the builds in teamcity for a particular month.

Below is the code i have written.

It works for few build ids and then it starts throwing http error 401 basic auth failed.

I have tried everything possible by even hard coding the values etc but nothing seems to be working.

It works when i hard code the value but when it encounters the same value in script, it throws error.

 

We are using below code but its working till some point and then starts failing with the basic auth failed error. 
Sometimes it works till 15 hits and sometimes it works till 600 hits but then starts throwing authentication failure error for all the subsequent builds.

Below is the code and output-

import xml.etree.ElementTree as ET 
import urllib, urllib2, os, sys, subprocess, time 
import json,base64,re 
import csv 
from random import randint 
from time import sleep 
from random import randint 
from datetime import datetime, timedelta 
teamcity_url = "https://teamcity-icgtts.nam.nsroot.net:8443"

teamcity_password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()

teamcity_username = "*******"

teamcity_password = "*******"

teamcity_password_mgr.add_password(None, teamcity_url, teamcity_username, teamcity_password) 
teamcity_handler = urllib2.HTTPBasicAuthHandler(teamcity_password_mgr) 
teamcity_opener = urllib2.build_opener(teamcity_handler)

def teamcity_request(request_string, request_type): 
request = urllib2.Request(request_string, data='false') 
request.add_header('Content-Type', 'application/xml') 
request.get_method = lambda: request_type 
url = teamcity_opener.open(request) 
raw_xml = url.read() 
url.close() 
return raw_xml

def getParameters():

teamcity_response_builds = teamcity_request(teamcity_url+"/httpAuth/app/rest/builds/?locator=sinceDate:20190418T190000%2B0500%2cbranch:default:any%2cstatus:SUCCESS%2ccount:100000", 'GET')

teamcity_response_builds_xml = ET.fromstring(teamcity_response_builds) 
i=0 
for build_xml in teamcity_response_builds_xml.findall('build'): 
try: 
buildtypeid=build_xml.attrib['id'] 
print("buildtype id is"+ buildtypeid) 

teamcity_response_parameters = teamcity_request(teamcity_url+"/httpAuth/app/rest/builds/id:"+buildtypeid+"/statistics/VisibleArtifactsSize", 'GET') 
print teamcity_response_parameters

if (teamcity_response_parameters.isdigit()): 
i+=1

else: 
pass

except Exception as e: 
print(e) 
print("there was an error") 
pass 
return i

count=getParameters() 
print ( count)

output-

buildtype id is636302 
41779200 
buildtype id is636294 
58565337 
buildtype id is636300 
60405760 
buildtype id is636276 
HTTP Error 404: 
there was an error 
buildtype id is636296 
HTTP Error 404: 
there was an error 
buildtype id is636287 
HTTP Error 404: 
there was an error 
buildtype id is636288 
HTTP Error 404: 
there was an error 
buildtype id is636247 
HTTP Error 404: 
there was an error 
buildtype id is636293 
HTTP Error 404: 
there was an error 
buildtype id is636292------------------------------it starts throwing authentication error at this point though it has 
artifacts and it should print the value like it has printed for previous 
ids 
HTTP Error 401: basic auth failed 
there was an error 
buildtype id is636284 
HTTP Error 401: basic auth failed 
there was an error 
buildtype id is636260 
HTTP Error 401: basic auth failed 
there was an error 
buildtype id is636259 
HTTP Error 401: basic auth failed 
there was an error 
buildtype id is636256 
HTTP Error 401: basic auth failed 
there was an error

 

0
Comment actions Permalink

Hi Abhishek,

If I am not mistaken, when you contacted us in support (ticket #2142036) with this message, our response was that there seems to be issues with the authentication provider in use and it makes sense to check logs/teamcity-auth.log on the server to get the reason of the 401 errors. Nothing have changed since that, that answer still holds true and I encourage you to continue communications in that ticket.

0
Comment actions Permalink

Hi Guys,

I have a similar problem, enabled the cors in the internal properties but am seeing a 401 on the hub and I see the below in the rest log. Whats stranger though is that the rest log is using the client pc ip ( the one viewing the hub ) rather than the hub server? I would have thought the call would come from the Hub server instance?

[2019-07-19 10:02:00,608]   WARN [nio-8096-exec-6] - est.jersey.ExceptionMapperBase - Error has occurred during request processing, status code: 500 (Internal Server Error). Details: java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed. Error occurred while processing this request. Request: GET '/app/rest/latest/projects?locator=archived%3Afalse&fields=project%28id%2Cname%2CparentProjectId%2Carchived%29', from client 10.31.2.193:53302, no auth.
[2019-07-19 10:02:00,610]   WARN [nio-8096-exec-4] - est.jersey.ExceptionMapperBase - Error has occurred during request processing, status code: 500 (Internal Server Error). Details: java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed. Error occurred while processing this request. Request: GET '/app/rest/latest/buildTypes?fields=buildType%28id%2Cname%2CprojectId%29', from client 10.31.2.193:53303, no auth.
0
Comment actions Permalink

Hi Mario,

 

What's making the rest calls? Is it something on your PC or is hub somehow running them?

 

Besides, for the issues, 500 errors are logged into the server's main log, so I'd recommend checking there and sharing the stacktraces from there. It might make sense to create a separate issue to not send notifications to everyone involved in this thread.

0

Please sign in to leave a comment.