Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/cuddly-guests-hug.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@graphprotocol/hypergraph-react": patch
"create-hypergraph": patch
---

improve processConnectAuthSuccess behaviour

14 changes: 10 additions & 4 deletions apps/events/src/routes/authenticate-success.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';

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

useEffect(() => {
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
console.log('redirecting to /');
navigate({ to: '/', replace: true });
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
if (result.success) {
isProcessingRef.current = true;
navigate({ to: '/', replace: true });
} else {
alert(result.error);
}
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);

return <div>Authenticating …</div>;
Expand Down
14 changes: 10 additions & 4 deletions apps/privy-login-example/src/routes/authenticate-success.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';

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

useEffect(() => {
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
console.log('redirecting to /');
navigate({ to: '/', replace: true });
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
if (result.success) {
isProcessingRef.current = true;
navigate({ to: '/', replace: true });
} else {
alert(result.error);
}
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);

return <div>Authenticating …</div>;
Expand Down
13 changes: 10 additions & 3 deletions apps/template-nextjs/Components/Login/AuthCallback.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';

export type AuthCallbackProps = {
ciphertext: string;
Expand All @@ -11,10 +11,17 @@ export type AuthCallbackProps = {
export function AuthCallback({ ciphertext, nonce }: Readonly<AuthCallbackProps>) {
const router = useRouter();
const { processConnectAuthSuccess } = useHypergraphApp();
const isProcessingRef = useRef(false);

useEffect(() => {
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
router.replace('/');
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
if (result.success) {
isProcessingRef.current = true;
router.replace('/');
} else {
alert(result.error);
}
}, [ciphertext, nonce, processConnectAuthSuccess, router]);

return <div>Authenticating …</div>;
Expand Down
14 changes: 10 additions & 4 deletions apps/template-vite-react/src/routes/authenticate-success.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { useEffect } from 'react';
import { useEffect, useRef } from 'react';

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

useEffect(() => {
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
console.log('redirecting to /');
navigate({ to: '/', replace: true });
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
if (result.success) {
isProcessingRef.current = true;
navigate({ to: '/', replace: true });
} else {
alert(result.error);
}
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);

return <div>Authenticating …</div>;
Expand Down
12 changes: 9 additions & 3 deletions docs/docs/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,17 @@ function RouteComponent() {
const { ciphertext, nonce } = Route.useSearch(); // get the ciphertext and nonce from the URL
const { processConnectAuthSuccess } = useHypergraphApp();
const navigate = useNavigate();
const isProcessingRef = useRef(false);

useEffect(() => {
processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
console.log("redirecting to /");
navigate({ to: "/", replace: true });
if (isProcessingRef.current) return; // prevent multiple calls from useEffect double calling in StrictMode
const result = processConnectAuthSuccess({ storage: localStorage, ciphertext, nonce });
if (result.success) {
isProcessingRef.current = true;
navigate({ to: '/', replace: true });
} else {
alert(result.error);
}
}, [ciphertext, nonce, processConnectAuthSuccess, navigate]);

return <div>Authenticating …</div>;
Expand Down
39 changes: 29 additions & 10 deletions packages/hypergraph-react/src/HypergraphAppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,15 @@ export type HypergraphAppCtx = {
connectUrl: string;
redirectFn: (url: URL) => void;
}): void;
processConnectAuthSuccess(params: { storage: Identity.Storage; ciphertext: string; nonce: string }): void;
processConnectAuthSuccess(params: { storage: Identity.Storage; ciphertext: string; nonce: string }):
| {
success: true;
identity: Connect.PrivateAppIdentity;
}
| {
success: false;
error: string;
};
syncServerUri: string;
};

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

console.log('identity', identity);
console.log('privyIdentity', privyIdentity);

const logout = useCallback(() => {
websocketConnection?.close();
setWebsocketConnection(undefined);
Expand Down Expand Up @@ -1464,15 +1469,26 @@ export function HypergraphAppProvider({
);

const processConnectAuthSuccessForContext = useCallback(
(params: { storage: Identity.Storage; ciphertext: string; nonce: string }) => {
(params: {
storage: Identity.Storage;
ciphertext: string;
nonce: string;
}):
| {
success: true;
identity: Connect.PrivateAppIdentity;
}
| {
success: false;
error: string;
} => {
const { storage, ciphertext, nonce } = params;
const storedNonce = storage.getItem('geo-connect-auth-nonce');
const storedExpiry = Number.parseInt(storage.getItem('geo-connect-auth-expiry') ?? '0', 10);
const storedSecretKey = storage.getItem('geo-connect-auth-secret-key');
const storedPublicKey = storage.getItem('geo-connect-auth-public-key');
if (!storedNonce || !storedExpiry || !storedSecretKey || !storedPublicKey) {
alert('Failed to authenticate due missing data in the local storage');
return;
return { success: false, error: 'Failed to authenticate due missing data in the local storage' };
}

try {
Expand All @@ -1487,7 +1503,7 @@ export function HypergraphAppProvider({
}),
);

setIdentity({
const identity: Connect.PrivateAppIdentity = {
address: parsedAuthParams.appIdentityAddress,
addressPrivateKey: parsedAuthParams.appIdentityAddressPrivateKey,
accountAddress: parsedAuthParams.accountAddress,
Expand All @@ -1498,14 +1514,17 @@ export function HypergraphAppProvider({
encryptionPrivateKey: parsedAuthParams.encryptionPrivateKey,
sessionToken: parsedAuthParams.sessionToken,
sessionTokenExpires: parsedAuthParams.sessionTokenExpires,
});
};

setIdentity(identity);
storage.removeItem('geo-connect-auth-nonce');
storage.removeItem('geo-connect-auth-expiry');
storage.removeItem('geo-connect-auth-secret-key');
storage.removeItem('geo-connect-auth-public-key');
return { success: true, identity };
} catch (error) {
console.error(error);
alert('Failed to authenticate due to invalid callback');
return { success: false, error: 'Failed to authenticate due to invalid callback' };
}
},
[setIdentity],
Expand Down
Loading