Send X-XSRF-TOKEN header with all requests
In ALM 16.00 and later versions, ALM enforces the XSRF security check: ALM checks whether the X-XSRF-TOKEN header is included in all requests, except the ones that use the GET HTTP method. If the header is missing, the REST API calls fail.
In this topic:
-
If you have existing scripts to run ALM REST APIs, all these scripts stop working in ALM 16.00 and later versions.
-
If your integrations with ALM access ALM resources using ALM REST APIs, the integrations do not work in ALM 16.00 and later versions.
-
(Recommended) Send the X-XSRF-TOKEN header in all requests . After getting authenticated, the ALM server returns the value of XSRF-TOKEN cookie. In all your subsequent requests, except for the ones that use the HTTP GET method, you should include the X-XSRF-TOKEN header (that is the value of XSRF-TOKEN cookie) in the requests. See X-XSRF-TOKEN header example .
If you want to bypass the security check for some clients, see Bypass security check .
-
(Not recommended) Disable the security check . See Disable security check .
Overview of XSRF and XSRF security check
Cross-Site Request Forgery (CSRF), also known as XSRF, Sea Surf, or Session Riding, is an attack that tricks the victim into submitting a malicious request. It inherits the identity and privileges of the victim to perform an undesired function on the victim’s behalf. If the victim is a normal user, a successful CSRF attack can force the user to perform such requests as transferring funds and changing email addresses. If the victim is an administrative account, CSRF attacks can endanger the entire web application.
How ALM mitigates XSRF
When a user accesses ALM and requests an action, such as submitting a defect change, the ALM website embeds a random token inside the form. When the user submits the form, the random token is returned, and the ALM server then checks if the two tokens match. If the tokens match, the required action is performed. The attackers have no way to access the random token value generated in the web page, and if they request the page, ALM prevents the attackers from reading the answer.
Impacts of XSRF security check
To make sure your existing scripts and integrations continue working after the upgrade to ALM 16.00, do either of the following:
X-XSRF-TOKEN header example
Python example of creating a domain in 16.00 and later
import json
import requests
from requests.auth import HTTPBasicAuth
almUserName = "sa"
almPassword = ""
almURL = "http://<ALM server URL>:<port>/qcbin/"
authEndPoint = almURL + "authentication-point/authenticate"
qcSessionEndPoint = almURL + "rest/site-session"
cookies = dict()
headers = {
'cache-control': "no-cache",
'Accept': "application/json",
'Content-Type': "application/json"
}
response = requests.post(authEndPoint, auth=HTTPBasicAuth(almUserName, almPassword), headers=headers)
if response.status_code == 200:
cookieName = response.headers.get('Set-Cookie')
LWSSO_COOKIE_KEY = cookieName[cookieName.index("LWSSO_COOKIE_KEY=") + 17: cookieName.index(";")]
cookies['LWSSO_COOKIE_KEY'] = LWSSO_COOKIE_KEY
print('logged in successfully')
response = requests.post(qcSessionEndPoint, headers=headers, cookies=cookies)
if response.status_code == 200 | response.status_code == 201:
setCookies = response.headers.get('Set-Cookie').split(",")
for setCookie in setCookies:
cookieName = setCookie[0: setCookie.index("=")].strip()
cookieValue = setCookie[setCookie.index("=") + 1: setCookie.index(";")]
cookies[cookieName] = cookieValue
if cookieName == 'XSRF-TOKEN':
headers['X-XSRF-TOKEN'] = cookieValue
createDomainUrl = almURL + "v2/sa/api/domains"
domainData = {'domain': {'name': 'TEST'}}
response = requests.post(createDomainUrl, headers=headers, cookies=cookies, data=json.dumps(domainData))
print(response)
Java example of creating a defect in 16.00 and later
Add createDefect.setRequestProperty("X-XSRF-TOKEN", xsrfHeaderValue); in your request for ALM 16.00 and later versions. See line 51 in the example below.
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.*;
import java.util.List;
import java.util.Map;
public class CreateDefect {
private static String createDefectRequest = "{\"Fields\":[{\"Name\":\"detected-by\",\"values\":[{\"value\":\"sa\"}]}," +
"{\"Name\":\"creation-time\",\"values\":[{\"value\":\"2010-03-02\"}]}," +
"{\"Name\":\"severity\",\"values\":[{\"value\":\"2-Medium\"}]}," +
"{\"Name\":\"name\",\"values\":[{\"value\":\"Returned value not does not match value in database.</ \"}]}]}";
public static void main(String[] args) throws Exception {
String almURL = "http://<ALM server URL>:<port>/qcbin/";
String authEndPoint = almURL + "authentication-point/alm-authenticate";
String qcSessionEndPoint = almURL + "rest/site-session";
/*authenticate begin */
URL authUrl = new URL(authEndPoint);
HttpURLConnection authConnection = (HttpURLConnection) authUrl.openConnection();
authConnection.setRequestMethod("POST");
authConnection.setRequestProperty("Content-Type", "application/xml");
authConnection.setDoOutput(true);
OutputStream os = authConnection.getOutputStream();
try(OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8")){
osw.write("<alm-authentication><user>sa</user><password></password></alm-authentication>");
}
authConnection.connect();
System.out.println(authConnection.getResponseMessage());
String lwssoCookie = authConnection.getHeaderField("Set-Cookie").split(";")[0];
/*authenticate end */
/*create session begin*/
HttpURLConnection createSession = (HttpURLConnection) new URL(qcSessionEndPoint).openConnection();
createSession.setRequestProperty("Cookie", lwssoCookie);
createSession.setRequestProperty("Content-Type", "application/json");
createSession.setRequestMethod("POST");
createSession.connect();
Map < String, List < String >> values = createSession.getHeaderFields();
String xsrfHeaderValue = "";
String cookies = "";
for (String cookie: values.get("Set-Cookie")) {
String content = cookie.split(";")[0];
cookies = cookies + content + ";";
String[] nameValue = content.split("=");
String name = nameValue[0];
String value = nameValue[1];
if (name.equalsIgnoreCase("XSRF-TOKEN")) {
xsrfHeaderValue = value;
}
}
/*create session end*/
/*create defect begin*/
HttpURLConnection createDefect = (HttpURLConnection) new URL(almURL + "rest/domains/DEFAULT/projects/demo/defects").openConnection();
createDefect.setRequestProperty("X-XSRF-TOKEN", xsrfHeaderValue);
createDefect.setRequestProperty("Cookie", cookies + lwssoCookie);
createDefect.setRequestProperty("Content-Type", "application/json");
createDefect.setRequestProperty("Accept", "application/json");
createDefect.setRequestMethod("POST");
createDefect.setDoOutput(true);
createDefect.setDoInput(true);
OutputStream osCreateDefect = createDefect.getOutputStream();
try(OutputStreamWriter osCreateDefectWriter = new OutputStreamWriter(osCreateDefect, "UTF-8")){
osCreateDefectWriter.write(createDefectRequest);
}
createDefect.connect();
System.out.println(createDefect.getResponseMessage());
}
}
Bypass security check
Disable security check
To disable the security check, set the ENABLE_XSRF_VALIDATION parameter to N .