Skip to content

Commit 1d29c53

Browse files
authored
improve processConnectAuthSuccess behaviour (#543)
1 parent 4c6ed64 commit 1d29c53

File tree

7 files changed

+85
-28
lines changed

7 files changed

+85
-28
lines changed

.changeset/cuddly-guests-hug.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"@graphprotocol/hypergraph-react": patch
3+
"create-hypergraph": patch
4+
---
5+
6+
improve processConnectAuthSuccess behaviour
7+

apps/events/src/routes/authenticate-success.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
22
import { createFileRoute, useNavigate } from '@tanstack/react-router';
3-
import { useEffect } from 'react';
3+
import { useEffect, useRef } from 'react';
44

55
export const Route = createFileRoute('/authenticate-success')({
66
component: RouteComponent,
@@ -16,11 +16,17 @@ function RouteComponent() {
1616
const { ciphertext, nonce } = Route.useSearch();
1717
const { processConnectAuthSuccess } = useHypergraphApp();
1818
const navigate = useNavigate();
19+
const isProcessingRef = useRef(false);
1920

2021
useEffect(() => {
21-
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
22-
console.log('redirecting to /');
23-
navigate({ to: '/', replace: true });
22+
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
23+
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
24+
if (result.success) {
25+
isProcessingRef.current = true;
26+
navigate({ to: '/', replace: true });
27+
} else {
28+
alert(result.error);
29+
}
2430
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);
2531

2632
return <div>Authenticating …</div>;

apps/privy-login-example/src/routes/authenticate-success.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
22
import { createFileRoute, useNavigate } from '@tanstack/react-router';
3-
import { useEffect } from 'react';
3+
import { useEffect, useRef } from 'react';
44

55
export const Route = createFileRoute('/authenticate-success')({
66
component: RouteComponent,
@@ -16,11 +16,17 @@ function RouteComponent() {
1616
const { ciphertext, nonce } = Route.useSearch();
1717
const { processConnectAuthSuccess } = useHypergraphApp();
1818
const navigate = useNavigate();
19+
const isProcessingRef = useRef(false);
1920

2021
useEffect(() => {
21-
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
22-
console.log('redirecting to /');
23-
navigate({ to: '/', replace: true });
22+
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
23+
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
24+
if (result.success) {
25+
isProcessingRef.current = true;
26+
navigate({ to: '/', replace: true });
27+
} else {
28+
alert(result.error);
29+
}
2430
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);
2531

2632
return <div>Authenticating …</div>;

apps/template-nextjs/Components/Login/AuthCallback.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
44
import { useRouter } from 'next/navigation';
5-
import { useEffect } from 'react';
5+
import { useEffect, useRef } from 'react';
66

77
export type AuthCallbackProps = {
88
ciphertext: string;
@@ -11,10 +11,17 @@ export type AuthCallbackProps = {
1111
export function AuthCallback({ ciphertext, nonce }: Readonly<AuthCallbackProps>) {
1212
const router = useRouter();
1313
const { processConnectAuthSuccess } = useHypergraphApp();
14+
const isProcessingRef = useRef(false);
1415

1516
useEffect(() => {
16-
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
17-
router.replace('/');
17+
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
18+
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
19+
if (result.success) {
20+
isProcessingRef.current = true;
21+
router.replace('/');
22+
} else {
23+
alert(result.error);
24+
}
1825
}, [ciphertext, nonce, processConnectAuthSuccess, router]);
1926

2027
return <div>Authenticating …</div>;

apps/template-vite-react/src/routes/authenticate-success.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
22
import { createFileRoute, useNavigate } from '@tanstack/react-router';
3-
import { useEffect } from 'react';
3+
import { useEffect, useRef } from 'react';
44

55
export const Route = createFileRoute('/authenticate-success')({
66
component: RouteComponent,
@@ -16,11 +16,17 @@ function RouteComponent() {
1616
const { ciphertext, nonce } = Route.useSearch();
1717
const { processConnectAuthSuccess } = useHypergraphApp();
1818
const navigate = useNavigate();
19+
const isProcessingRef = useRef(false);
1920

2021
useEffect(() => {
21-
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
22-
console.log('redirecting to /');
23-
navigate({ to: '/', replace: true });
22+
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
23+
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
24+
if (result.success) {
25+
isProcessingRef.current = true;
26+
navigate({ to: '/', replace: true });
27+
} else {
28+
alert(result.error);
29+
}
2430
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);
2531

2632
return <div>Authenticating …</div>;

docs/docs/authentication.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,17 @@ function RouteComponent() {
126126
const { ciphertext, nonce } = Route.useSearch(); // get the ciphertext and nonce from the URL
127127
const { processConnectAuthSuccess } = useHypergraphApp();
128128
const navigate = useNavigate();
129+
const isProcessingRef = useRef(false);
129130

130131
useEffect(() => {
131-
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
132-
console.log("redirecting to /");
133-
navigate({ to: "/", replace: true });
132+
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
133+
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
134+
if (result.success) {
135+
isProcessingRef.current = true;
136+
navigate({ to: '/', replace: true });
137+
} else {
138+
alert(result.error);
139+
}
134140
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);
135141

136142
return <div>Authenticating …</div>;

packages/hypergraph-react/src/HypergraphAppContext.tsx

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,15 @@ export type HypergraphAppCtx = {
115115
connectUrl: string;
116116
redirectFn: (url: URL) => void;
117117
}): void;
118-
processConnectAuthSuccess(params: { storage: Identity.Storage; ciphertext: string; nonce: string }): void;
118+
processConnectAuthSuccess(params: { storage: Identity.Storage; ciphertext: string; nonce: string }):
119+
| {
120+
success: true;
121+
identity: Connect.PrivateAppIdentity;
122+
}
123+
| {
124+
success: false;
125+
error: string;
126+
};
119127
syncServerUri: string;
120128
};
121129

@@ -250,9 +258,6 @@ export function HypergraphAppProvider({
250258
const identity = useSelectorStore(store, (state) => state.context.identity);
251259
const privyIdentity = useSelectorStore(store, (state) => state.context.privyIdentity);
252260

253-
console.log('identity', identity);
254-
console.log('privyIdentity', privyIdentity);
255-
256261
const logout = useCallback(() => {
257262
websocketConnection?.close();
258263
setWebsocketConnection(undefined);
@@ -1464,15 +1469,26 @@ export function HypergraphAppProvider({
14641469
);
14651470

14661471
const processConnectAuthSuccessForContext = useCallback(
1467-
(params: { storage: Identity.Storage; ciphertext: string; nonce: string }) => {
1472+
(params: {
1473+
storage: Identity.Storage;
1474+
ciphertext: string;
1475+
nonce: string;
1476+
}):
1477+
| {
1478+
success: true;
1479+
identity: Connect.PrivateAppIdentity;
1480+
}
1481+
| {
1482+
success: false;
1483+
error: string;
1484+
} => {
14681485
const { storage, ciphertext, nonce } = params;
14691486
const storedNonce = storage.getItem('geo-connect-auth-nonce');
14701487
const storedExpiry = Number.parseInt(storage.getItem('geo-connect-auth-expiry') ?? '0', 10);
14711488
const storedSecretKey = storage.getItem('geo-connect-auth-secret-key');
14721489
const storedPublicKey = storage.getItem('geo-connect-auth-public-key');
14731490
if (!storedNonce || !storedExpiry || !storedSecretKey || !storedPublicKey) {
1474-
alert('Failed to authenticate due missing data in the local storage');
1475-
return;
1491+
return { success: false, error: 'Failed to authenticate due missing data in the local storage' };
14761492
}
14771493

14781494
try {
@@ -1487,7 +1503,7 @@ export function HypergraphAppProvider({
14871503
}),
14881504
);
14891505

1490-
setIdentity({
1506+
const identity: Connect.PrivateAppIdentity = {
14911507
address: parsedAuthParams.appIdentityAddress,
14921508
addressPrivateKey: parsedAuthParams.appIdentityAddressPrivateKey,
14931509
accountAddress: parsedAuthParams.accountAddress,
@@ -1498,14 +1514,17 @@ export function HypergraphAppProvider({
14981514
encryptionPrivateKey: parsedAuthParams.encryptionPrivateKey,
14991515
sessionToken: parsedAuthParams.sessionToken,
15001516
sessionTokenExpires: parsedAuthParams.sessionTokenExpires,
1501-
});
1517+
};
1518+
1519+
setIdentity(identity);
15021520
storage.removeItem('geo-connect-auth-nonce');
15031521
storage.removeItem('geo-connect-auth-expiry');
15041522
storage.removeItem('geo-connect-auth-secret-key');
15051523
storage.removeItem('geo-connect-auth-public-key');
1524+
return { success: true, identity };
15061525
} catch (error) {
15071526
console.error(error);
1508-
alert('Failed to authenticate due to invalid callback');
1527+
return { success: false, error: 'Failed to authenticate due to invalid callback' };
15091528
}
15101529
},
15111530
[setIdentity],

0 commit comments

Comments
 (0)