Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: signInWithCredential() generates CORS error on "capacitor://localhost" on iOS #221

Closed
maxbarry opened this issue Oct 9, 2022 · 7 comments

Comments

@maxbarry
Copy link

maxbarry commented Oct 9, 2022

Plugin(s):
@capacitor-firebase/authentication

Platform(s):
iOS

Current behavior:
When following the steps documented here for signing into Firebase JavaScript SDK, calling signInWithCredential generates a CORS error saying capacitor://localhost is not allowed.

[Log] Result of FirebaseAuthentication.signInWithGoogle(): – {credential: {accessToken: [REDACTED], providerId: "google.com", idToken: [REDACTED]}} (main.12648797.js, line 2)
[Error] TypeError: undefined is not an object (evaluating 'gapi.iframes.getContext')
	callback (main.12648797.js:2:216096)
	(anonymous function) (api.js:22:487)
	ka (api.js:15:704)
	B (api.js:22:471)
	(anonymous function) (api.js:23)
	(anonymous function) (api.js:23:113)
	Global Code (cb=gapi.loaded_0:1)
[Error] Error: A`capacitor
	(anonymous function) (api.js:23:599)
	(anonymous function) (api.js:22:487)
	ka (api.js:15:704)
	B (api.js:22:471)
	(anonymous function) (api.js:23)
	(anonymous function) (api.js:23:113)
	Global Code (cb=gapi.loaded_1:1)
[Error] Cross-origin redirection to http://developers.google.com/ denied by Cross-Origin Resource Sharing policy: Origin capacitor://localhost is not allowed by Access-Control-Allow-Origin. Status code: 301
[Error] XMLHttpRequest cannot load https://apis.google.com/_/jserror?script=https%3A%2F%2Fapis.google.com%2F_%2Fscs%2Fabc-static%2F_%2Fjs%2Fk%3Dgapi.lb.en.z9QjrzsHcOc.O%2Fm%3Dgapi_iframes%2Frt%3Dj%2Fsv%3D1%2Fd%3D1%2Fed%3D1%2Frs%3DAHpOoo8359JQqZQ0dzCVJ5Ui3CZcERHEWA%2Fcb%3Dgapi.loaded_0%3Fle%3Dscs&error=A%60capacitor&line=180 due to access control checks.
[Error] Failed to load resource: Cross-origin redirection to http://developers.google.com/ denied by Cross-Origin Resource Sharing policy: Origin capacitor://localhost is not allowed by Access-Control-Allow-Origin. Status code: 301 (jserror, line 0)

Expected behavior:
The call to signInWithCredential should succeed.

Steps to reproduce:

Related code:

import { FirebaseAuthentication } from '@capacitor-firebase/authentication'
import {
   getAuth,              
   GoogleAuthProvider,
   signInWithCredential,
} from 'firebase/auth'

const signInWithGoogle = async () => {
  const result = await FirebaseAuthentication.signInWithGoogle()
  console.log("Result of FirebaseAuthentication.signInWithGoogle():", result)
  const credential = GoogleAuthProvider.credential(result.credential?.idToken)
  const auth = getAuth()
  const firebaseResult = await signInWithCredential(auth, credential)
  // This is never reached
  console.log("Firebase -> signInWithCredential", firebaseResult, auth, credential)
}

Other information:

I'm attempting to solve a problem where Firestore users are only authenticated when on the Ionic web platform, not on iOS, which effectively means read-only access to my Firestore database. My reading suggests that I need to make sure the user is signed in to both layers (native & web), but when I attempted that, I hit this CORs error.

Capacitor doctor:

💊   Capacitor Doctor  💊 

Latest Dependencies:

  @capacitor/cli: 4.3.0
  @capacitor/core: 4.3.0
  @capacitor/android: 4.3.0
  @capacitor/ios: 4.3.0

Installed Dependencies:

  @capacitor/android: not installed
  @capacitor/cli: 4.3.0
  @capacitor/ios: 4.3.0
  @capacitor/core: 4.3.0

[success] iOS looking great! 👌
@robingenz
Copy link
Member

Seems like a duplicate of firebase/firebase-js-sdk#5020.
Make sure you use Firebase JS SDK Version 9.8.2 or later.

@robingenz robingenz self-assigned this Oct 9, 2022
@maxbarry
Copy link
Author

maxbarry commented Oct 9, 2022

Wow, that was a fast reply, thank you so much.

I have seen that bug and it does indeed look very similar. But I'm on firebase@9.11.0 and editing capacitor.config.ts to add server: { iosScheme: "ionic" } results in the same CORS error, only now complaining about "ionic://localhost" rather than "capacitor://localhost".

Cross-origin redirection to http://developers.google.com/ denied by Cross-Origin Resource Sharing policy: Origin ionic://localhost is not allowed by Access-Control-Allow-Origin. Status code: 301

Thank you again and for your amazing work on this package.

@robingenz
Copy link
Member

Okay, then please have a look at this issue: ionic-team/capacitor#5531

@maxbarry
Copy link
Author

maxbarry commented Oct 9, 2022

Thanks again! I have also looked at that bug, but it seems to be about AngularFire, while I'm using Ionic React.

@robingenz
Copy link
Member

AngularFire is just a wrapper for the Firebase JS SDK.
Try to adjust the initialization of the Firebase JS SDK according to the SO answer:

if (Capacitor.isNativePlatform()) {
  return initializeAuth(getApp(), {
    persistence: indexedDBLocalPersistence
  })
} else {
  return getAuth()
}

@maxbarry
Copy link
Author

maxbarry commented Oct 9, 2022

Aha! Yes, this worked, and led me to firebase/firebase-js-sdk#5019 (comment) which I believe is my bug. Signing in & out is now working on both web & device, which means signed-in users are authenticated when they make database write/update requests to the Firestore Cloud DB. Hooray! Thank you so much.

So my firebase.js file now contains:

import { initializeApp, getApp } from "firebase/app"
import { Capacitor } from "@capacitor/core"
import { getAuth, initializeAuth, indexedDBLocalPersistence } from "firebase/auth"

const firebaseApp = initializeApp(config)

let auth
export function getFirebaseAuth() {
  if (!auth) {
    if (Capacitor.isNativePlatform()) {
      auth = initializeAuth(getApp(), { persistence: indexedDBLocalPersistence })
    } else {
      auth = getAuth()
    }
  }
  return auth
}

export default const firebaseApp

For signing in, my Login.js contains:

import { FirebaseAuthentication } from '@capacitor-firebase/authentication'
import { GoogleAuthProvider, signInWithCredential } from 'firebase/auth'
import { getFirebaseAuth } from './firebase'

const signInWithGoogle = async () => {
  const result = await FirebaseAuthentication.signInWithGoogle()
 
  const credential = GoogleAuthProvider.credential(result.credential?.idToken)
  const auth = getFirebaseAuth()
  await signInWithCredential(auth, credential)

  return result.user
}

To get signing out to work, I needed to replace FirebaseAuthentication.signOut() with this:

import { signOut } from 'firebase/auth'
import { getFirebaseAuth } from './firebase'

function signMeOut() {
  const auth = getFirebaseAuth()
  signOut(auth)
}

And my App.js listens for user changes:

import { getFirebaseAuth } from './firebase'

useEffect(() => {
    getFirebaseAuth().onAuthStateChanged(user => {
        if (!result) {
            setUser(null)
        } else {
            setUser({ ...user })
        }
    })

    async function getCurrentUser() {
        const { user } = await FirebaseAuthentication.getCurrentUser()
        if (user) {
            setUser(user)
        }   
    }
    getCurrentUser()

}, [ setUser ])

@robingenz
Copy link
Member

Great, thanks for sharing.
In this case I will close this issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 6, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants