user.getIdToken() takes a long time

Hi!

I’m using the DID token to authenticate/authorize in my backend. This means I need to pass the DID tokens to my backends in every request from my frontend.

The approach I currently use for getting the DID token, is by using the user.getIdToken() function of the javascript client API. Unfortunately, this call takes between 4-6 seconds to complete, which means my current approach of doing getIdToken() before every request to the backend is making things very slow.

My rationale for using getIdToken() before every backend request, was that this would ensure I always got a valid token. I could always cache the token in my app and reuse it, but that would also require some client-side logic for determining whether the cached key is still usable, or if a new one has to be fetched. I’d prefer the SDK to be responsible for this logic.

What is the recommended approach here, to avoid doing this expensive function call slowing down my app?

const t1 = performance.now();
const token = await m.user.getIdToken();
const t2 = performance.now();
console.log("Call to getToken took " + (t2 - t1) + " ms.");

Hi @hognevevle

Is the request slow every time or just the initial one?

You can increase performance by preloading our iframe: API Reference | Magic

Also, I would recommend against calling getIdToken upon every request. Instead, you should set a cookie with the DID token (or use localStorage) and retrieve a new one when the old one expires.

Alternatively, you can manage your own sessions and use the ID token for auth alone (which is the intended design).

Every call to getIdToken() will take consistently several seconds (typically around 4-6s).

I may have confused my terms a bit - the token returned by getIdToken() is what I pass to my backend. I thought this was the DID token, but I realize now it’s not. I do indeed save the DID token in localstorage.

I ended up caching the ID token in my app, and reuse that during its validity, and only call getIdToken() again when necessary. This fixed my performance issue (although it does still take 4-6 seconds every time I need a new ID token. Sharing my code below in case others experience the same issue. (ref comes from Vue)

const tokenLifetimeInSeconds = 900;
const tokenLifeTimeInMs = tokenLifetimeInSeconds * 1000;
const tokenCache = ref<string | null>(null);
const tokenCacheGeneratedAt = ref<number | null>(null);

const _getToken = notConcurrent(async () => {
  if (
    tokenCache.value &&
    tokenCacheGeneratedAt.value &&
    Date.now() - tokenCacheGeneratedAt.value < tokenLifeTimeInMs
  ) {
    return tokenCache.value;
  }

  try {
    tokenCache.value = await m.user.getIdToken({
      lifespan: tokenLifetimeInSeconds
    });
    tokenCacheGeneratedAt.value = Date.now();

    return tokenCache.value;
  } catch (err) {
    // handle errors
    return null;
  }
});

(the notConcurrent() function is a copy-paste from How to Correctly Manage Concurrency in JavaScript , and used to avoid race conditions if many consumers request the token simultaneously (which was the case for me))

1 Like