How to check whether a user has already signed up using Phone Number before send otp - react-native

check phone number whether it exist if exist error and check before otp
signIn() {
this.setState({ waiting: true });
firebase
.auth()
.signInWithPhoneNumber(this.state.phoneNumber)
//if phone number is right, then update phone in store and call verify code screen
.then(res => {
Store.currentUserPhone = this.state.phoneNumber;
Actions.VerifyCode({ result: res });
})
.catch(error => this.setState({ error: error.message, waiting: false
}));
}

you can check the user auth object whether there's a phoneNumber value with
const userAuth = firebase.auth().currentUser;
if(userAuth.phoneNumber !== undefined) {
//user has phone number
}else {
//user does not have phone number
}

Related

React Native Google Sign In User Birthday Access Problem

I am trying to get user birthday when user is registered with Google Sign In and want to display his/her info in the profile page.
Google Sign In was implemented via firebase.
And then, I went to google developer console and made
Added People Apis and then go to OAuth consent screen
Select External
Added App domain, Authorized domains, Developer contact information
Added birthday scope
Added test users
Save and Back to Dashboard
Birthday info is set as public
The problem is still my test users cannot login to Google. It says "Access Denied. your app did not complete the google verification process. The app is currently being tested. Only approved test users can access the app."
I can only login with my developer account.
And when I logged in, in the console, I can see the birthday scope is added in scopes array. However the birthday info is still not in my user object.
I use "#react-native-google-signin/google-signin": "^6.0.1" package.
Can someone help me please ?
Do I need to verify the domain/owner to be able to see birthday info ?
Or the package does not support this info ?
Why my test users cannot login even though I added them ?
My code is below
export const auth = {
initGoogleSignIn: function () {
GoogleSignin.configure({
scopes: [
'https://www.googleapis.com/auth/user.birthday.read',
'https://www.googleapis.com/auth/user.gender.read',
'https://www.googleapis.com/auth/plus.login',
],
// scopes: ['https://www.googleapis.com/auth/plus.login'],
webClientId: Config.GOOGLE_WEB_CLIENT_ID,
offlineAccess: false,
});
},
};
import auth from '#react-native-firebase/auth';
export const googleLogin = () => {
return async dispatch => {
try {
await GoogleSignin.hasPlayServices({showPlayServicesUpdateDialog: true});
const isSignedIn = await GoogleSignin.isSignedIn();
if (isSignedIn && Platform.OS === 'android') {
await GoogleSignin.revokeAccess();
}
const {idToken} = await GoogleSignin.signIn();
const token = await GoogleSignin.getTokens();
dispatch(handleSocialSignup(COMMON.GOOGLE, token?.accessToken));
// Create a Google credential with the token
const googleCredential = auth.GoogleAuthProvider.credential(idToken);
// Sign-in the user with the credential
const userSignIn = auth().signInWithCredential(googleCredential);
Alert.alert(JSON.stringify(userSignIn));
userSignIn.then(user => Alert.alert(user)).catch(err => console.log(err));
} catch (error) {
if (error.code === statusCodes.SIGN_IN_CANCELLED) {
console.log('Cancelled by user');
} else if (error.code === statusCodes.IN_PROGRESS) {
// operation (e.g. sign in) is in progress already
} else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
// play services not available or outdated
} else {
Sentry.captureException(error);
Sentry.captureMessage(strings.common.undefinedError);
console.log('some other error happened', error);
dispatch(showSnackbar(strings.common.undefinedError));
}
return false;
}
const [googleUserName, setGoogleUserName] = useState('');
const getGoogleUserName = async () => {
const currentUser = await GoogleSignin.getCurrentUser();
setGoogleUserName(currentUser);
console.log('currentUser', currentUser);
};
useEffect(() => {
getGoogleUserName();
}, []);
console.log('googleUserName', googleUserName);

Login With React Native using Asyncronous storage

I am implementing login in React Native using Asynchronous storage. Here, when users login successfully, i keep the user object in the Asynchronous storage then i access this information to get the Authentication Key for my API request anytime I want to do a request.
When I login and information is stored in the Asynchronous storage, the current app session fails to get the just stored information hence all my authenticated request fails in this session. When I close the app and restart, I can successfully get the information from the Async storage stored in the previous session and make successful authenticated request.
I do not know what I am missing out in my code as I believe I need to refresh or reload the app internally after a successful login but I do not know how to do this in React Native. Any information or help is needed. Here is my Login code.
HttpRequest.post('api/login', body)
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.succcode == 201){ //successful login
var data = responseJson.user;
data.loggedIn = true;
AsyncStorage.setItem(USER_DATA, JSON.stringify(data)).then(val => {
console.log('just before reload in login')
Actions.menu(); //this solves the after login problem as it goes to the next page only after a successful AsyncStorage save
this.setState({ procesing: false });
})
.catch(err => {
this.setState({ procesing: false, error: "Couldn't log you in! Please try again" });
//console.log("\nCouldn't save to AsyncStorage: " + err + "\n");
});
}
else{
this.setState({ procesing: false, error: "Wrong Username and/or Password! Please try again" });
}
After I have login, my request looks like ;
//for making a post request
post: (url,body) => {
return fetch(url+'?access-token='+this.state.user.auth_key, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
//'Autorization': 'Bearer token2'
},
})
but the user object is gotten from the Async storage as
getUser(){
return AsyncStorage.getItem("USER_DATA").then(value => {
if(JSON.parse(value) == null) {
return false;
} else {
return JSON.parse(value)
}
});
},
Any Information, Ideas, proposed solutions are highly welcome
If you are receiving the information correctly, you can pass the information to the next screen or use the asynchronous repository as it is now.
If use navigation
HttpRequest.post('api/login', body)
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.succcode == 201){ //successful login
var data = responseJson.user;
data.loggedIn = true;
this.setState({ procesing: false });
this.navigation.navigate("LoginScreen",{data: JSON.stringify(data) })
}
else{
this.setState({ procesing: false, error: "Wrong Username and/or Password! Please try again" });
}
LoginScreen
this.state={
data : this.props.navigation.state.params.data
}
If use AsyncStorge
HttpRequest.post('api/login', body)
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.succcode == 201){ //successful login
var data = responseJson.user;
data.loggedIn = true;
AsyncStorage.setItem("USER_DATA", JSON.stringify(data));
this.setState({ procesing: false });
else{
this.setState({ procesing: false, error: "Wrong Username and/or Password! Please try again" });
}
LoginScreen
async componentDidMount() {
let data = await AsyncStorage.getItem("USER_DATA")
}

How to insert data in firebase using expo..?

I've an issue, actually I want to insert data into firebase using expo from different screen(I'm using google auth in another screen and after completing it I'm going to main screen), it's working also but it is not saving data in which table I want it to store(after google auth, I'm saving data into firebase in 'users')..
// I'm using this code to insert data in first place (while login)
// and I'm also using isUserNew() method and it's working really fine..
onSignIn = googleUser => {
console.log('Google Auth Response', googleUser);
// We need to register an Observer on Firebase Auth to make sure auth is initialized.
var unsubscribe = firebase.auth().onAuthStateChanged(function(firebaseUser) {
unsubscribe();
// Check if we are already signed-in Firebase with the correct user.
if (!this.isUserEqual(googleUser, firebaseUser)) {
// Build Firebase credential with the Google ID token.
var credential = firebase.auth.GoogleAuthProvider.credential(
googleUser.idToken,
googleUser.accessToken
);
// Sign in with credential from the Google user.
firebase.auth().signInAndRetrieveDataWithCredential(credential).then(function(result) {
console.log('user signed in');
if(result.additionalUserInfo.isNewUser){
firebase.database().ref('/users/' + result.user.uid).set({
gmail: result.user.email,
profile_picture: result.additionalUserInfo.profile.picture,
locale: result.additionalUserInfo.profile.locale,
first_name: result.additionalUserInfo.profile.given_name,
last_name: result.additionalUserInfo.profile.family_name,
created_at: Date.now()
}).then(function (snapshot){
// console.log('Snapshot', snapshot);
});
}else{
firebase.database().ref('/users/' + result.user.uid).update({
last_logged_in: Date.now()
});
}
}).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
} else {
console.log('User already signed-in Firebase.');
}
}.bind(this));
};
// This code is also showing an error that I can't call setState from an //unmounted component.
// :- this function as well update() in firebase is in another screen or page.
async componentDidMount() {
try {
let {status} = await Permissions.getAsync(Permissions.LOCATION);
if(status !== 'granted'){
const {status} = await Permissions.askAsync(Permissions.LOCATION);
}else{
const watchId = navigator.geolocation.watchPosition(
({ coords : {latitude, longitude} }) => this.setState({latitude, longitude}, () => console.log('State:', this.state)),
(error) => this.setState({ error: error.message }),
{ enableHighAccuracy: true, timeout: 0, maximumAge: 1000, distanceFilter: 1},
);
await AsyncStorage.setItem('LiveFeedId', JSON.stringify(watchId));
}
}
catch(err) {
console.error(error);
}
};
/* when I'm using this code it's saving the data but not in 'users' table in firebase */
firebase.database().ref('users/').update({
latitude: latitude,
longitude: longitude,
});
Can anyone please help me out here, I'm really new to react native..
And I want to update my latitude and longitude from another screen to firebase where I've saved my users details, ex:- 'firebase.database().ref('/users/' + result.user.uid)'..
Thanks

How to show amount of times user has logged in using AsyncStorage

I am currently attempting to show a full log of how many times a user has logged in using AsyncStorage.
This is because I want to show a pop-up modal when the user logs in for the first time.
Is there a way to achieve this?
Previously, I have been able to show the user details in the console.log, which shows the email and password in a string format.
However, I am unsure on were to go to from there. Would a for loop be the appropriate solution, or is there a method that is already achieves this?
LOGIN SCREEN -
_loginUser = async () => {
const { password, email } = this.state;
if(email == '' || password == '') {
alert('Please enter all fields');
}
else {
//save data using AsyncStorage
let loginArray = {
email: email,
password: password
}
//key of the item to set
AsyncStorage.setItem('loginArray',
JSON.stringify(loginArray));
console.log(loginArray);
// const logsInfo = await AsyncStorage.getAllKeys('loginArray');
// console.log(this.setState({ logs: logsInfo }));
this.setState({
loading: true
});
this._signInAsync();
}
}
_signInAsync = async () => {
setTimeout(() => {
this.setState({
loading: false,
});
this.props.navigation.navigate("App");
}, 2000);
};
HOMESCREEN -
fetchAllItems = async () => {
try {
const keys = await AsyncStorage.getAllKeys()
const items = await AsyncStorage.multiGet(keys)
this.setState({ userCredentials: items })
Reactotron.log(this.state.userCredentials);
} catch (error) {
console.log(error, "problemo")
}
}
I think you want to know how many times a user logged in your App?
For that you can keep a counter in AsyncStorage.
In LOGIN SCREEN -,
...
// Count of last logged in
let count = 0
try {
const value = await AsyncStorage.getItem("COUNTER");
if (value !== null) {
// We have counter!!
count = parseInt(value) + 1
}
} catch (error) {
// Error retrieving data, ie. count = 0
}
let loginArray = {
email: email,
password: password,
counter: count
};
//key of the item to set
AsyncStorage.setItem("loginArray", JSON.stringify(loginArray));
AsyncStorage.setItem("COUNTER", JSON.stringify(count));
console.log(loginArray);
...
And in HOMESCREEN -,
You will get the total count in AsyncStorage.
...
//Here you will get the cont
const items = await AsyncStorage.getItem("loginArray")
this.setState({ userCredentials: items })
...
items contain 'email', 'password' and 'counter'.

Passport middleware, check if the user already has a living session from

I am building a web application using angular-fullstack. The stack is using express-sessions for session storage (in Mongodb) and passport.js for authentication.
I want to limit each user to a single login session. I am trying find a way to check if a user already has a living session when they login.
Is there a way to programmatically call a route to query mongodb from the passport middleware?
'use strict';
import path from 'path';
import passport from 'passport';
import {Strategy as LocalStrategy} from 'passport-local';
import express from 'express';
import session from 'express-session';
import _ from 'lodash';
import Session from '../../api/session/session.model';
var app = express();
require('run-middleware')(app);
function localAuthenticate(User, email, password, done, req) {
User.findOne({
email: email.toLowerCase()
}).exec()
.then(user => {
if (!user) {
return done(null, false, {
message: 'This email is not registered.'
});
}
// HERE is where I am trying to check if a user
// already has a living session when they login
// I tried to use the runMiddleware
// to query mongodb for all the existing sessions
// but I get this error: http://pastebin.com/YTeu5AwA
app.runMiddleware('/sessions',{},function(code,data){
console.log(code) // 200
console.log(data) // { user: '20', name: 'Moyshale' }
});
// Is there a way to access and use an existing route?
user.authenticate(password, function(authError, authenticated) {
if (authError) {
return done(authError);
}
if (!authenticated) {
return done(null, false, { message: 'This password is not correct.' });
} else {
return done(null, user);
}
});
})
.catch(err => done(err));
}
export function setup(User, config) {
passport.use(new LocalStrategy({
passReqToCallback: true,
usernameField: 'email',
passwordField: 'password' // this is the virtual field on the model
}, function(req, email, password, done) {
return localAuthenticate(User, email, password, done, req);
}));
}
Ok, I figured it out and I'll try and explain what I did. My specific implementation required me to set up user 'seats', where each user is part of a group and each group is limited in N number of logins at a single time.
As I mentioned in the question, I am using the angular fullstack yeoman generator, so this solution is specific to that setup.
I created a 'sessions' API endpoint so that I could query and modify the sessions stored in the mongo db. I included a 'seat' record with type Number into the sessions model. This is used to keep track of the users seat status for each session. Each user is given a 'loginSeat' value which is used to populate this filed. Also the session now has a seatAllowed of type Boolean, true: the user is allowed to access the site, false: the user is not allowed access to the site.
'use strict';
import mongoose from 'mongoose';
var SessionSchema = new mongoose.Schema({
_id: String,
session: String,
expires: Date,
seat: Number,
seatAllowed: Boolean // true: the user is allowed to access the site, false: the user is not allowed access to the site
});
export default mongoose.model('Session', SessionSchema);
I modified server/auth/login/passport.js so that when a user logs into the site, all other users with a matching seat are bumped out.
'use strict';
import path from 'path';
import passport from 'passport';
import {Strategy as LocalStrategy} from 'passport-local';
import _ from 'lodash';
import Sessions from '../../api/session/session.model';
function saveUpdates(updates) {
return function(entity) {
var updated = _.merge(entity, updates);
return updated.save()
.then(updated => {
return updated;
});
};
}
function localAuthenticate(User, email, password, done, req) {
User.findOne({
email: email.toLowerCase()
}).exec()
.then(user => {
if (!user) {
return done(null, false, {
message: 'This email is not registered.'
});
}
// When a user logs into the site we flag their seat as allowed
var updateSession = {'seat': user.loginSeat, 'seatAllowed': true};
Sessions.findById(req.session.id).exec()
.then(saveUpdates(updateSession))
// When a user logs into the site, we disallow the seats of all other sessions with matching seat
Sessions.find().exec()
.then(sessions => {
// Check for existing user logged in with matching login seat
for (var i = 0; i < sessions.length; i++) {
if (sessions[i].seat === user.loginSeat && sessions[i].id !== req.session.id) {
console.log('DISALOW SEAT:');
var updateSession = {'seatAllowed': false};
Sessions.findById(sessions[i].id).exec()
.then(saveUpdates(updateSession));
}
}
});
user.authenticate(password, function(authError, authenticated) {
if (authError) {
return done(authError);
}
if (!authenticated) {
return done(null, false, { message: 'This password is not correct.' });
} else {
return done(null, user);
}
});
})
.catch(err => done(err));
}
export function setup(User, config) {
passport.use(new LocalStrategy({
passReqToCallback: true,
usernameField: 'email',
passwordField: 'password' // this is the virtual field on the model
}, function(req, email, password, done) {
return localAuthenticate(User, email, password, done, req);
}));
}
Each time the client makes a request the isAuthenticated function is triggered. This is where I check for the seaAllowed boolean for the current session, if true, allow the user to access the site, otherwise logout the user:
function saveUpdates(updates) {
return function(entity) {
var updated = _.merge(entity, updates);
return updated.save()
.then(updated => {
return updated;
});
};
}
/**
* Attaches the user object to the request if authenticated
* Otherwise returns 403
*/
export function isAuthenticated() {
return compose()
// Validate jwt
.use(function(req, res, next) {
// Allow access_token to be passed through query parameter as well
if (req.query && req.query.hasOwnProperty('access_token')) {
req.headers.authorization = 'Bearer ' + req.query.access_token;
}
validateJwt(req, res, next);
})
// Attach user to request
.use(function(req, res, next) {
User.findById(req.user._id).exec()
.then(user => {
if (!user) {
return res.status(401).end();
}
req.user = user;
///////////////////////////
// Login seat limitation //
///////////////////////////
// Check if the user seat is allowed
Sessions.findById(req.session.id).exec()
.then(thisSession => {
// TODO access the session in a better way
if (thisSession.seatAllowed === false || thisSession.seatAllowed === undefined) {
res.redirect('/login');
}
})
next();
})
.catch(err => next(err));
});
}
Thats it.