JIRA REST API with JQuery XSRF check failed

Solomon Razvan January 31, 2018

I need to make an api able to create jira issues on a locally installed server from a third party cloud installed software. So no server to server communication is possible and the only solution is to use the js libraries to make rest calls to the local serve. For a basic example I'm using jquery.

$.ajax({
    url: 'http://localhost:8080/rest/api/latest/issue/',
    type: "POST",
    dataType: 'json',
    cache: false,
    crossDomain: true,
    timeout: 5000,
    data: JSON.stringify(fields: {
        project: {
           key: 'TES'
        },
        summary: "REST EXAMPLE",
        description: "Creating an issue via REST API",
        issuetype: {
           name: "Bug"
        }
    }),
    xhrFields: {
        withCredentials: true
    },
    headers: {
        'Authorization': 'Basic '+window.btoa(user+':'+password),
        'Content-Type': 'application/json',
        'X-Atlassian-Token': 'nocheck'
    },
    complete: function(response) {
        console.log(response.responseText);
    }
});

Everything is ok if I execute the script for IE 11 and Firefox (although for Firefox I add an extra 'User-Agent': 'test' header).

But I can't seem to figure out why it won't work for Chrome. The preflight request returns a 200 status but when the actual request is sent, I receive a 403 status with an error: XSRF check failed.

JIRA is installed with all its default packages and I work on a Tomcat 8 server. I configured it to accept the CORS filter, so I don't think it's a server problem, because for IE and Firefox works but not for Chrome.

1 answer

0 votes
Andy Heinzer
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
February 13, 2018

Do you see any errors in the $JIRAHOME/log/atlassian-jira.log file when this happens?  I suspect that log file might provide some more details about why this isn't working. 

Just from a speculation, I would recommend checking out this related post:

https://community.atlassian.com/t5/Answers-Developer-Questions/Jira-7-rest-api-XSRF-check-failed-for-post-issue-with/qaq-p/488706

In that case, the use of an incorrect user-agent string could also cause this kind of cross site scripting problem.  I am surprised that the firefox works with the 'test' value in that field.   Perhaps you can define the user-agent string to match the actual browser type/version to avoid this error.

I also believe that these other KBs might be important information in relation to this problem:

https://confluence.atlassian.com/jirakb/rest-api-calls-with-a-browser-user-agent-header-may-fail-csrf-checks-802591455.html

and

https://confluence.atlassian.com/kb/cross-site-request-forgery-csrf-protection-changes-in-atlassian-rest-779294918.html

Solomon Razvan February 14, 2018

I tried all the methods above several times. My jira access log looks like this when I make a request from Chrome:

82.79.69.201 - - [14/Feb/2018:10:12:21 +0100] "OPTIONS /rest/api/latest/issue/ HTTP/1.1" 200 - 1 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36" "-"
82.79.69.201 612x375x1 Razvan Solomon [14/Feb/2018:10:12:21 +0100] "POST /rest/api/latest/issue/ HTTP/1.1" 403 59 48 "https:// This is a real domain" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
 like Gecko) Chrome/64.0.3282.140 Safari/537.36" "1pq5zex"

For Firefox looks like this:

82.79.69.201 - - [14/Feb/2018:10:27:53 +0100] "OPTIONS /rest/api/latest/issue/ HTTP/1.1" 200 - 1 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0" "-"
82.79.69.201 627x377x1 Razvan Solomon [14/Feb/2018:10:27:54 +0100] "POST /rest/api/latest/issue/ HTTP/1.1" 201 126 227 "https:// This is a real domain" "Test" "150um3q"

 

In the atlassian-jira.log I find this every time I make a request from Chrome:

2018-02-14 10:12:21,826 https-jsse-nio-8443-exec-12 WARN Razvan Solomon 612x375x1 1pq5zex 82.79.69.201 /rest/api/latest/issue/ [c.a.p.r.c.security.jersey.XsrfResourceFilter] Additional XSRF checks failed for request: https://my jira server:8443/rest/api/latest/issue/ , origin: https:// This is a real domain , referrer: https:// This is a real domain/jira , credentials in request: true , allowed via CORS: false

