Skip to main content
Announcements
Defect acknowledgement with Nprinting Engine May 2022 SR2, please READ HERE
cancel
Showing results for 
Search instead for 
Did you mean: 
Not applicable

NPrinting 17.2.1 REST API - Create OnDemand Request

I'm having issues invoking the API request to en-queue a new on-demand request as per the API (https://help.qlik.com/en-US/nprinting/17.2/APIs/NP%20API/#ondemandRequestsPost).

Authentication is successful and I am able to query Apps, Filters, Reports and On-Demand Requests.  However, when I invoke the API to create an On-Demand request I receive the following error from the server:

{

    "title": "Forbidden",

    "description": "REVEL_CSRF: tokens mismatch."

}

This error occurs regardless of the payload being supplied.  Even supplying no payload generates the same result.  Reviewing the error description it appears to relate to a Cross-Site Request Forgery (CSRF) exception where the authentication token associated with the current login session is different.

I'm using .NET Framework v4.6.1 to query the service.  The relevant code is as follows (edited for brevity):

public class NPrintingService

{

  private HttpClient Client { get; set; }

  public NPrintingService(string serviceUrl)

  {

  var httpClientHandler = new HttpClientHandler { UseDefaultCredentials = true };

  var client = new HttpClient(httpClientHandler)

  {

  BaseAddress = new Uri(serviceUrl)

  };

  client.DefaultRequestHeaders.Accept.Clear();

  client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

  this.Client = client;

  }

  public async Task<bool> Authenticate()

  {

  var response = await this.Client.GetAsync("api/v1/login/ntlm");

  if (response.IsSuccessStatusCode)

  {

  return await Task.FromResult(true);

  }

  return await Task.FromResult(false);

  }

  public async Task<string> CreateOnDemandRequest()

  {

  HttpResponseMessage response = await this.Client.PostAsJsonAsync("api/v1/ondemand/requests", null);

  if (response.IsSuccessStatusCode)

  {

  var content = await response.Content.ReadAsStringAsync();

  return content;

  }

  //var error = await response.Content.ReadAsStringAsync(); // NOTE: This code is used to retrieve the underlying 'REVEL_CSRF: tokens mismatch' error

  throw new ApplicationException($"({response.StatusCode}): {response.ReasonPhrase}");

  }

}

This code is being used in a Console application running in the context of my domain account.  This domain account has been setup in NPrinting as a user with the 'Administrator' security role.  I've also ensured that the user has been linked with my domain account.

var service = new NPrintingService(ConfigurationManager.AppSettings["ServiceUrl"]);

var authenticate = await service.Authenticate();

var result = await service.CreateOnDemandRequest(); // Exception occurs here

I can confirm that the request is successfully authenticated.  I've also run this code with Fiddler active and confirmed that the output is the same -- Authentication is successful, but creating the On-Demand request fails.

Has anyone been able to successfully use this API?  If so, how?

1 Solution

Accepted Solutions
Not applicable
Author

Short Answer: Your requests need to include the custom HTTP header X-XSRF-TOKEN.  The value of this header will be identical to the value of the NPWEBCONSOLE_XSRF-TOKEN cookie.  For example (taken from Fiddler, which will successfully submit an OnDemand request)

POST https://REDACTED/api/v1/ondemand/requests HTTP/1.1

Accept: application/json

X-XSRF-TOKEN: 9z80xdFG/9T+xhKUmBFlFxVOCbkjqimdW+iuUZtXtl4=

Content-Type: application/json; charset=utf-8

Host: REDACTED

Cookie: NPWEBCONSOLE_XSRF-TOKEN=9z80xdFG/9T+xhKUmBFlFxVOCbkjqimdW+iuUZtXtl4=; NPWEBCONSOLE_SESSION=71512e89749096debeeaa8eb3583f508570e1df6-%00NPWEBCONSOLE_XSRF-TOKEN%3A9z80xdFG%2F9T%2BxhKUmBFlFxVOCbkjqimdW%2BiuUZtXtl4%3D%00%00_TS%3Asession%00%00userid%3Ae66d500966df4d96b9eb52989c13d931%00

Content-Length: 100

Expect: 100-continue

{"Config":{"OutputFormat":"HTML","ReportId":"595d3ca8-ff7a-4199-98ad-dc55e6004b6c"},"Type":"Report"}

Long Answer:

