JsonServiceClient error thrown when access token expires

I have been using the typescript JsonServiceClient with servericestack core version 1.0.40.

I am using JWT tokens, but was setting the token expiration to a minute to test out the refresh token.

When I call Authenticate, where it does an automatic call to “/access-token”, the call to Authenticate continues but an error is thrown. Previous calls to Authenticate work fine.

“res.json is not a function”
stack
:
"TypeError: res.json is not a function? at JsonServiceClient.handleError
.

Here is the code

import { JsonServiceClient } from 'servicestack-client';
import { Authenticate } from 'dtos';

var client = new JsonServiceClient("http://127.0.0.1/");
client.refreshToken = saved.refreshToken;

var request = new Authenticate();
request.provider = "credentials";
request.userName = "my@email.com";
request.password = "password";

client.post(request)
  .then(response =>
  {
    //  do stuff
  })
  .catch(err =>
  {
    if (err.responseStatus)
    {
      console.log(err.responseStatus.message);
    }
    else if (err.response && err.response.status)
    {
      console.log(err.response.statusText || err.response.status);
    }
    else
    {
      // err.message is "res.json is not a function"
      console.log(err.message || "Unable to login");
    }
  }
);

If you need more info I can try and find the exact line it errors, but it’s in webpack so couldn’t see it tonight.

Can you upgrade to the latest version of servicestack-client (0.0.34), if you’re using npm you’ll need to uninstall then reinstall, as we have several Auth tests that test Authentication.

If it’s still an issue can you show the raw HTTP Response that causes this error, thx.

Thanks. I had 0.0.34 installed anyway. I’ll work on getting the raw responses.

I was trying to see if I could add some tests into servicestack-client. However, I’m havign trouble getting tests to run. I get this:

 > servicestack-client@0.0.32 pretest /tmp/servicestack-client
 > tsc

src/index.ts(793,38): error TS2345: Argument of type '{ method: string; mode: string; credentials: string; headers: Headers; compress: boolean; }' is not assign
able to parameter of type 'RequestInit'.
  Types of property 'mode' are incompatible.
    Type 'string' is not assignable to type 'RequestMode'.
tests/client.auth.spec.ts(1,1): error TS6053: File '/tmp/servicestack-client/typings/index.d.ts' not found.
tests/client.auth.spec.ts(34,1): error TS2304: Cannot find name 'describe'.
tests/client.auth.spec.ts(38,5): error TS2304: Cannot find name 'beforeEach'.
tests/client.auth.spec.ts(43,5): error TS2304: Cannot find name 'it'.
tests/client.auth.spec.ts(56,5): error TS2304: Cannot find name 'it'.
tests/client.auth.spec.ts(75,5): error TS2304: Cannot find name 'it'.
tests/client.auth.spec.ts(89,5): error TS2304: Cannot find name 'it'.
tests/client.auth.spec.ts(106,5): error TS2304: Cannot find name 'it'.

It’s a clean Ubuntu 16 / node v6 docker container with a checkout of the v0.0.34 tag.

Something obvious I’m missing?

edit: found the issue

I was missing global typings, had to run “npm install typings && node_modules/.bin/typings install”.

But also had to change src/index.ts line 793 to add as RequestMode and as RequestCredentials

var reqOptions = {
    method: method,
    mode: this.mode as RequestMode,
    credentials: this.credentials as RequestCredentials,
    headers: this.headers,
    compress: false
};

Do you have the latest version of 2.3.2 TypeScript installed? It uses the W3C Fetch definitions that’s embedded in the “es2016” type definitions, see:

I do. Completely clean docker container. Node v6.10.0, tsc 2.3.2. I tried changing tsconfig to set it es2016, but that didn’t work.

ok looks like they changed the type defs in the last release, if you pull latest it should work.

I’ve got a test case that fails.

Add this to client.auth.spec.ts

it ("Can reauthenticate after an auto refresh access token", async () => {

    var client = new JsonServiceClient(TEST_URL);
    var auth = new Authenticate();
    auth.provider = "credentials";
    auth.userName = "test";
    auth.password = "test";
    var authResponse = await client.post(auth);

    var refreshToken = authResponse.refreshToken;

    let createExpiredJwt = createJwt();
    createExpiredJwt.jwtExpiry = "2000-01-01";
    const expiredJwt = await client.post(createExpiredJwt);
    var bearerToken = expiredJwt.token;

    client = new JsonServiceClient(TEST_URL);
    client.bearerToken = bearerToken;
    client.refreshToken = refreshToken;

    auth.password = "notvalid";
    authResponse = await client.post(auth);

    expect(client.bearerToken).not.eq(expiredJwt.token);
});

BTW it’s likely your last assertion is wrong, it should be:

expect(authResponse .bearerToken).not.eq(expiredJwt.token);

Also this works with fetch in the browser, which you can test if you run http-server then go to http://localhost:8080/testrunner.html

So the issue would be due to the node-fetch js impl, i’ll check to see if there’s a workaround.

Actually the test assertion was wrong, the invalid password request should throw an error, it passed in the browser since it was using the existing session cookies so they needed to be cleared. But it did highlight the issue which should be resolved with this commit.

This change is available from v0.0.35 on npm.

Thanks I’ll try that out. Yes, sorry, I didn’t update the assertion once I realised it was the failed login that was causing the “res.json() is not a function”.The test should check if a login returns 401.

I check it in my main code and see if it’s resolved.

Updating my main project to 0.0.35 is now failing because it can’t find those two new types, RequestMode and RequestCredentials. I find typescript typings all a bit unintuitive but I expected it to pick them up automatically. Do you know if this happening generally?

What version of TypeScript are you using? if it’s not the latest can you upgrade TypeScript, i.e. by installing/uninstalling it?

All working. Thanks, that pointed me at the issue. I had 2.3.2 globally installed and reinstalled, but then saw an old 2.2.2 in node_modules which was being used by webpack ts-loader. The original problem is solved.

1 Like