Whenever I make the same request from Firefox, there is no warning like this.

Andy Heinzer
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
February 15, 2018

Well I can see in your first post it looks like you're trying to post to Jira using http, the localhost, and port 8080.  However in your last post it looks like you're using https, some obscured domain name, and port 8443.  

I think that the guide in Cross Site Request Forgery (CSRF) protection changes in Atlassian REST has the steps needed to correct this.   If the origin and referer headers don't match up, we can expect this error to happen.   These need to line up on protocol, address, and port number in order to prevent this from happening.  But also we need to make sure that the Jira application itself is setup to correct accept and understand where traffic it receives is being directed to.

Hence I am interested to learn more about what settings you have in the $JIRAINSTALL/conf/server.xml file that defines Jira's Tomcat instance settings.  Specifically, I would like to know what your <Connector> tag(s) look like.  I would expect that at least one of these will need to have the proxyPort, proxyName, and scheme defined for it.   Furthermore, when you set this up within Jira, the traffic that reaches that port is expected to line up with the proxyName value defined there.  So, if this connector is using 8080 and has the proxyName defined for it as something like jira.example.com in those cases, you won't want to try to reach it the site from localhost:8080.  The traffic for that port is expected to actually be directed at the jira.example.com  domain. 

With the connector information and the specific protocol, address, port, that you are trying to use to send these requests to Jira, we should be able to better understand what configuration could help make this work regardless of browser used.

Solomon Razvan February 16, 2018

Hi Andrew,

Sorry for the confusion. Initially my question was asked when I was still testing on a local environment. Right now, the setup has changed (we went live with it), but the Chrome problem still persists. So, I have an application run on https that tries to make an ajax call to a JIRA installation on a different domain that is also on https. Neither of them are proxies. They are both installed on different servers.

 

<Connector port="8080"
                   maxThreads="150"
                   minSpareThreads="25"
                   connectionTimeout="20000"

                   enableLookups="false"
                   maxHttpHeaderSize="8192"
                   protocol="HTTP/1.1"
                   useBodyEncodingForURI="true"
                   redirectPort="8443"
                   acceptCount="100"
                   disableUploadTimeout="true"
                   bindOnInit="false"/>

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
              maxHttpHeaderSize="8192" SSLEnabled="true"
              maxThreads="150" minSpareThreads="25"
              enableLookups="false" disableUploadTimeout="true"
              acceptCount="100" scheme="https" secure="true"
              clientAuth="false" sslProtocol="TLS" useBodyEncodingForURI="true"
              keystoreFile="/opt/atlassian/jira/jira.jks" keystorePass="changeit" keyAlias="jira" keystoreType="JKS"/>

Andy Heinzer
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
February 16, 2018

Ok, I think that helps a bit more.   Even if you are not using a reverse proxy, there are still instance where you might need to use the proxyName and proxyPort parameters in the connector that is serving up this content.

For example, Jira is running on ports 8080 (http) and 8443 (https).   However if your other site is trying to reach the Jira instance over an example address like https://examplejira.example.com , that default URL is natively using port 443 for https unless otherwise defined.  This means that you are either using some kind or port forwarding, a reverse proxy, or iptable rules that are shaping this traffic to Jira's 8443 port somehow.   In cases like this we still need to define proxyPort and proxyName.  In this case I think your 8443 connector is going to need parameters added to it to make it look like this:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
              maxHttpHeaderSize="8192" SSLEnabled="true"
              maxThreads="150" minSpareThreads="25"
              enableLookups="false" disableUploadTimeout="true"
              acceptCount="100" scheme="https" secure="true"
              clientAuth="false" sslProtocol="TLS" useBodyEncodingForURI="true"
              keystoreFile="/opt/atlassian/jira/jira.jks" keystorePass="changeit" keyAlias="jira" keystoreType="JKS"
