Do not input private or sensitive data. View Qlik Privacy & Cookie Policy.
Skip to main content

Announcements
Qlik and ServiceNow Partner to Bring Trusted Enterprise Context into AI-Powered Workflows. Learn More!
cancel
Showing results for 
Search instead for 
Did you mean: 
christopherkramer
Partner - Contributor III
Partner - Contributor III

Connecting using JWT token with QlikSense.NetSDK only works once

I am writing my own API and one of its endpoints needs to fetch data from a qlik app. My users authenticate against my API using a JWT token. I configured a virtual proxy in qlik to connect to qlik using the same token. This works, but only once per token. This is my code:

 

private string GetTokenFromAuthHeader()
{
    string authorizationHeader = HttpContext.Request.Headers.Authorization;
    if (string.IsNullOrEmpty(authorizationHeader) || !authorizationHeader.StartsWith("Bearer "))
    {
        throw new InvalidParameterValueException("No bearer token found");
    }
    return authorizationHeader.Substring("Bearer ".Length).Trim();
}

private static ILocation ConnectToQlikUsingToken(string token)
{
    ILocation location = Location.FromUri($"wss://{server}");
    location.VirtualProxyPath = "myproxy";
    location.AsJwtViaProxy(token, false);
    return location;

}

[HttpPost(Name = "myEndpoint")]
public IActionResult Post()
{
    string token = GetTokenFromAuthHeader();
    var location = ConnectToQlikUsingToken(token);
    string appName = "my-appname";
    var appIdentifier = LocationExtensions.AppWithNameOrDefault(location, appName);
    Qlik.Engine.ISession session = Session.WithApp(appIdentifier, SessionType.Default);
    var app = location.App(appIdentifier, session);
    var result = app.EvaluateEx("=Count(Task.Category)");
    return Ok(result);           
}

 

Everything works well for the first request. But when I send another request to my API, authentication fails throwing this error:

      System.Security.Authentication.AuthenticationException: Authentication failed.
         at Qlik.Engine.Communication.QlikConnection.AwaitResponseTask[T](T task, String methodName, CancellationToken cancellationToken)
         at Qlik.Engine.Communication.QlikConnection.AwaitResponse(Task task, String methodName, CancellationToken cancellationToken)
         at Qlik.Engine.Communication.QlikConnection.Ping()
         at Qlik.Sense.JsonRpc.GenericLocation.DisposeOnError(IDisposable o, Action f)
         at Qlik.Engine.LocationExtensions.Hub(ILocation location, ISession session)
         at Qlik.Engine.LocationExtensions.AppsWithNameOrDefault(ILocation location, String appName)
         at Qlik.Engine.LocationExtensions.AppWithNameOrDefault(ILocation location, String appName)

Obtaining a new JWT token and using this works. Why? Do I need to close the session somehow? I tried Dispose() on the location and app but it does not help. Any ideas?

Labels (3)
4 Replies
Øystein_Kolsrud
Employee
Employee

Are you sure you get the same token the second time around? It should work to use the same JWT twice. I ran this code and it worked just fine:

var url = "<url>";
var jwt = "<jwt>";

foreach (var i in Enumerable.Range(0, 2))
{
var location = Location.FromUri(url);
location.AsJwtViaProxy(jwt, false);

var appIdentifier = LocationExtensions.AppWithNameOrDefault(location, "MyApp");
ISession session = Session.WithApp(appIdentifier, SessionType.Default);

using (var app = location.App(appIdentifier))
{
Console.WriteLine(app.GetAppProperties().Title);
}
}

 

SBr
Partner - Contributor II
Partner - Contributor II

Hi,

we tried your suggestion, however, it does not work for us.

The second time 

var appIdentifier = LocationExtensions.AppWithNameOrDefault(location, appName);

is executed, an exception with message "Authentication failed." is thrown.


For reference, we are using Qlik Sense Mai 2024 Patch 15. Are you using a different version?

Thanks and regards,

Stefan

Øystein_Kolsrud
Employee
Employee

I'm not sure why it fails for you. Maybe there's something on how your JWT is configured? A timeout or something? Anyway, have you tried to use the "AsExistingSessionViaProxy" instead? Once you have authenticated using JWT, then you should be able to pick up the session cookie and connect using that one instead. Something like this:

var location = Location.FromUri(url);
location.AsJwtViaProxy(jwt, false);
var appIdentifier = LocationExtensions.AppWithNameOrDefault(location, "MyApp");
var (sessionCookieHeaderName, sessionCookie) = GetSessionCookie(location);

 Where "GetSessionCookie" is defined like this:

private static (string sessionCookieHeaderName, string sessionCookie) GetSessionCookie(ILocation location)
{
    var segments = location.SessionCookie.Split('=');
    return (segments[0], segments[1]);
}

Once you have that cookie, you should be able to use this flow when reconnecting:

foreach (var i in Enumerable.Range(0, 2))
{
    var location = Location.FromUri(url);
    location.AsExistingSessionViaProxy(sessionCookie, sessionCookieHeaderName, false);
    using (var app = location.App(appIdentifier))
    {
        Console.WriteLine(app.GetAppProperties().Title);
    }
}

 

SBr
Partner - Contributor II
Partner - Contributor II

Thanks to the support team, we were able to identify the issue: Qlik Sense does not accept the same token more than once when the jti (JWT ID) attribute is set. See also: Qlik Sense: JWT Token evaluation is failing when same jti is specified  

This is exactly the problem we're facing — we can't reuse the token. That's problematic for us, as we're treating the token like a session token.
So our next question is: Is there any way to disable the jti check?

As for your suggestion: yes, it works, and it's what we're currently doing. However, this means our component is no longer stateless, since it now needs to cache the session ID.
To support multiple instances of the component (e.g., for load balancing), we’d also need an external cache — which adds additional complexity.