I believe a Nuxt.js (Vue.js) web app with Firebase is correctly set up, as I'm able to log in with Firebase/Apple using signInWithPopup.
I have properly set my custom domain in the Auth domain settings. The problem only occurs when signing in with redirect.
Here is my implementation: I click on the "Sign in with Apple" button, which triggers the corresponding function. I am correctly redirected to Apple’s sign-in page. I enter my credentials and am redirected back to the sign-in page. Absolutely nothing happens—no error message, nothing.
The result from getRedirectResult is always null.
I tried moving the getRedirectResult block into onMounted, but it changed nothing.
So, how can I get getRedirectResult to correctly pick up the sign-in process?
<script setup lang="ts">
// Define page meta to use appropriate layout
definePageMeta({
layout: 'web-no-tab-bar'
});
useSeoMeta({
title: 'Sign-In'
});
import { httpsCallable } from 'firebase/functions'
import { GoogleAuthProvider, OAuthProvider, signInWithPopup, updateProfile, getAdditionalUserInfo, signInWithRedirect, getRedirectResult, getAuth } from 'firebase/auth'
import { doc, getDoc, Firestore } from 'firebase/firestore'
// Store instances
const authStore = useAuthStore()
const flashStore = useFlashStore()
// Firebase instances
const { $auth, $firestoreDb, $functionsInstance } = useNuxtApp()
const auth = getAuth();
getRedirectResult(auth)
.then((result) => { //-----------> ALWAYS NULL
// Check if result is not null before processing
if (result) {
alert('result')
const credential = OAuthProvider.credentialFromResult(result);
if (credential) {
// You can also get the Apple OAuth Access and ID Tokens.
const accessToken = credential.accessToken;
const idToken = credential.idToken;
}
// The signed-in user info.
const user = result.user;
}
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
// The email of the user's account used.
const email = error.customData.email;
// The credential that was used.
const credential = OAuthProvider.credentialFromError(error);
// ...
});
/**
* ================================
* Apple Sign-In
* ================================
*/
const signInWithApple = async () => {
try {
const provider = new OAuthProvider('apple.com')
// Configure Apple provider with required scopes
provider.addScope('email')
provider.addScope('name')
const result = await signInWithRedirect($auth, provider)
} catch (err: any) {
// eslint-disable-next-line no-console
console.error('Apple sign-in failed:', err)
flashStore.show(err?.message || 'Apple sign-in failed. Please try again.')
}
}
/**
* ================================
* Providers Sign-In
* ================================
*/
// Verify user profile after authentication. Not for email sign-in. For providers.
const checkUserProfileAfterProvidersSignIn = async (userId: string) => {
try {
const userDoc = await getDoc(doc($firestoreDb as Firestore, 'users', userId))
// If missing username or country, treat as new user
if (!userDoc.exists() || !userDoc.data()?.username || !userDoc.data()?.country) {
navigateTo('/authentication/user-info-collect')
} else {
// Persist user country in localStorage for later use
if (utils.isLocalStorageAvailable()) {
const key = `selectedCountry_${userId}`
window.localStorage.setItem(key, userDoc.data()?.country.toLowerCase())
}
// Redirect back to the page the visitor came from (or home)
const target = utils.isLocalStorageAvailable()
? window.localStorage.getItem('previousUrlForAfterSignIn') || '/'
: '/'
navigateTo(target)
}
} catch (err) {
// eslint-disable-next-line no-console
console.error('Error verifying user profile after Google sign-in:', err)
navigateTo('/')
}
}
// Store previous URL in localStorage for future redirect handling
onMounted(() => {
if (utils.isLocalStorageAvailable()) {
const previousUrl = (window.history.state && window.history.state.back) || document.referrer || '/';
localStorage.setItem('previousUrlForAfterSignIn', previousUrl);
}
});
</script>
The fix had nothing to do with nuxtjs.
It was a problem with "auth:" frontend firebase setting. It was set to auth.mydomain.com. Which caused problem with mobile redirects (worked fine on desktop) since the domain of my app is www.mydomain.com. The subdomain mismatch caused a problem.
Problem: my files are not served from firebase hosting but from cloudflare. If you host you file on firebase the hosting will have the proper files returned when called by the provider.
If hosting your file not on firebase you don't have this luxury.
So from this page : https://firebase.google.com/docs/auth/web/google-signin#redirect-mode
I had to implement solution 3.1. Proxy auth requests to firebaseapp.com
What a nightmare.
I ended up creating a compute worker in cloudflare (not a regular worker - the one i used is free up to 100 000 calls / day):
const FB_HOST = "yourproject-project.firebaseapp.com"; // ← your project
export default {
async fetch(request) {
const url = new URL(request.url);
const needsProxy =
url.pathname.startsWith("/__/auth/") ||
url.pathname.startsWith("/__/firebase/");
if (needsProxy) {
const target = new URL("https://" + FB_HOST + url.pathname + url.search);
const upstreamReq = new Request(target, {
method: request.method,
headers: request.headers,
body: request.method === "GET" || request.method === "HEAD" ? null : request.body,
redirect: "manual",
cache: "no-store",
});
return fetch(upstreamReq); // stream response back unchanged
}
// Everything else → your normal origin / Pages site
return fetch(request);
},
};
You also have to setup for this worker 2 routes:
www.mydomain.com/\_\_/firebase/\*
www.mydomain.com/\_\_/auth/\*
result: when the provider redirects to www.mydomain.com/\_\_/auth/\*, it will in fact be served the specific sign in firebase code from:
yourproject-project.firebaseapp.com
which has the correct files to pick from there the login process.
This works. Everything else FAILED: "Ensure that this forwarding is transparent to the browser; this cannot be done via a 302 Redirect."
This is why I had to go for the worker.