proxyName="examplejira.example.com" proxyPort="443"/>

Where examplejira.example.com is the URL that your other site is using to reach this Jira instance.   After you make a change like this to the server.xml file, you will need to save that file, and then restart Jira before this change takes effect.

However I think this is going to be necessary unless your other (non-Jira) site is able to connect to the specific hostname/IP and port number that Jira is hosting its site on.  If that is how you are using this, please let me know.  However I think we're on the right track here since these changes are known to correct this kind of XSRF problems.

Like Tomas Fanty likes this
Solomon Razvan February 19, 2018

I don't understand why I would need to defined as a proxyName my application that calls the jira application server, but I did it. So I replaced the examplejira.example.com from above with my address (let's call it https://realdomain.com) from where I'm trying to make a js request to my JIRA server (let's call it htts://jiraserver.com) in the connector and it looked like this:

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
              maxHttpHeaderSize="8192" SSLEnabled="true"
              maxThreads="150" minSpareThreads="25"
              enableLookups="false" disableUploadTimeout="true"
              acceptCount="100" scheme="https" secure="true"
              clientAuth="false" sslProtocol="TLS" useBodyEncodingForURI="true"
              keystoreFile="/opt/atlassian/jira/jira.jks" keystorePass="changeit" keyAlias="jira" keystoreType="JKS"
proxyName="realdomain.com" proxyPort="443"/>

 

This is why I got after restart in the atlassian-jira.log:

2018-02-19 10:21:25,710 https-jsse-nio-8443-exec-9 WARN Jira Admin 621x35x1 10yvfs4 82.79.69.201 /rest/analytics/1.0/publish/bulk [c.a.p.r.c.security.jersey.XsrfResourceFilter] Additional XSRF checks failed for request: https://realdomain.com/rest/analytics/1.0/publish/bulk , origin: null , referrer: https://jiraserver.com:8443/secure/Dashboard.jspa , credentials in request: true , allowed via CORS: false
2018-02-19 10:21:41,936 Caesium-1-2 INFO ServiceRunner     [c.a.jira.upgrade.UpgradeScheduler] Running scheduled upgrades
2018-02-19 10:21:41,952 Caesium-1-2 INFO ServiceRunner     [c.a.jira.upgrade.LoggingUpgradeService] run upgrades has started
2018-02-19 10:21:42,698 Caesium-1-2 INFO ServiceRunner     [c.a.j.upgrade.util.BuildNumberDao] Setting current build number to 77002
2018-02-19 10:21:42,786 Caesium-1-2 INFO ServiceRunner     [c.a.jira.upgrade.UpgradeIndexManager] There is no reindex requests of type [IMMEDIATE, DELAYED] so none will be run
2018-02-19 10:21:42,787 Caesium-1-2 INFO ServiceRunner     [c.a.j.upgrade.util.BuildNumberDao] Setting current version to 7.7.1
2018-02-19 10:21:42,815 Caesium-1-2 INFO ServiceRunner     [c.a.j.upgrade.util.BuildNumberDao] Setting downgrade version to 7.1.2
2018-02-19 10:21:42,870 Caesium-1-2 INFO ServiceRunner     [c.a.jira.upgrade.LoggingUpgradeService] run upgrades has finished successfully, and took 905 milliseconds to process.
2018-02-19 10:21:42,870 Caesium-1-2 INFO ServiceRunner     [c.a.jira.upgrade.UpgradeScheduler] JIRA upgrades completed successfully
2018-02-19 10:21:42,920 Caesium-1-2 INFO ServiceRunner     [c.a.jira.upgrade.UpgradeScheduler] Plugins upgrades completed successfully
2018-02-19 10:21:42,921 Caesium-1-2 INFO ServiceRunner     [c.a.jira.upgrade.UpgradeIndexManager] Reindexing is not allowed after this upgrade and there is no immediate reindex requests
2018-02-19 10:21:42,967 HealthCheck:thread-2 ERROR      [c.a.t.j.healthcheck.support.GadgetFeedUrlHealthCheck] An error occurred when performing the Gadget feed URL healthcheck
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
        at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
        at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
        at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
        at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
        at com.atlassian.troubleshooting.jira.healthcheck.support.GadgetFeedUrlHealthCheck.check(GadgetFeedUrlHealthCheck.java:56)
        at com.atlassian.troubleshooting.healthcheck.impl.PluginSuppliedSupportHealthCheck.check(PluginSuppliedSupportHealthCheck.java:49)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
        ... 26 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)

 

Also on the JIRA dashboard I got this message along with other errors:

 

Dashboard Diagnostics: Mismatched URL Hostname

JIRA is reporting that it is running on the hostname 'realdomain.com', which does not match the hostname used to run these diagnostics, 'jiraserver.com'. This is known to cause JIRA to construct URLs using the incorrect hostname, which will result in errors in the dashboard, among other issues.

The most common cause of this is the use of a reverse-proxy HTTP server (often Apache or IIS) in front of the application server running JIRA. While this configuration is supported, some additional setup might be necessary in order to ensure that JIRA detects the correct hostname.

The following articles describe the issue and the steps you should take to ensure that your web server and app server are configured correctly:

    Gadgets do not display correctly after upgrade to JIRA 4.0
    Integrating JIRA with Apache
    Integrating JIRA with Apache using SSL

If you believe this diagnosis is in error, or you have any other questions, please contact Atlassian Support.
Detailed Error


com.atlassian.gadgets.dashboard.internal.diagnostics.UrlHostnameMismatchExcep
Andy Heinzer
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
February 20, 2018

Hi Solomon,

That error is a pretty clear indication that Jira cannot connect to the site on that address.  When we see this 'pkix path building failed' error, it tells us that Jira can't properly establish a connection to that SSL address.

Please follow the diagnosis steps in the KB Unable to Connect to SSL Services due to PKIX Path Building Failed.   Try those steps, using the SSLPoke utility, on both the Jira server and from the server that is trying to establish this connection to Jira.   Depending on the results to get from each location will determine how to resolve this.

I suspect this problem could be in regards to the certificate Jira has in it's truststore, but without seeing the results of the sslpoke it is difficult to know for sure.

Solomon Razvan February 21, 2018

Hi Andrew,

I did the steps that you asked me, but let's reiterate a bit my problem, because I think we're not understanding each other correctly.

I want to use the JIRA REST API to create an issue with js by using only the client side browser. So if I run my script from above on IE 11, Firefox, Edge, everything is ok. My problem only appears when the user is using Chrome. For Chrome it passes the preflight request of the CORS, but fails at the second request that adds the actual content. My two applications the one that I want to use to create a JIRA defect (https://realdomain.com), and the JIRA server (https://jiraserver.com) both work on HTTPS. For the sake of testing I also disabled the certificates on both servers and tried it without SSL. Same result: IE 11, Firefox, Edge work and Chrome does not.

I also did something with even weirder outcomes. I added my application URL to the JIRA Whitelist (although it is already present in the Apache CORS filter) and got this result. The rest API worked for all browsers (the JIRA issue is created), but I can't get the response message correctly because they all throw a similar message in the console log:

The 'Access-Control-Allow-Origin' header contains multiple values 'https://realdomain.com, https://realdomain.com', but only one is allowed. Origin 'https://realdomain.com' is therefore not allowed access.

My feeling is that this is a pure browser behavior issue.

So I ran the SSLPoke. From the application server (which btw didn't even had JAVA installed because it was not necessary for my application) to the JIRA server I ran this:

java SSLPoke jiraserver.com 8443

with this response:

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)
        at SSLPoke.main(SSLPoke.java:31)
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)

 

From the JIRA server to the application server I ran this:

java SSLPoke realdomain.com 443

with this response:

Successfully connected

 

Maheswari December 14, 2018

Hi

Did you find the solution

I am facing the same issue 

pls help

Suggest an answer

Log in or Sign up to answer