diff --git a/src/App.web.tsx b/src/App.web.tsx
index cd451e38c..518afd143 100644
--- a/src/App.web.tsx
+++ b/src/App.web.tsx
@@ -41,6 +41,7 @@ import {
useSessionApi,
} from '#/state/session'
import {getWebOAuthClient} from '#/state/session/oauth-web-client'
+import {consumeOAuthReturnUrl} from '#/state/session/oauth-web-return-url'
import {readLastActiveAccount} from '#/state/session/util'
import {Provider as ShellStateProvider} from '#/state/shell'
import {Provider as ComposerProvider} from '#/state/shell/composer'
@@ -72,11 +73,11 @@ import {
features,
setupDeviceId,
} from '#/analytics'
-import {SettingsSyncGate} from '#/features/settingsSync'
import {
prefetchLiveEvents,
Provider as LiveEventsProvider,
} from '#/features/liveEvents/context'
+import {SettingsSyncGate} from '#/features/settingsSync'
import * as Geo from '#/geolocation'
import {Splash} from '#/Splash'
import {BackgroundNotificationPreferencesProvider} from '../modules/expo-background-notification-handler/src/BackgroundNotificationHandlerProvider'
@@ -144,6 +145,13 @@ function InnerApp() {
},
'LoginForm',
)
+
+ const returnUrl = consumeOAuthReturnUrl()
+ if (returnUrl) {
+ window.location.replace(returnUrl)
+ return
+ }
+
// Clear hash fragment after processing
window.history.replaceState(null, '', window.location.pathname)
return
@@ -187,55 +195,55 @@ function InnerApp() {
-
-
-
-
-
- {/* LabelDefsProvider MUST come before ModerationOptsProvider */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+ {/* LabelDefsProvider MUST come before ModerationOptsProvider */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/routes/web.ts b/src/lib/routes/web.ts
new file mode 100644
index 000000000..a7b212ccd
--- /dev/null
+++ b/src/lib/routes/web.ts
@@ -0,0 +1,4 @@
+export function replaceWebLocation(href: string) {
+ if (typeof window === 'undefined') return
+ window.location.replace(href)
+}
diff --git a/src/screens/Login/AuthCallback.tsx b/src/screens/Login/AuthCallback.tsx
index 0de2a37bc..a16730d87 100644
--- a/src/screens/Login/AuthCallback.tsx
+++ b/src/screens/Login/AuthCallback.tsx
@@ -2,16 +2,18 @@ import {useEffect} from 'react'
import {useNavigation} from '@react-navigation/native'
import {type NavigationProp} from '#/lib/routes/types'
+import {replaceWebLocation} from '#/lib/routes/web'
import {logger} from '#/logger'
import {useSessionApi} from '#/state/session'
import {getWebOAuthClient} from '#/state/session/oauth-web-client'
+import {consumeOAuthReturnUrl} from '#/state/session/oauth-web-return-url'
export function AuthCallback() {
const {login} = useSessionApi()
const navigation = useNavigation()
useEffect(() => {
- ;(async () => {
+ void (async () => {
try {
const client = getWebOAuthClient()
const result = await client.init()
@@ -26,9 +28,18 @@ export function AuthCallback() {
'LoginForm',
)
}
+
+ const returnUrl = consumeOAuthReturnUrl()
+ if (returnUrl) {
+ replaceWebLocation(returnUrl)
+ return
+ }
+
navigation.replace('Home')
- } catch (e: any) {
- logger.error('OAuth callback failed', {error: e.message})
+ } catch (e: unknown) {
+ logger.error('OAuth callback failed', {
+ error: e instanceof Error ? e.message : String(e),
+ })
navigation.replace('Home')
}
})()
diff --git a/src/screens/Login/LoginForm.web.tsx b/src/screens/Login/LoginForm.web.tsx
index c43da6a9b..dad5b6a4c 100644
--- a/src/screens/Login/LoginForm.web.tsx
+++ b/src/screens/Login/LoginForm.web.tsx
@@ -21,6 +21,7 @@ import {logger} from '#/logger'
import {useSetHasCheckedForStarterPack} from '#/state/preferences/used-starter-packs'
import {useSessionApi} from '#/state/session'
import {getWebOAuthClient} from '#/state/session/oauth-web-client'
+import {saveOAuthReturnUrl} from '#/state/session/oauth-web-return-url'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
@@ -204,6 +205,7 @@ function OAuthLoginFields({
setIsProcessing(true)
try {
+ saveOAuthReturnUrl()
const client = getWebOAuthClient()
await client.signIn(identifier)
// Browser will redirect to authorization server
diff --git a/src/state/session/oauth-web-return-url.ts b/src/state/session/oauth-web-return-url.ts
new file mode 100644
index 000000000..d001d0ad8
--- /dev/null
+++ b/src/state/session/oauth-web-return-url.ts
@@ -0,0 +1,25 @@
+const OAUTH_RETURN_URL_KEY = 'oauth_return_url'
+
+export function saveOAuthReturnUrl(url = window.location.href) {
+ if (typeof window === 'undefined') return
+
+ window.sessionStorage.setItem(OAUTH_RETURN_URL_KEY, url)
+}
+
+export function consumeOAuthReturnUrl() {
+ if (typeof window === 'undefined') return undefined
+
+ const savedUrl = window.sessionStorage.getItem(OAUTH_RETURN_URL_KEY)
+ window.sessionStorage.removeItem(OAUTH_RETURN_URL_KEY)
+
+ if (!savedUrl) return undefined
+
+ try {
+ const url = new URL(savedUrl, window.location.origin)
+ if (url.origin !== window.location.origin) return undefined
+ if (url.pathname === '/auth/web/callback') return undefined
+ return `${url.pathname}${url.search}${url.hash}`
+ } catch {
+ return undefined
+ }
+}