I'm trying to use VueFire's useCurrentUser() function in a Nuxt 3 application without SSR.
I have configured vuefire in nuxt.config.ts as indicated in the documentation.
export default defineNuxtConfig({
modules: ['nuxt-vuefire',],
vuefire: {
config: {
apiKey: '...',
authDomain: '...',
projectId: '...',
appId: '...',
},
},
})
Then in app.vue I use the code as in the documentation:
<script setup>
const router = useRouter()
const route = useRoute()
const user = useCurrentUser()
onMounted(() => {
watch(user, (user, prevUser) => {
if (prevUser && !user) {
// user logged out
router.push('/login')
} else if (user && typeof route.query.redirect === 'string') {
// user logged in
router.push(route.query.redirect)
}
})
})
</script>
Unfortunately, it always gives me the error:
**
[VueFire] useCurrentUser() called before the VueFireAuth module was
added to the VueFire plugin. This will fail in production.
**
Thank you in advance for your help
Related
I am currently working on a project using iron-session and next.js. I don't lose my user on clicking Link tags. But if I refresh user becomes undefined. Cookie is set and doesn't get deleted on refresh. I don't know what is wrong.
Here is my login.ts code:
export default withIronSessionApiRoute(loginRoute, sessionOptions);
async function loginRoute(req: NextApiRequest, res: NextApiResponse) {
try {
const {
data: {tcId, admin, userName},
} = await axios('http://localhost:8080/user/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
data: JSON.stringify(req.body),
});
const user = {tcId: tcId, userName: userName, admin: admin} as User;
req.session.user = user;
await req.session.save();
res.json(user);
} catch (error) {
res.status(500).json({message: (error as Error).message})
}}
Here is my session.ts code:
// this file is a wrapper with defaults to be used in both API routes and `getServerSideProps` functions
import type { IronSessionOptions } from 'iron-session'
import type { User } from '../pages/api/user'
export const sessionOptions: IronSessionOptions = {
password: process.env.SECRET_COOKIE_PASSWORD as string,
cookieName: 'eys-cookie',
// secure: true should be used in production (HTTPS) but can't be used in development (HTTP)
cookieOptions: {
secure: process.env.NODE_ENV === 'production',
},
};
// This is where we specify the typings of req.session.*
declare module 'iron-session' {
interface IronSessionData {
user?: User
}
}
As I said previously. I don't lose my user. While routing around using Link tags from next.
Refreshing causes to lose my user. Also other tabs don't reach my user.
I can show more code if wanted. But I think problem is here.
I had a similar issue and solved the tab switching by setting:
revalidateOnFocus = false,
for the useSWR function
sample
const fetcher = (url: any) => fetch(url).then((res) => res.json());
const options = {
revalidateOnFocus: false,
};
const {
data: session,
error,
mutate: mutateUser,
} = useSWR<Session>("/api/session", fetcher, options);
you can also explore other options here https://swr.vercel.app/docs/options
Probably you forgot to add SWRconfig on the index or app component:
import { AppProps } from 'next/app'
import { SWRConfig } from 'swr'
import fetchJson from 'lib/fetchJson'
function MyApp({ Component, pageProps }: AppProps) {
return (
<SWRConfig
value={{
fetcher: fetchJson,
onError: (err) => {
console.error(err)
},
}}
>
<Component {...pageProps} />
</SWRConfig>
)
}
export default MyApp
I can't get data from firebase. Firebase.js is using for initialization of firebase and in App.js I am trying to get and work with it.
Now when I'm trying to get data and display it in browser, I see just blank page. Looks like I didn't get any data.
In some reasons I even can't console.log from stocksRef.on('value', (dataSnapshot) and I can't check what data I got and did I get it.
Please, help me to fix it.
App.js
class StocksList extends Component {
constructor(props){
super(props);
this.state = {
stocks: []
}
}
componentDidMount() {
const stocksRef = firebase.database().ref('list');
console.log('popopok', stocksRef)
stocksRef.on('value', (dataSnapshot) => {
let list = dataSnapshot.val();
this.setState({
stocks: Object.values(list)
})
})
}
render() {
return (
<div>
{this.state.stocks.map((item) => {
return (
<div>
<p>ISIN: {item.isin}</p>
<p>issuer: {item.issuer}</p>
<p>issuerCode: {item.issuerCode}</p>
<p>ISIN: {item.isin}</p>
<p>nominal: {item.nominal} {item.currency}</p>
<p>form: {item.form}</p>
<p>vyd: {item.vyd}</p>
</div>
)
})}
</div>
)
}
}
export default StocksList;
firebase.js
import firebase from 'firebase'
let config = {
apiKey: ******,
authDomain: ******,
databaseURL: ******,
projectId: ******,
storageBucket: ******,
messagingSenderId: ******,
appId: ******
};
firebase.initializeApp(config);
export default firebase;
You need to make access permission rules at firebase console.
As far as I know you need to make some rules for Access data in firebase real-time-database.
And If you want to know about firebase permission rule, just read my reference
You can check it with next code's error
try{
stocksRef.on('value', (dataSnapshot) => {
let list = dataSnapshot.val();
this.setState({
stocks: Object.values(list)
})
})
} catch(error) {
console.log(error);
}
Reference
Database rules - Firebase Documents
Try like this
async componentDidMount() {
const stocksRef = await firebase.database().ref('list');
console.log('popopok', stocksRef)
stocksRef.on('value', (dataSnapshot) => {
let list = dataSnapshot.val();
this.setState({
stocks: Object.values(list)
})
})
}
I am importing 'firebaseApp' from a file where I have done all the setup of firebase and I have implemented email, google and Facebook authentication but when I am implementing the phone number auth the ReCaptcha is not a constructor I am using ReactJs functional component.
Is there any way of implementing phone number auth without ReCaptcha or if not how can I fix the error.
Setup of firebase
import firebase from 'firebase/app';
import 'firebase/auth'
import 'firebase/firestore';
// Web app's Firebase configuration
var firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: ""
};
// Initialize Firebase
export const firebaseApp = firebase.initializeApp(firebaseConfig);
export const auth = firebase.auth();
export const db = firebase.firestore();
export const google_provider = new firebase.auth.GoogleAuthProvider();
export const facebook_provider = new firebase.auth.FacebookAuthProvider();
This is the place I am taking the number as user input and sending the OTP for verification but the sample code number is hardcoded.
import { firebaseApp, auth } from '../../../firebase/firebasesetup'
function Form() {
const setuprecaptcha = () => {
window.recaptchaVerifier = new firebaseApp.auth.RecaptchaVerifier('recaptcha-container',
{
'size': 'invisible',
'callback': function (response) {
console.log("captcha resolved");
// sendsms();
}
});
}
const sendsms = () => {
setuprecaptcha();
var phoneNumber = '+918220310506';
var appVerifier = window.recaptchaVerifier;
auth.signInWithPhoneNumber(phoneNumber, appVerifier)
.then(function (confirmationResult) {
window.confirmationResult = confirmationResult;
}).catch(function (error) {
alert("not sent")
});
}
return (
<input type="text" placeholder="Mobile" value={mob}
onChange={e => setMob(e.target.value)} />
<div id="recaptcha-container"></div>
<button onClick={sendsms} id='sign-in-button'>Send otp</button>
)
}
export default Form
Ok, so I am answering My own question. This kind of looks Weird but still if anyone of you faces the same problem as mine.
2 things I need to solve in the firebase_setup file and add the main function in React functional component. (Total 3 updates)
firebase_setup file
first
import firebase from 'firebase'; and not import firebase from 'firebase/app';
second
firebase.initializeApp(firebaseConfig); export const firebaseApp = firebase
React functional component
import { firebaseApp} from './firebase_setup';
const sendsms = () => {
//If you want to make the recaptcha invisible
var recaptcha = new firebaseApp.auth.RecaptchaVerifier('recaptcha-container', {
'size': 'invisible'
});
//If you want to make the recaptcha visible
var recaptcha = new firebaseApp.auth.RecaptchaVerifier('recaptcha-container');
//Your phone number with the country code
var number = '+**********';
//actual code begins here
auth.signInWithPhoneNumber(number, recaptcha).then(function (e) {
var code = prompt("enter the code sent to your mobile number");
if (code === null) return;
e.confirm(code).then(function (result) {
alert(result.user + ' verified ')
}).catch(function (error) {
alert('Could not verify,Please try again');
});
}).catch(function (error) {
alert('Please try again.We were unable to reach your phone.Select the correct code and the phone number');
});
}
I want to reload or trigger some event in foregrounf if push message is sent with firebase.messaging().onMessage, but it not fired. I'm using firebase.mesaging.sw.js with background notification and it works correctly what is wrong with my code?
firebase.js
const config = {
apiKey: "x",
projectId: "x",
storageBucket: "x",
messagingSenderId: "x"
};
firebase.initializeApp(config);
const msg = firebase.messaging()
msg.requestPermission()
.then(() => {
return msg.getToken()
})
.then((token) => {
})
.catch((err) => {
})
msg.onMessage(function(payload) {
alert("Foreground message fired!")
console.log(payload)
});
firebase.messaging.sw.js
importScripts("https://www.gstatic.com/firebasejs/7.0.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/7.0.0/firebase-messaging.js");
const config = {
apiKey: "x",
projectId: "x",
storageBucket: 'x',
messagingSenderId: "x"
};
firebase.initializeApp(config);
const msg = firebase.messaging()
msg.setBackgroundMessageHandler(function(payload) {
let options = {
body: payload.data.body,
icon: payload.data.icon
}
return self.registration.showNotification(payload.data.title, options);
});
I don't know what is wrong with my code
Simple solution to this is update your Firebse to latest version.
Eg.
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');
Note: Once you have updated your firebase libraries versions then messagingSenderId will not work in your firebase-messaging-sw.js file. You have to provide all other params eg. apiKey, projectId, appId along with messagingSenderId.
If still not work. Clean your browser cache and re-register service worker.
For more details you can refer to this solution
Still had the same issue in 2020. In my case it was like this:
you need to have same versions in importScripts for background messages and in your app for foreground messages
call it after obtaining token for background service
firebaseApp.messaging().getToken().then((currentToken) => {
if (currentToken) {
console.log(currentToken)
} else {
// Show permission request.
console.log(
'No Instance ID token available. Request permission to generate one.')
}
/** When app is active */
firebase.messaging().onMessage((payload) => {
console.log(payload)
}, e => {
console.log(e)
})
})
For anyone else with this problem, I finally solved it by:
Upgrading the Firebase SDK version in both header-included JS files and the SW JS file to latest (currently, that would be 7.8.1).
Adding the entire firebaseConfig array to the SW firebase.initializeApp(), as the previous answer suggests.
Cleaning the Chrome cache from the Application > Clear Storage section in the Developer Tools.
Deleting the previous registration token from my database.
Blocking and unblocking notifications from the browser to force a new token generation.
Basically, a total fresh start with updated Firebase SDK seems to fix issues like this.
You are missing lots of things and onMessage will only work if firebase is initialized before calling it. Please follow this. I have done it like this and it is working.
initialize firebase and get the token
export class BrowserFcmProvider {
export const FIREBASE_CONFIG = {
apiKey: "****",
authDomain: "****",
databaseURL: "****",
projectId: "****",
storageBucket: "****",
messagingSenderId: "****",
appId: "****"
}
firebase.initializeApp(FIREBASE_CONFIG);
async webGetToken() {
try {
const messaging = firebase.messaging();
await messaging.requestPermission();
const token = await messaging.getToken();
let uuidTemp = new DeviceUUID().get();
return this.saveTokenToFireStoreFromWeb(token, uuidTemp)
} catch (e) {
console.log(e);
}
}
saveTokenToFireStoreFromWeb(token, uuid) {
try {
const docData = {
token: token,
device_type: 'web',
uuid: uuid
}
const devicesRef = this.db.collection('devices')
return devicesRef.doc(uuid).set(docData);
} catch (e) {
console.log(e, 'saveTokenError');
}
}
showMessage() {
try {
const messaging = firebase.messaging();
messaging.onMessage((payload) => {
console.log(payload);
})
} catch (e) {
console.log(e)
}
}
}
And calling the method while app loads like this
async configureFirebaseForBrowser(res) {
await this.bfcm.webGetToken();
this.bfcm.showMessage();
}
Firebase function and payload type
const payloadWeb = {
title: title,
body: body,
data: {
title: title,
body: body
},
tokens: uniqueDevicesTokenArrayWeb,
}
const responseWeb = await admin.messaging().sendMulticast(payloadWeb);
console.log(responseWeb.successCount + ' notifications has been sent to Web successfully');
I have used async and await as we need to manage firebase/firestore operations asynchronously.
fcm does not work in Incognito mode and safari browser
Same issue i was faced. In my case firebase version in "package.json" and "firebase-messaging-sw.js" importScripts version was different. After set same version in "firebase-messaging-sw.js" importScripts which was in
"package.json", my issue is resolved.
Before change
**"package.json"**
"firebase": "^8.2.1",
**"firebase-messaging-sw.js"**
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js');
After change
**"package.json"**
"firebase": "^8.2.1",
**"firebase-messaging-sw.js"**
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.1/firebase-messaging.js');
I have a component with a form that holds the email and password. Imports at the top:
import Component from '#ember/component';
import { inject as service } from '#ember/service';
import { computed } from '#ember/object';
import * as firebase from 'firebase';
Next, I inject the service for the firebaseApp and session (session just has some attrs that I set to tell the app we're authenticated -- these will be refactored later):
session: service(),
firebaseApp: service(),
If I pass these values into the signInWithEmailAndPassword() function from fbApp.auth(), the account is validated and logged in. Works as expected:
login() {
const session = this.get('session');
const fbApp = this.get('firebaseApp');
const e = this.get('form.email');
const p = this.get('form.password');
fbApp.auth().signInWithEmailAndPassword(e, p).then(u => {
session.set('user.email', u.email);
session.set('user.signedIn', true);
this.get('goHome')(); // route transition to home
}).catch(e => {
this.set('error', 'Something went wrong. Try again?');
});
}
Next, I wanted to persist the session so that the user is not logged out on refresh, only if the tab is closed. So I modified the code and wrapped the signInWithEmailAndPassword in with setPersistence as follows:
login() {
const session = this.get('session');
const fbApp = this.get('firebaseApp');
const e = this.get('form.email');
const p = this.get('form.password');
fbApp.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION)
.then(()=> {
fbApp.auth().signInWithEmailAndPassword(e, p).then(u => {
session.set('user.email', u.email);
session.set('user.signedIn', true);
this.get('goHome')(); // route transition to home
}).catch(e => {
this.set('error', 'Something went wrong. Try again?');
});
}).catch(e => {
this.set('error', 'Something went wrong. Try again?');
});
}
This doesn't work. I get a Cannot read property 'SESSION' of undefined error in the console. I'm sure it has to do with how firebase is imported but I'm having trouble with it.
This question is very similar to the one I answered here on how to import Material Components Web JavaScript file.
Luckily, I been using Firebase and Firebase Auth in my Ambitious EmberJS project for about a year now. The process is dead simple, complete working example below.
In package.json
....
"devDependencies": {
"firebase": "^5.5.8",
....
In ember-cli-build.js
....
let app = new EmberApp(defaults, {
....
fingerprint: {
enabled: true,
generateAssetMap: true,
exclude: [
'firebase-app',
'firebase-auth',
'firebase-messaging',
'firebase-messaging-sw',
....
]
},
....
});
....
app.import('node_modules/firebase/firebase-app.js', { outputFile: 'firebase-app.js'});
app.import('node_modules/firebase/firebase-auth.js', { outputFile: 'firebase-auth.js'});
app.import('node_modules/firebase/firebase-messaging.js', { outputFile: 'firebase-messaging.js'});
....
In index.html before vendor.js and app.js files
....
<script src="/firebase-app.js"></script>
<script src="/firebase-auth.js"></script>
<script src="/firebase-messaging.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: "ABC123XYZ",
authDomain: "auth.my-app.com", // Did you know you can customize this or use default my-app.firebaseapp.com
databaseURL: "https://my-app.firebaseio.com",
projectId: "my-app",
storageBucket: "app.appspot.com",
messagingSenderId: "123456789"
};
if( typeof firebase !== 'undefined' && firebase) {
firebase.initializeApp(config);
}
</script>
....
In .eslintrc.js
....
module.exports = {
....
env: {
browser: true
},
globals: {
"firebase": false
},
....
};
....
Then anywhere but not in Fastboot (if using it) just called firebase methods and properties.e.g
....
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
user.getIdTokenResult()
.then((idTokenResult) => {
session.setToken(idTokenResult.token);
if (idTokenResult.claims.admin) {
session.setIsAdmin(true);
} else {
session.setIsAdmin(false);
}
session.setUser(user);
session.setIsAuthenticated(true);
})
.catch((error) => {
console.log(error);
});
} else {
// User is signed out.
// ...
}
});
....
Enjoy!