The only other instance of this error I could find was for the source for a GO library at (https://github.com/cbonello/revel-csrf/blob/master/csrf.go).

I ended up decompiling the NPrinting Server WebEngine (which is built using the .NET Framework) and found in the Startup class the following snippet:

directoryName.EnvironmentVariables["GOPATH"] = fileInfo.DirectoryName;

Which gave me a clue that the application was actually using something built in GO.  This turned out to be a proxy that sits in front of the WebEngine to validate requests.  The application executable is located at:

C:\Program Files\NPrintingServer\proxy\webconsoleproxy\

To help diagnose the problem I enabled additional loggin in the app.config, located at:

C:\Program Files\NPrintingServer\proxy\webconsoleproxy\src\qlik.com\webconsoleproxy\conf

To enable logging, the following changes were made to the end of the conf:

log.trace.output = %(app.name)s.log

log.info.output  = %(app.name)s.log

log.warn.output  = %(app.name)s.log

log.error.output = %(app.name)s.log

I could then see that the library was missing a token from the client:

TRACE 2016/12/08 11:26:44 csrf.go:56: CSRF Filter: cookie found, value: jTmzEhFFnxRGlm11lv3w2zoIuGIxMCbCHb5TjD6B5iE=

TRACE 2016/12/08 11:26:44 csrf.go:100: REVEL-CSRF: Processing unsafe 'POST' method...

TRACE 2016/12/08 11:26:44 csrf.go:128: REVEL-CSRF: Token received from client: ''

Reviewing the source of the CSRF.go file I found that it was expecting a header named X-XSRF-TOKEN.  Taking an intuitive step I used the same value returned from the NPrinting authentication cookie (NPWEBCONSOLE_XSRF-TOKEN) and was successful in getting the POST requests submitted.

View solution in original post

6 Replies
Not applicable
Author

One discrepancy I noticed in Fiddler is that after performing the initial Authentication call that the Cookie: NPWEBCONSOLE_SESSION was not the same for the POST request, though it was the same as the GET requests.

GET Request:

2b959abceaaf4b269651180bae7834ffda463955-_TS:sessionuserid:e66d500966df4d96b9eb52989c13d931NPWEBCONSOLE_XSRF-TOKEN:I/z1TsYFYSOO2P3T/DrgI7IpJt0DTuiWadLOx09YoFQ=

POST Request:

5faf8b88b0e99baa0681b3ad51658564cc6cfa27-NPWEBCONSOLE_XSRF-TOKEN:I/z1TsYFYSOO2P3T/DrgI7IpJt0DTuiWadLOx09YoFQ=_TS:sessionuserid:e66d500966df4d96b9eb52989c13d931

I've revised my code so that after the Authentication request the NPWEBCONSOLE_XSRF-TOKEN and NPWEBCONSOLE_SESSION cookie values are pulled from the response and then used on each subsequent request, and have confirmed through Fiddler that the cookie values are now consistent amongst all request types, but I still get the same error as before (REVEL_CSRF: tokens mismatch).

Not applicable
Author

Short Answer: Your requests need to include the custom HTTP header X-XSRF-TOKEN.  The value of this header will be identical to the value of the NPWEBCONSOLE_XSRF-TOKEN cookie.  For example (taken from Fiddler, which will successfully submit an OnDemand request)

POST https://REDACTED/api/v1/ondemand/requests HTTP/1.1

Accept: application/json

X-XSRF-TOKEN: 9z80xdFG/9T+xhKUmBFlFxVOCbkjqimdW+iuUZtXtl4=

Content-Type: application/json; charset=utf-8

Host: REDACTED

Cookie: NPWEBCONSOLE_XSRF-TOKEN=9z80xdFG/9T+xhKUmBFlFxVOCbkjqimdW+iuUZtXtl4=; NPWEBCONSOLE_SESSION=71512e89749096debeeaa8eb3583f508570e1df6-%00NPWEBCONSOLE_XSRF-TOKEN%3A9z80xdFG%2F9T%2BxhKUmBFlFxVOCbkjqimdW%2BiuUZtXtl4%3D%00%00_TS%3Asession%00%00userid%3Ae66d500966df4d96b9eb52989c13d931%00

Content-Length: 100

Expect: 100-continue

{"Config":{"OutputFormat":"HTML","ReportId":"595d3ca8-ff7a-4199-98ad-dc55e6004b6c"},"Type":"Report"}

Long Answer:

The only other instance of this error I could find was for the source for a GO library at (https://github.com/cbonello/revel-csrf/blob/master/csrf.go).

I ended up decompiling the NPrinting Server WebEngine (which is built using the .NET Framework) and found in the Startup class the following snippet:

directoryName.EnvironmentVariables["GOPATH"] = fileInfo.DirectoryName;

Which gave me a clue that the application was actually using something built in GO.  This turned out to be a proxy that sits in front of the WebEngine to validate requests.  The application executable is located at:

C:\Program Files\NPrintingServer\proxy\webconsoleproxy\

To help diagnose the problem I enabled additional loggin in the app.config, located at:

C:\Program Files\NPrintingServer\proxy\webconsoleproxy\src\qlik.com\webconsoleproxy\conf

To enable logging, the following changes were made to the end of the conf:

log.trace.output = %(app.name)s.log

log.info.output  = %(app.name)s.log

log.warn.output  = %(app.name)s.log

log.error.output = %(app.name)s.log

I could then see that the library was missing a token from the client:

TRACE 2016/12/08 11:26:44 csrf.go:56: CSRF Filter: cookie found, value: jTmzEhFFnxRGlm11lv3w2zoIuGIxMCbCHb5TjD6B5iE=

TRACE 2016/12/08 11:26:44 csrf.go:100: REVEL-CSRF: Processing unsafe 'POST' method...

TRACE 2016/12/08 11:26:44 csrf.go:128: REVEL-CSRF: Token received from client: ''

Reviewing the source of the CSRF.go file I found that it was expecting a header named X-XSRF-TOKEN.  Taking an intuitive step I used the same value returned from the NPrinting authentication cookie (NPWEBCONSOLE_XSRF-TOKEN) and was successful in getting the POST requests submitted.

philipp_kunz
Partner - Creator II
Partner - Creator II

Hi Anthony,

great you figured out this issue, it solved my Problem,

however if I log off fom Server and log on with a different

Service account admin User the Problem still remains.

Do you have an idea?

Thanks!

Chrome by the way never throws an error.

bc-thebruuu
Creator
Creator

Hi!

I am having the same REVEL_CSRF: tokens mismatch. issue

But I am in a slightly different scenario as I am trying to connect to the API via the qvRestConnector and the X-XSRF-TOKEN hint you published get no better.

I managed to  do the login via qvRestConnector and I get the cookies values.

Those values are good as I can use them in a curl query and in this way I can see the task execution in the NPrinting Web Console :

curl  -v -X POST  -khttps://<server name>:4993/api/v1/tasks/<task id>/executions -H "X-XSRF-TOKEN:%cookie2%" -H"Cookie:%cookie1%"

where cookie1 and cookie 2 are the strings I get from the login qcRestConnector query (in Qv).

But If I try to run the POST query to the https://<server name>:4993/api/v1/tasks/<task id>/executions using the Cookie queryheader variable and X-XSRF-TOKEN queryheader variable

Nothing happen on the server side and on the Qv side

I get a response that Qv is not able to handle/show (QVX....error)

Can you help me as I am struggling on that?

aurelien_thiery
Contributor II
Contributor II

Hi Anthony,

Can you describe us what are the changes you made in the CSRF.go file please?

I'm not a C# professional.

Thank you very much!

Best regards,

Aurélien

sivarajkumar
Contributor
Contributor

There is a much simpler and easier way to invoke Qlik Nprint using REST or CURL. 

Most of the tools we used to develop the Big Data Platform is installed on Linux. Qliksense and NPrint are the odd ones installed in Windows. We have work on a very narrow timeline to complete EOD and trigger Qliksense/Nprint tasks. Due to OS conflict, we run the tasks manually. Challenge in NPrint is, there are bunch of reports and different ways the tasks were created. It is what it is and I can't change that. 

We built a simple shell script with couple of curl commands to get this done seamlessly without impacting the security features offered in Nov 2018 release (AD)

1. Get the Auth token for the NTLM Creds --> curl -X GET https://Server:4993/api/v1/login/ntlm -v --ntlm --negotiate -u domain\user:Pass

2. Fire the Post request to Task execution --> refer the following URL for more details on the headers and cookies list.

https://qliksupport.force.com/articles/Basic/How-to-Authenticate-Connect-with-the-Qlik-NPrinting-API...

 

List of supported APIs --> https://help.qlik.com/en-US/nprinting/November2017/APIs/NP+API/index.html?page=45