I am relatively new to mobile app development and currently learning React Native with Expo. I have previous experience with ReactJS, where I successfully implemented Google OAuth using Passport for authentication in the backend.
Now, I am attempting to integrate Google OAuth into my React Native Expo app, and I’m facing challenges in understanding the workflow. Specifically, I am uncertain about whether I need to run the frontend and backend separately when building an Expo React Native app.
Here’s a snippet of the code where I am trying to perform authentication:
backend
index.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const passport = require("passport");
const authRoutes = require('./routes/authRoutes');
const setupSwagger = require('./swagger');
const cookieSession = require("cookie-session");
const app = express();
app.use(
cookieSession({
name: "session",
keys: ["cyberwolve"],
maxAge: 24 * 60 * 60 * 100,
})
);
app.use(passport.initialize());
app.use(passport.session());
// Integrate Swagger configuration
setupSwagger(app);
app.use(bodyParser.json());
app.use(
cors({
origin: "http://localhost:8081",
methods: "GET,POST,PUT,DELETE",
credentials: true,
})
);
// Use authentication routes
app.use('/auth', authRoutes);
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
authRoutes.js
const express = require('express');
const router = express.Router();
const passport = require("passport");
router.get("/google", passport.authenticate("google", { scope: ["profile", "email"] }));
router.get(
"/google/callback",
passport.authenticate("google", {
successRedirect: process.env.CLIENT_URL,
failureRedirect: "/auth/login/failed",
})
);
module.exports = router;
passport.js
require('dotenv').config()
const passport = require("passport");
const GoogleStrategy = require("passport-google-oauth20").Strategy;
passport.use(
new GoogleStrategy(
{
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
callbackURL: "/auth/google/callback",
scope: ["profile", "email"],
},
function (accessToken, refreshToken, profile, callback) {
return callback(null, profile);
}
)
);
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
Frontend:
api.js
import axios from 'axios';
import { API_BASE_URL } from '../../.env';
const signInWithGoogle = async () => {
try {
const response = await axios.get(`${API_BASE_URL}/auth/google`);
console.log(response.data);
return response.data;
} catch (error) {
console.error('Error signing in with Google:', error);
return null;
}
};
export { signInWithGoogle };
.env.js
export const API_BASE_URL = "http://localhost:8080";
welcomescreen.jsx
import React from "react";
import { View, Text, TouchableOpacity, StyleSheet, Image } from "react-native";
import { useNavigation } from "@react-navigation/native";
import { AntDesign } from "@expo/vector-icons";
import { primaryColor, secondaryColor } from "../../utils/constants/color";
import { signInWithGoogle } from "../../services/api";
export const WelcomeScreen = () => {
const navigation = useNavigation();
const handleSignInWithGoogle = async () => {
const user = await signInWithGoogle();
if (user) {
console.log("User signed in:", user);
navigation.navigate("Balance");
} else {
console.log("Sign-in failed");
}
};
return (
<View style={styles.container}>
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.googleButton}
onPress={handleSignInWithGoogle}
>
<AntDesign name="google" size={24} color="white" />
<Text style={styles.buttonText}>Sign In with Google</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
logo: {
width: 100,
height: 100,
borderRadius: 20,
marginBottom: 20,
},
title: {
fontSize: 24,
fontWeight: "bold",
color: primaryColor,
marginBottom: 20,
},
buttonContainer: {
width: "80%",
marginTop: 20,
},
googleButton: {
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
backgroundColor: secondaryColor,
padding: 10,
borderRadius: 5,
marginBottom: 10,
},
buttonText: {
marginLeft: 10,
color: "white",
fontWeight: "bold",
},
});
The issue I’m encountering is “I’m getting a network error when attempting to connect to the backend server”. I’ve checked changing the local host to ipaddress and .env file to .env.js , but the problem persists.
I would appreciate any guidance on the correct flow for implementing Google OAuth in a React Native Expo app with a separate backend. Additionally, if there are specific considerations or configurations needed for Expo apps, please provide insights.
Thank you for your assistance!