User is not returned from login and app.currentUser is an empty object - Mongo Realm Sync - realm

I couldn't find a similar question so I will ask here:
I'm using the Realm library and the react-native SDK to build an app.
I started by running the example app https://github.com/mongodb-university/realm-tutorial-react-native
I can start the app in xcode, login, and register, and even add a task, but every time I try to get the current user that is signed to the app it gives me an empty object.
For example I have tried to log the user (code is taken from the repo mentioned above - Auth Provider):
const signIn = async (email, password) => {
const creds = Realm.Credentials.emailPassword(email, password);
const newUser = await app.logIn(creds);
console.log('====', { newUser, creds, app: app.currentUser });
setUser(newUser);
};
The log I get is: LOG ==== {"app": {}, "creds": {}, "newUser": {}}
As I mentioned the app is WORKING and I can see the users and tasks added OK on the Realm UI app. What am I missing? How can I get the user?
(I would like to save it in a secured storage and in the app state to change the screens depending on the auth state of the user)

Related

Debugging discrepancy between authentication in firebase app and rules

I'm developing an app using Firebase Auth and Firestore.
I have the current code to create a game document:
export const createGame = async () => {
const title = makeid(6);
const myDoc = doc(db, "rides", title);
const payload = {
createdBy: auth.currentUser.uid
};
console.log(title, payload, auth.currentUser);
await setDoc(myDoc, payload);
return title;
};
This results in the following being printed to the console:
5YTm0R {createdBy: 'pLCzrgwSQSa9KxaW5OlU2l18CGY2'} UserImpl {providerId: 'firebase', proactiveRefresh: ProactiveRefresh, reloadUserInfo: {…}, reloadListener: null, uid: 'pLCzrgwSQSa9KxaW5OlU2l18CGY2', …}
As you can see from the log, the current user exists. It is an anonymous user, so isAnonymous is true when you expand the object.
However, the request fails, and when I look at the emulator's console, I see the following image:
The current user is being shown as null in the Firebase Emulator console whereas it is non-null in the application.
I'm wondering if there's a particular set of steps I need to take for Firestore to use the current user's authentication when making a request? Thanks!
Posting as community wiki:
As per #mikesol, the issue was resolved by upgrading to the newest Firebase version.
npm i firebase#latest

What Sign in method to use best?

We are having a flutter app (ios, android, web), where users are signed in via username & password.
We are also using google firebase since its powerful and easy to integrate.
The username and password mainly belongs to the website where we are gathering data at. (As example - If they use the website without the app, and they change the password, after that he wont be able to login to the app)
Now the mentionned websites host is giving us API access, login via OpenId to get the access token for the API. Because we are a safety risk since we store the passwort of the users too!
For the API access we dont really need to store Username and password of the user, since they are redundant anyway. But if we want to add a feature (for example message sending or further data storage) we need to have the user signed in into firebase.
Upt to now we are using for (first) signin the following snippet:
firebaseAuth.createUserWithEmailAndPassword(
email: email, password: password);
and for already signed in users :
firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
Notice that similar credentials are also using to login on the API. (Since the user is there already registered)
How can we login on firebase with said information without asking twice for a password ond username (once for us, and once for the API) ?
We already tried :
await firebaseAuth.signInWithCustomToken(token)
with the jwl token from the OpenId, of course it did not work because the token did not contain the uid reference.
SOLUTION
Create a Firebase Cloud Function just like described in Firebase Cloud Functions.
Be aware that if you want to create a customtoken, the cloud functions need rights. On initializeApp(..)
admin.initializeApp({
serviceAccountId: '{App_Name}#appspot.gserviceaccount.com',
});
So the correct service account has to be selected, you also have to give him the rights to generate tokens. (See => Stackoverflow Question
The Cloud Function does then look the following way :
export const functionName= functions.https.onRequest(async (request, response) => {
const id = request.query.id;
const passcode = request.query.passcode; // not really needed
// add other passcodes for different authentications
if (passcode == "{COMPARE SOMETHING}") {
await admin.auth().createCustomToken(id).then((customToken) => {
response.status(200).send({
'id': id,
'customToken': customToken
});
}).catch((error) => {
response.status(500).send({
'ErrorMessage': "No token could be generated",
"Error": error
});
});
}
else {
response.status(500).send({
'ErrorMessage': "Passcode wrong"
});
}
});
On the other hand we have the code on the mobile app :
// Get JWT Token
Map<String, dynamic> jwtpayload =
Jwt.parseJwt(response_decoded['id_token']); // use import 'package:jwt_decode/jwt_decode.dart';
final queryParameters = {
'id': jwtpayload ['sub'],
'passcode': 'APassCode',
};
final uri = Uri.https('us-central1-{yourApp}.cloudfunctions.net',
'/{functionName}', queryParameters);
final cloud_function_api_call = await client.post(uri);
var decoded_cloud_function_api_call =
jsonDecode(cloud_function_api_call.body);
And at the end :
await firebaseAuth.signInWithCustomToken(
decoded_cloud_function_api_call['customToken']);
I hope it helps others facing a similar issue.

problem firebase.auth.Auth.Persistence.LOCAL

Hi every one I want to set Auth state persistence on firebase to local i'm working on flutter and I don't know how to do that
I found this on firebase web site
import { getAuth, setPersistence, signInWithEmailAndPassword, browserSessionPersistence } from "firebase/auth";
const auth = getAuth();
setPersistence(auth, browserSessionPersistence)
.then(() => {
// Existing and future Auth states are now persisted in the current
// session only. Closing the window would clear any existing state even
// if a user forgets to sign out.
// ...
// New sign-in will be persisted with session persistence.
return signInWithEmailAndPassword(auth, email, password);
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
});
but not sure how I do that on flutter if any one can help with that
As per the FlutterFire documentation
On native platforms such as Android & iOS, this behavior is not configurable and the user's authentication state will be persisted on-device between app restarts. The user can clear the apps cached data via the device settings which will wipe any existing state being stored.
If you're using Flutter for a web app, by default the auth state is stored in local storage. If you want to change this to session based or no persistence you would set that like this:
// Disable persistence on web platforms
await FirebaseAuth.instance.setPersistence(Persistence.NONE);

Firebase signInWithCredentials from Microsoft Azure

Normally, I'd use the firebase.auth.OAuthProvider('microsoft.com') and pass it to firebase.auth().signInWithPopup() but in my case I need to log into Microsoft first using their library and pass the credentials back to firebase. (why? because I need their accessToken/refreshToken handling which isn't done by firebase).
Anyway, I can't seem to find a way to take the microsoft-supplied credentials and pass them successfully back to firebase...
here's what's not working for me:
export async function msLogin() {
const userAgent = new MSAL.UserAgentApplication({ auth: { clientId: CLIENT_ID, } });
const auth = await userAgent.loginPopup({ scopes: ['profile'] });
const provider = new firebase.auth.OAuthProvider('microsoft.com');
const idToken = auth.idToken.rawIdToken;
const credential = provider.credential(idToken);
await firebase.auth().signInWithCredential(credential); // **** THIS FAILS
// ... with "Invalid IdP response/credential: http://localhost?id_token=eyJ0eXAiO...0e9BeTObQ&providerId=microsoft.com"
The microsoft popup part works great and I'm logged in successfully there and able to issue API calls. But I can't get firebase to accept those credentials to log in on firebase. I've enabled the Microsoft OAuth provider in the Firebase Authentication panel and I'm sure the CLIENT_ID's match...
Maybe I'm constructing the OAuthCredential wrong?
Help greatly appreciated!
ps: this is a continuation of this SO post.

one of the firebase realtime database instance not authenticated when initialized for multiple database in web javascript

in web i have firebase project with two database instances in the same project / app
after successful login with firebase auth;
the second database reference seems to be non authenticated and thus the database access fail; with auth != null in rules.
if i replace the second database url in config object and put default database url in config2 the second database than starts to work fine authenticated but old database fails with database access rule auth != null
How can i use both database in web javascript code without anyone having the above issue ?
Is the initialisation done correctly ?
Thanks in Advance
Should be documented properly in firebase documentation for Auth in web
but unfortunately its not for this question.
So the firebase auth instances are maintained separately including the auth callback
So i had to do like bellow
await firebase.auth().signInWithEmailAndPassword(_ths.form.email, _ths.form.password);
await firebase.app('app2').auth().signInWithEmailAndPassword(_ths.form.email, _ths.form.password);
let authPromises = [];
authPromises.push(new Promise((resolve,reject)=>{
firebase.auth().onAuthStateChanged(function (user) {
if (user) resolve(user);
});
}));
authPromises.push(new Promise((resolve,reject)=>{
firebase.app('app2').auth().onAuthStateChanged(function (user) {
if (user) resolve(user);
});
}));
Promise.all(authPromises).then(async(users)=>{
// ....
let oldDbInstance = firebase.database();
let newDbInstance = firebase.database(app2);
});
Phew!!!

Resources