Skip to content

Commit

Permalink
logout whoami behavior with onIdle
Browse files Browse the repository at this point in the history
  • Loading branch information
krpeacock committed Aug 2, 2024
1 parent 12d1a4d commit 10b9279
Showing 1 changed file with 83 additions and 2 deletions.
85 changes: 83 additions & 2 deletions packages/use-auth-client/src/use-auth-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,35 @@ import {
AuthClientLoginOptions,
InternetIdentityAuthResponseSuccess,
} from '@dfinity/auth-client';
import { Identity } from '@dfinity/agent';
import {
type Identity,
type Agent,
type HttpAgentOptions,
type ActorConfig,
HttpAgent,
Actor,
} from '@dfinity/agent';
import type { IDL } from '@dfinity/candid';
import { Principal } from '@dfinity/principal';

export interface CreateActorOptions {
/**
* @see {@link Agent}
*/
agent?: Agent;
/**
* @see {@link HttpAgentOptions}
*/
agentOptions?: HttpAgentOptions;
/**
* @see {@link ActorConfig}
*/
actorOptions?: ActorConfig;

idlFactory: IDL.InterfaceFactory;

canisterId: Principal | string;
}

/**
* Options for the useAuthClient hook
Expand All @@ -19,6 +47,10 @@ export type UseAuthClientOptions = {
* Options passed during the login of the auth client
*/
loginOptions?: AuthClientLoginOptions;
/**
* Options to create an actor using the auth client identity
*/
actorOptions?: CreateActorOptions;
};

/**
Expand All @@ -31,17 +63,39 @@ export type UseAuthClientOptions = {
export function useAuthClient(options?: UseAuthClientOptions) {
const [authClient, setAuthClient] = React.useState<AuthClient | null>(null);
const [identity, setIdentity] = React.useState<Identity | null>(null);
const [actor, setActor] = React.useState<Actor | null>(null);
const [isAuthenticated, setIsAuthenticated] = React.useState<boolean>(false);

// load the auth client on mount
React.useEffect(() => {
AuthClient.create(options?.createOptions).then(async client => {
AuthClient.create({
...options?.createOptions,
idleOptions: {
...options?.createOptions?.idleOptions,
onIdle:
options?.createOptions?.idleOptions?.onIdle ??
(() => {
logout();
}),
},
}).then(async client => {
setAuthClient(client);
setIdentity(client.getIdentity());
setIsAuthenticated(await client.isAuthenticated());
});
}, []);

React.useEffect(() => {
if (identity && options?.actorOptions) {
createActor({
...options.actorOptions,
agentOptions: { ...options?.actorOptions?.agentOptions, identity },
}).then(actor => {
setActor(actor);
});
}
}, [identity]);

/**
* Login through your configured identity provider
* Wraps the onSuccess and onError callbacks with promises for convenience
Expand Down Expand Up @@ -78,14 +132,41 @@ export function useAuthClient(options?: UseAuthClientOptions) {
setIsAuthenticated(false);
setIdentity(null);
await authClient.logout();
setActor(await createActor(options?.actorOptions));
}
}

return {
actor,
authClient,
identity,
isAuthenticated,
login,
logout,
};
}

const createActor = async (options: CreateActorOptions) => {
const agent = options.agent || (await HttpAgent.create({ ...options.agentOptions }));

if (options.agent && options.agentOptions) {
console.warn(
'Detected both agent and agentOptions passed to createActor. Ignoring agentOptions and proceeding with the provided agent.',
);
}

// Fetch root key for certificate validation during development
if (process.env.DFX_NETWORK !== 'ic') {
agent.fetchRootKey().catch(err => {
console.warn('Unable to fetch root key. Check to ensure that your local replica is running');
console.error(err);
});
}

// Creates an actor with using the candid interface and the HttpAgent
return Actor.createActor(options.idlFactory, {
agent,
canisterId: options.canisterId,
...options.actorOptions,
});
};

0 comments on commit 10b9279

Please sign in to comment.