fix: Amber login callback URL for HashRouter
BUG #1 (critical): buildCallbackUrl() was returning https://skate-spots.org/amber-callback?event= but the app uses HashRouter, so React Router never matched /amber-callback. Amber would open the callback URL in a new tab, land on the homepage, and AmberCallbackPage would never render — login was silently broken. Fixed to: https://skate-spots.org/#/amber-callback?event= BUG #2: AmberCallbackHandler (global, in App.tsx) was competing with AmberCallbackPage on the /amber-callback route, causing a race condition where the global handler could consume the pubkey before the page component. Fixed by detecting the hash path and early-returning when on /amber-callback. BONUS: openAmberForLogin() now persists amber_return_path from the current hash path so AmberCallbackPage can navigate back to where the user was. Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
4f7852fec7
commit
59eda93641
2 changed files with 24 additions and 2 deletions
|
|
@ -40,6 +40,14 @@ export function AmberCallbackHandler() {
|
||||||
console.log('[AmberCallback] Search:', window.location.search);
|
console.log('[AmberCallback] Search:', window.location.search);
|
||||||
console.log('[AmberCallback] Pre-captured event:', sessionStorage.getItem('amber_callback_event'));
|
console.log('[AmberCallback] Pre-captured event:', sessionStorage.getItem('amber_callback_event'));
|
||||||
|
|
||||||
|
// If we're already on the /amber-callback route, AmberCallbackPage handles
|
||||||
|
// the processing — this global handler must stay silent to avoid a race.
|
||||||
|
const hashPath = window.location.hash.replace(/^#/, '').split('?')[0];
|
||||||
|
if (hashPath === '/amber-callback') {
|
||||||
|
console.log('[AmberCallback] On /amber-callback route — deferring to AmberCallbackPage');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this is an Amber callback
|
// Check if this is an Amber callback
|
||||||
const isCallback = isAmberCallback();
|
const isCallback = isAmberCallback();
|
||||||
console.log('[AmberCallback] isAmberCallback():', isCallback);
|
console.log('[AmberCallback] isAmberCallback():', isCallback);
|
||||||
|
|
|
||||||
|
|
@ -270,9 +270,15 @@ function generateOperationId(): string {
|
||||||
/**
|
/**
|
||||||
* Build the dedicated Amber callback URL.
|
* Build the dedicated Amber callback URL.
|
||||||
*
|
*
|
||||||
|
* This app uses HashRouter, so ALL in-app routes live inside the hash fragment:
|
||||||
|
* https://skate-spots.org/#/amber-callback
|
||||||
|
*
|
||||||
|
* Amber will open the callbackUrl in the browser after the user approves.
|
||||||
|
* The URL must therefore use the hash-based path so React Router can match
|
||||||
|
* the /amber-callback route and render AmberCallbackPage.
|
||||||
|
*
|
||||||
* In the Capacitor APK we must use the app's custom URI scheme so Android fires
|
* In the Capacitor APK we must use the app's custom URI scheme so Android fires
|
||||||
* an intent back into the app (not a browser navigation).
|
* an intent back into the app (not a browser navigation).
|
||||||
* Web/PWA builds use the normal https origin.
|
|
||||||
*
|
*
|
||||||
* The app ID is `org.skatespots.app` — Capacitor registers this as a URI scheme
|
* The app ID is `org.skatespots.app` — Capacitor registers this as a URI scheme
|
||||||
* automatically via the `appId` in capacitor.config.ts.
|
* automatically via the `appId` in capacitor.config.ts.
|
||||||
|
|
@ -285,7 +291,10 @@ function buildCallbackUrl(): string {
|
||||||
// correct route inside the HashRouter.
|
// correct route inside the HashRouter.
|
||||||
return 'org.skatespots.app://amber-callback?event=';
|
return 'org.skatespots.app://amber-callback?event=';
|
||||||
}
|
}
|
||||||
return `${window.location.origin}/amber-callback?event=`;
|
// HashRouter: routes live in the # fragment, so the callback URL must be:
|
||||||
|
// https://skate-spots.org/#/amber-callback?event=<result>
|
||||||
|
// This is what Amber will open in the browser tab after user approves.
|
||||||
|
return `${window.location.origin}/#/amber-callback?event=`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -336,6 +345,11 @@ export function openAmberForLogin(): void {
|
||||||
|
|
||||||
setAmberPendingOperation(pendingOp);
|
setAmberPendingOperation(pendingOp);
|
||||||
|
|
||||||
|
// Store the current hash path so AmberCallbackPage can navigate back here
|
||||||
|
// after login (e.g. user was on /map and tapped Login → returns to /map).
|
||||||
|
const currentPath = window.location.hash.replace(/^#/, '') || '/';
|
||||||
|
localStorage.setItem('amber_return_path', currentPath);
|
||||||
|
|
||||||
// NIP-55 nostrsigner: URI — Amber opens, user approves, Amber calls callbackUrl
|
// NIP-55 nostrsigner: URI — Amber opens, user approves, Amber calls callbackUrl
|
||||||
const amberUrl = `nostrsigner:?compressionType=none&returnType=signature&type=get_public_key&callbackUrl=${encodeURIComponent(callbackUrl)}`;
|
const amberUrl = `nostrsigner:?compressionType=none&returnType=signature&type=get_public_key&callbackUrl=${encodeURIComponent(callbackUrl)}`;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue