How to Stay Logged In with Internet Identity

What is the correct way to keep a user logged in on a mobile device for e.g. 2 days using Internet Identity?

You are looking for maxTimeToLive. From the docs:

authClient.login({
  // 7 days in nanoseconds
  maxTimeToLive: BigInt(7 * 24 * 60 * 60 * 1000 * 1000 * 1000),
  onSuccess: async () => {
    handleAuthenticated(authClient);
  },
});

IIRC max allowed value is 30 days

1 Like

I have tried this, but it doesn’t seem to be working.


let maxTimeToLiveNs: bigint = BigInt(1 * 24 * 60 * 60 * 1000 * 1000 * 1000);
let maxTimeToLiveMs = 1 * 24 * 60 * 60 * 1000;

const login = async () => {
  try {
    const authClient = await AuthClient.create({
      idleOptions: {
          idleTimeout: maxTimeToLiveMs
        }
    });
    await authClient.login({
      // 7 days in nanoseconds, not sure if this is working ???
      maxTimeToLive: maxTimeToLiveNs,
      identityProvider: iicanisterId,

      onSuccess: async () => {
        const actor = await $getActor({},true);
  
        isLoggedIn.value = true;

        // check or create user profile // we  must not wait
        actor.createUserProfile();

        // Redirect to the profile page after login
        router.push({ path: '/profile' });
      },
    });
  } catch (error) {
    console.error("Login failed:", error);
  }
};

Avoid creating the AuthClient within your login method, instead create it on page load and re-use it in your login and logout methods. See the recently updated docs: Integrating with II | Internet Computer

If you have multiple AuthClient instances (not recommended) any of these instances could log the user out unintentionally.

Thank you very much!

I believe that was a great suggestion. It turns out there were multiple instances of authClient. Now, I’ve implemented a single shared instance across the Nuxt application using a plugin.

I’ve pushed a new version, let’s see if this resolves the early logout issue.

1 Like

The single instance approach seems working :clap:.
I didn’t notice there is a replaceIdentity function to switch between anonymous and authenticated user :confused: .

Yeah that function is very convenient, it avoids the need to re-create your actor and agent because of an identity change, enabling you to simplify code a lot in most cases.

Another convenient one is the withOptions method on an actor:

// Common call that can also be anonymous
const balance = await ledger.balance.withOptions({ agent: anonymousAgent })(accountPrincipal);

It enables you to define the agent (and thus identity) per individual method call. It also allows you to define the target canister on individual calls, so you can for example use a single ICRC-1 actor to call different ledgers.

When integrating with wallets with e.g. SignerJS or IdentityKit, these options enable you to call certain methods anonymously directly from your dapp and thus avoid a wallet approval prompt.

Overall, these utilities methods enable you to use the default generated actor code from dfx new with these more advanced uses cases without moving to more complex implementations where e.g. you have multiple actors for the same thing.