Skip to content

Commit 4462360

Browse files
committed
Fix session reset
1 parent fde072c commit 4462360

File tree

3 files changed

+28
-13
lines changed

3 files changed

+28
-13
lines changed

src/frontend/src/lib/stores/session.store.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,21 @@ export interface Session {
2222
salt: Uint8Array;
2323
}
2424

25+
type SessionData = Pick<Session, "identity" | "nonce" | "salt">;
26+
2527
type SessionStore = Readable<Session> & {
2628
init: (params: {
2729
canisterId: Principal;
2830
agentOptions: HttpAgentOptions;
2931
}) => Promise<void>;
30-
reset: () => Promise<void>;
32+
reset: () => void;
3133
};
3234

3335
const STORAGE_KEY = "ii-session";
3436

3537
const internalStore = writable<Session | undefined>();
3638

37-
const create = async () => {
39+
const createSession = async (): Promise<SessionData> => {
3840
const identity = await ECDSAKeyIdentity.generate({
3941
extractable: true,
4042
});
@@ -59,7 +61,7 @@ const create = async () => {
5961
};
6062
};
6163

62-
const read = async () => {
64+
const readSession = async (): Promise<SessionData | undefined> => {
6365
const item = sessionStorage.getItem(STORAGE_KEY);
6466
if (isNullish(item)) {
6567
return undefined;
@@ -91,9 +93,24 @@ const read = async () => {
9193
};
9294
};
9395

96+
let preCreatedSession: SessionData;
97+
const nextSession = (): SessionData => {
98+
const session = preCreatedSession!;
99+
void (async () => {
100+
// Pre-create the next session in the background to make reset synchronous
101+
preCreatedSession = await createSession();
102+
})();
103+
return session;
104+
};
105+
94106
export const sessionStore: SessionStore = {
95107
init: async ({ canisterId, agentOptions }) => {
96-
const { identity, nonce, salt } = (await read()) ?? (await create());
108+
// Try to read an existing session from sessionStorage,
109+
// if it doesn't exist or is expired create a new one.
110+
const { identity, nonce, salt } =
111+
(await readSession()) ?? (await createSession());
112+
// Pre-create the next session for synchronous reset later on.
113+
void nextSession();
97114
const agent = HttpAgent.createSync({ ...agentOptions, identity });
98115
// Fetch subnet keys to speed up queries during authentication,
99116
// this avoids having to fetch them later on user interaction.
@@ -110,8 +127,8 @@ export const sessionStore: SessionStore = {
110127
}
111128
return session;
112129
}).subscribe,
113-
reset: async () => {
114-
const { identity, nonce, salt } = await create();
130+
reset: () => {
131+
const { identity, nonce, salt } = nextSession();
115132
internalStore.update((session) => {
116133
if (isNullish(session)) {
117134
throw new Error("Not initialized");

src/frontend/src/lib/utils/openID.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ export const createRedirectURL = (
103103
config: Omit<RequestConfig, "configURL">,
104104
options: RequestOptions,
105105
): URL => {
106-
const state = toBase64URL(
107-
window.crypto.getRandomValues(new Uint8Array(12)).buffer,
108-
);
106+
const state = toBase64URL(window.crypto.getRandomValues(new Uint8Array(12)));
109107
const redirectURL = new URL(REDIRECT_CALLBACK_PATH, window.location.origin);
110108
const authURL = new URL(config.authURL);
111109
// Even though we only need an id token, we're still asking for a code
@@ -170,7 +168,7 @@ export const createAnonymousNonce = async (
170168
bytes.set(salt);
171169
bytes.set(principal.toUint8Array(), 32);
172170
const nonce = toBase64URL(
173-
await window.crypto.subtle.digest("SHA-256", bytes),
171+
new Uint8Array(await window.crypto.subtle.digest("SHA-256", bytes)),
174172
);
175173
return { nonce, salt };
176174
};

src/frontend/src/lib/utils/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,10 @@ export const bufFromBufLike = (
431431
);
432432
};
433433

434-
export const toBase64 = (bytes: ArrayBuffer): string =>
435-
btoa(String.fromCharCode(...new Uint8Array(bytes)));
434+
export const toBase64 = (bytes: Uint8Array): string =>
435+
btoa(String.fromCharCode(...bytes));
436436

437-
export const toBase64URL = (bytes: ArrayBuffer): string =>
437+
export const toBase64URL = (bytes: Uint8Array): string =>
438438
toBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
439439

440440
export const fromBase64 = (base64: string): Uint8Array =>

0 commit comments

Comments
 (0)