Facebook/Google Login: A Solution with React-Native-Meteor


Introduction

Disclaimer

This article is not a 100%-original walkthrough but a derivative design and implementation inspired by Spencer Carli and other open-source implementations.

All code snippets shown in this article are from public open-source projects. The proprietary part will not be provided here.

Tech Stack: Understanding Meteor.js

The Meteor web tech stack is a mature web full-stack solution. In the Meteor land, we’re used to luxuries like automatically synced data or being able to write database queries using the same syntax on the client and server. You may not have heard of Meteor before, but its successor, Apollo, is widely known for the popular GraphQL. It gives you more control but also requires writing more logic yourself.

When it comes to mobile, the maturity might become a problem. As the combo of React-Native-Meteor is quite rare, the 3rd party package React-Native-Meteor has not been updated for 2 years. On the other hand, it’s still the best solution so far if you don’t want to build your own wheel.

The target backend uses Meteor.Accounts for user login and authentication as part of the mature solution, including social login. However, Meteor.Accounts APIs are not available on mobile (React Native). So, developers need to find a third-party package or SDK to finish the FB login and Google login.

If developers are looking for a 3rd party package to solve this with yarn or npm install, they may want the desired package to be compatible with the frontend React-Native-Meteor and the backend Meteor.Accounts package at the same time.

Unfortunately, there was none like this.

Spencer Carli was able to implement the Facebook login by writing his own Facebook login handler. Then, for Google login, he basically followed his GitHub project.

Thus, based on Spencer’s great work, it’s time for developers to refactor their own wheels.

The Challenge: Meteor in Mobile Environment

The Problem:

  • Meteor.Accounts social login APIs don’t work on React Native
  • No existing npm package provides both React-Native-Meteor compatibility AND Meteor.Accounts backend integration
  • The official React-Native-Meteor package hasn’t been updated in 2 years
  • Developers must bridge the gap between native SDKs and Meteor’s authentication system

Why It Matters:

  • Unified authentication across web and mobile is crucial for user experience
  • Manual token management without proper integration leads to security issues
  • Building custom solutions from scratch is time-consuming and error-prone

Workflow Overview

Here is the workflow, inspired by Spencer Carli.

Spencer didn’t provide the database CRUD details because the database and web social login solutions may vary. He used the default LoginButton component provided by the Facebook SDK, so we need to create our own custom social login components.

The Authentication Flow:

User Action (Mobile App)

Native SDK Login (Facebook/Google)

Token Retrieval from SDK

Send Token to Meteor Server

Meteor Login Handler Processes Token

Generate Meteor-Stamped Token

Store Token & User ID Locally

User Authenticated

Legend:

  • Red circled: Spencer Carli’s design
  • Uncircled: Original implementation

Social Login Backend

Facebook Login Backend

Here, Spencer Carli elaborated his flow in these two articles. It’s not hard to follow and implement, so links are provided here for records.

Medium article: Spencer Carli’s Facebook Login Implementation

Github project: React Native Meteor Facebook Login

Google Login Backend

Github project: React Native Meteor Google Login

Using Accounts Methods to Stamp and Upsert Services

Here, Spencer didn’t provide the database CRUD details because the database and web social login solutions may vary. In general, Meteor.Accounts is one of the most widely used packages for social login with the Meteor web solution.

After dismantling the source code of Meteor.Accounts, here is the implementation of Meteor server token generation:

Accounts.registerLoginHandler('facebookMobile', ({ options }) => {
  //*** Auth part
  const stampedToken = Accounts._generateStampedLoginToken()
  const hashStampedToken = Accounts._hashStampedToken(stampedToken)
  Meteor.users.update(userId, {
    $push: { 'services.resume.loginTokens': hashStampedToken }
  })
  return {
    _id: userId,
    userId: userId,
    token: stampedToken.token
  }
})

After Facebook/Google Auth succeeded, the Meteor.Accounts package’s source code came with two methods to upsert the services.resume.loginTokens, in order to make the mobile users get consistent login info as web users.

Social Login Frontend

Set Up

For the React Native part, it’s recommended to use these packages:

{
  "react-native-google-signin": "^2.0.0",  // for RN 0.60+, try @react-native-community/google-signin
  "react-native-fbsdk": "^0.10.1"  // or RN 0.60+, try react-native-fbsdk 1.0+
}

Google: react-native-google-signin
Facebook: react-native-fbsdk

Critical Implementation Steps

Here, Spencer created a MeteorGoogleLoginManager to handle everything with Google login on the Mobile (React Native) side, with the help of the MeteorCommunicationManager Class created previously for handling the communication with our Meteor Server.

Step 1: Configure the Service

Configure the service to get the token from Google/Facebook auth services via the mobile SDK.

import { YourMeteorCommunicationManager } from './'

export default class YourMeteorGoogleLoginManager {
  static configureGoogleSignIn() {
    GoogleSignin.configure({
      webClientId: ENV_CONFIG.google.webClientId,
      offlineAccess: false
    })
  }
  // ... other methods
}

Step 2: Implement Native SDK Login

static async loginWithGoogle() {
  try {
    await GoogleSignin.hasPlayServices()
    const userInfo = await GoogleSignin.signIn()
    const { idToken, accessToken } = await GoogleSignin.getTokens()
    
    // Send tokens to Meteor server
    return await MeteorCommunicationManager.callMethod(
      'loginWithGoogleMobile',
      { idToken, accessToken }
    )
  } catch (error) {
    console.error('Google login error:', error)
    throw error
  }
}

Step 3: Handle Server Response

The last step: Store the ID and Meteor-generated token in AsyncStorage and the local Meteor object, respectively.

// Same for Google/Facebook login
static YourMeteorAuthCallback = (err, res, cbk, failCbk) => {
  if (!err && !!res) {
    // Save user ID and token
    const Data = Meteor.getData()
    AsyncStorage.setItem(ENV_CONFIG.USER_TOKEN_KEY, res.token)
    Data._tokenIdSaved = res.token
    Meteor._userIdSaved = res.id
    cbk && cbk(res)
  } else {
    AsyncStorage.removeItem(ENV_CONFIG.USER_TOKEN_KEY)
    failCbk && failCbk(err)
  }
}

Implementation Considerations

Token Storage

  • Store Meteor tokens securely using AsyncStorage
  • Keep tokens synchronized with Meteor’s local collection
  • Implement token refresh logic for long-lived sessions

Error Handling

  • Handle network failures gracefully
  • Implement retry logic for failed authentication attempts
  • Provide clear error messages to users

Platform Differences

  • iOS requires URL scheme configuration
  • Android requires Google Services compatibility check
  • Handle platform-specific OAuth flows

Security Best Practices

  1. Never commit credentials to version control
  2. Use environment variables for API keys and secrets
  3. Validate tokens on the server side
  4. Implement proper session management
  5. Use HTTPS for all OAuth communications

Testing Strategy

  1. Test login flows on both iOS and Android devices
  2. Verify token persistence across app restarts
  3. Test error scenarios (network failures, user cancellation)
  4. Validate token refresh mechanisms
  5. Ensure proper logout functionality

Conclusion

Implementing social authentication with React Native and Meteor requires bridging the gap between native SDKs and Meteor’s authentication system. While challenging, the approach pioneered by Spencer Carli provides a solid foundation for developers who need this functionality.

The key to success is understanding:

  • How Meteor.Accounts works internally
  • How to properly bridge native authentication with Meteor’s token system
  • How to maintain security while providing a seamless user experience

By following this approach, developers can achieve unified authentication across web and mobile platforms while leveraging Meteor’s robust backend infrastructure.

References