baumblatt / capacitor-firebase-auth

Capacitor Firebase Authentication Plugin
MIT License
261 stars 129 forks source link

Observable not returning value to subscriber #51

Closed sabahang closed 4 years ago

sabahang commented 4 years ago

Hi, I'm trying to do phone verification and none of the .subscribe() methods return the values they are supposed to. For example:

            cfaSignInPhone(number).subscribe(
                user => {
                    console.log('Sent to number ' + user.phoneNumber + ' successfully!');
                }
            );

Actually sends the SMS but console.log is never called. I have the same situation with cfaSignInPhoneOnCodeSent().subscribe() after I get the code and need to verify it.

What am I doing wrong?

baumblatt commented 4 years ago

Hello Saba,

Are you on Android or iOS? Please can you share any native log?

Just in case, cfaSignInPhone on iOS will complete without emit any value (just like EMPTY)

In other hands the cfaSignInPhoneOnCodeSent must emit the verification code that will be used in the next step of authentication.

Anyway, please review the docs, maybe could help:

Phone Verification https://github.com/baumblatt/capacitor-firebase-auth/blob/master/README.MD#phone-verification

Notifications For Phone Verification https://github.com/baumblatt/capacitor-firebase-auth/blob/master/README.MD#notification-for-phone-verification-step

Take a look at the end of this topic to view an iOS verification step suggested!

I'm looking forward for hearing from you

Best regards, Bernardo Baumblatt

On Fri, Dec 27, 2019, 07:07 Saba Ahang notifications@github.com wrote:

Hi, I'm trying to do phone verification and none of the .subscribe() methods return the values they are supposed to. For example:

        cfaSignInPhone(number).subscribe(
            user => {
                console.log('Sent to number ' + user.phoneNumber + ' successfully!');
            }
        );

Actually sends the SMS but console.log is never called. I have the same situation with cfaSignInPhoneOnCodeSent().subscribe() after I get the code and need to verify it.

What am I doing wrong?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/baumblatt/capacitor-firebase-auth/issues/51?email_source=notifications&email_token=ADJMCV45XC2NFTBKJSQH4F3Q2XHU7A5CNFSM4J7ZSSGKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4IC2Z2WA, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADJMCV5RHP2H6PGDGLSWYLTQ2XHU7ANCNFSM4J7ZSSGA .

sabahang commented 4 years ago

Im on Android. Problem is not having an empty value. Problem is that verificationId doesn't get passed in to javascript code at all because no listener gets registered. I have read all your documentation. Is there any specific order to calling cfaSignInPhoneOnCodeSent and cfaSignInPhone? Should one be called before the other?

My javascript code is as follows:

            console.log("Mobile: trying to send code...");
            //First setting listener for code (seems like this has to be set before calling cfaSignIn!?)
            const verificationId;
            cfaSignInPhoneOnCodeSent().subscribe(
                verificationId => {
                    console.log("VerificationId recieved");
                    verificationId = verificationId;
                },
                (error) => {    
                    setFireBaseError("coulnd't verify phone number because of " + error);
                },
                () => {console.log("Code verify complete was called")}
            );
            cfaSignInPhone(number).subscribe(
                (user) => {
                    //This block is never called
                    console.log('Sent to number ' + user.phoneNumber + ' successfully!');
                    // open dialog to ask for Code
                },
                (error) => {
                    setFireBaseError("coulnd't send SMS to phone number because of " + error);
                },
                () => {console.log("Send SMS code complete was called")}
            );

            console.log("Mobile: trying to verify number");

            if (verificationId && data.code){
                //Creating a credential using the code user recieved and verificationId
                const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, data.code);
                firebase.auth().signInWithCredential(credential).catch(function(error) {
                    setFireBaseError(error);
                    return;
                });
                console.log(verificationId, "code was provided. User is now signed in");

                setHintMessage("Number validated!");
            } else {
                setFireBaseError("Mobile: verificationId was not recieved");
            } 

The following is some native logs. As you can see SMS is sent but subscriber method is never called

...
D/Capacitor: Starting BridgeActivity
D/FA: Logging event (FE): session_start(_s), Bundle[{ga_event_origin(_o)=auto, ga_session_id(_sid)=[RETRACTED]}]
D/Capacitor: Registering plugin: App
D/Capacitor: Registering plugin: Accessibility
D/Capacitor: Registering plugin: BackgroundTask
D/Capacitor: Registering plugin: Browser
D/Capacitor: Registering plugin: Camera
D/Capacitor: Registering plugin: Clipboard
    Registering plugin: Device
D/Capacitor: Registering plugin: LocalNotifications
D/Capacitor: Registering plugin: Filesystem
D/Capacitor: Registering plugin: Geolocation
D/Capacitor: Registering plugin: Haptics
D/Capacitor: Registering plugin: Keyboard
D/Capacitor: Registering plugin: Modals
D/Capacitor: Registering plugin: Network
    Registering plugin: Permissions
D/Capacitor: Registering plugin: Photos
    Registering plugin: PushNotifications
D/Capacitor: Registering plugin: Share
D/Capacitor: Registering plugin: SplashScreen
    Registering plugin: StatusBar
D/Capacitor: Registering plugin: Storage
D/Capacitor: Registering plugin: Toast
    Registering plugin: WebView
D/Capacitor: Registering plugin: CapacitorFirebaseAuth
D/CapacitorFirebaseAuth: Verifying if the default FirebaseApp was initialized.
D/CapacitorFirebaseAuth: Retrieving FirebaseAuth instance
    Initializing Phone Provider
    Phone Provider Initialized
E/Capacitor: Unable to read file at path public/plugins
D/Capacitor: Loading app at http://localhost
W/om.[RETRACTED].ap: Accessing hidden method Landroid/media/AudioManager;->getOutputLatency(I)I (greylist, reflection, allowed)
I/AdrenoGLES: QUALCOMM build                   : e0436c5, Ib165d46056
    Build Date                       : 09/10/19
    OpenGL ES Shader Compiler Version: EV031.27.05.01
    Local Branch                     : 
    Remote Branch                    : quic/gfx-adreno.lnx.1.0.r74-rel
    Remote Branch                    : NONE
    Reconstruct Branch               : NOTHING
    Build Config                     : S P 8.0.11 AArch64
V/FA: Connection attempt already in progress
W/cr_media: Requires BLUETOOTH permission
I/AdrenoGLES: PFP: 0x016ee187, ME: 0x00000000
V/FA: Connection attempt already in progress
W/AdrenoUtils: <ReadGpuID_from_sysfs:194>: Failed to open /sys/class/kgsl/kgsl-3d0/gpu_model
    <ReadGpuID:218>: Failed to read chip ID from gpu_model. Fallback to use the GSL path
D/Capacitor/Plugin/LN: LocalNotification received: null
    Activity started without notification attached
D/Capacitor: App started
V/FA: Activity resumed, time: 623682028
D/Capacitor/Plugin/App: Firing change: true
V/Capacitor/Plugin/App: Notifying listeners for event appStateChange
D/Capacitor/Plugin/App: No listeners found for event appStateChange
W/VideoCapabilities: Unsupported mime image/vnd.android.heic
D/Capacitor: App resumed
D/FA: Logging event (FE): screen_view(_vs), Bundle[{ga_event_origin(_o)=auto, ga_screen_class(_sc)=MainActivity, ga_screen_id(_si)=-1234818339153558742}]
W/VideoCapabilities: Unsupported mime video/divx
W/VideoCapabilities: Unsupported mime video/divx4
W/VideoCapabilities: Unrecognized profile/level 0/3 for video/mpeg2
W/VideoCapabilities: Unrecognized profile/level 0/3 for video/mpeg2
W/VideoCapabilities: Unsupported mime video/x-ms-wmv
D/Capacitor: Handling local request: http://localhost/
W/Looper: Slow Looper main: Activity com.[RETRACTED].app/.MainActivity is 624ms late (wall=0ms running=0ms ClientTransaction{ callbacks=[android.app.servertransaction.TopResumedActivityChangeItem] }) because of 2 msg, msg 1 took 281ms (seq=2 running=249ms runnable=8ms io=6ms h=android.app.ActivityThread$H w=110), msg 2 took 354ms (seq=3 running=220ms runnable=21ms io=45ms late=256ms h=android.app.ActivityThread$H w=159)
W/ContentCatcher: Failed to notify a WebView
V/FA: Connection attempt already in progress
V/FA: Connection attempt already in progress
W/Gralloc3: mapper 3.x is not supported
V/Capacitor/Plugin/Network: Notifying listeners for event networkStatusChange
D/Capacitor/Plugin/Network: No listeners found for event networkStatusChange
D/FA: Connected to remote service
W/InputMethodManager: Ignoring onBind: cur seq=4244, given seq=4243
V/FA: Processing queued up service tasks: 6
D/Capacitor: Handling local request: http://localhost/static/css/10.4d723b5a.chunk.css
D/Capacitor: Handling local request: http://localhost/static/css/main.1612b7ec.chunk.css
D/Capacitor: Handling local request: http://localhost/static/js/10.93653e6d.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/main.0e4e27e2.chunk.js
W/Capacitor/Console: File: http://localhost/static/js/10.93653e6d.chunk.js - Line 2 - Msg: 
    It looks like you're using the development build of the Firebase JS SDK.
    When deploying Firebase apps to production, it is advisable to only import
    the individual SDK components you intend to use.

    For the module builds, these are available in the following manner
    (replace <PACKAGE> with the name of a component - i.e. auth, database, etc):

    CommonJS Modules:
    const firebase = require('firebase/app');
    require('firebase/<PACKAGE>');

    ES Modules:
    import firebase from 'firebase/app';
    import 'firebase/<PACKAGE>';

    Typescript:
    import * as firebase from 'firebase/app';
    import 'firebase/<PACKAGE>';
I/Capacitor/Console: File: http://localhost/static/js/main.0e4e27e2.chunk.js - Line 1 - Msg: Ionic current Platforms:  android,tablet,cordova,capacitor,mobile,hybrid
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 30367580, pluginId: Device, methodName: getInfo
V/Capacitor: callback: 30367580, pluginId: Device, methodName: getInfo, methodData: {}
I/Capacitor/Console: File: http://localhost/static/js/main.0e4e27e2.chunk.js - Line 1 - Msg: production
D/Capacitor: Handling local request: http://localhost/static/js/12.45191161.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/83.d630655d.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/61.8178dcfa.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/65.47006205.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/51.5b655fdc.chunk.js
I/Capacitor/Console: File: http://localhost/static/js/main.0e4e27e2.chunk.js - Line 1 - Msg: Capacitor device type:  android
D/Capacitor: Handling local request: http://localhost/static/js/0.74d77655.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/85.c96461da.chunk.js
D/Capacitor: Handling local request: http://localhost/assets/icon/favicon.png
D/Capacitor: Handling local request: http://localhost/static/js/7.9b7a3488.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/2.3dfc6079.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/1.19ac1b83.chunk.js
D/Capacitor: Handling local request: http://localhost/static/js/5.6222f794.chunk.js
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 30367581, pluginId: App, methodName: addListener
V/Capacitor: callback: 30367581, pluginId: App, methodName: addListener, methodData: {"eventName":"backButton"}
D/Capacitor: SplashScreen was automatically hidden after the launch timeout. You should call `SplashScreen.hide()` as soon as your web app is loaded (or increase the timeout).Read more at https://capacitor.ionicframework.com/docs/apis/splash-screen/#hiding-the-splash-screen
V/FA: Inactivity, disconnecting from the service
I/om.[RETRACTED].ap: ProcessProfilingInfo new_methods=2461 is saved saved_to_disk=1 resolve_classes_delay=8000
I/AssistStructure: Flattened final assist data: 1760 bytes, containing 2 windows, 6 views
V/Capacitor/Plugin/Keyboard: Notifying listeners for event keyboardWillShow
D/Capacitor/Plugin/Keyboard: No listeners found for event keyboardWillShow
V/Capacitor/Plugin/Keyboard: Notifying listeners for event keyboardDidShow
D/Capacitor/Plugin/Keyboard: No listeners found for event keyboardDidShow
D/Capacitor: Handling local request: http://localhost/start
D/Capacitor: Handling local request: http://localhost/static/css/main.1612b7ec.chunk.css
D/Capacitor: Handling local request: http://localhost/static/css/10.4d723b5a.chunk.css
I/Capacitor/Console: File: http://localhost/static/js/main.0e4e27e2.chunk.js - Line 1 - Msg: +447522600335
I/Capacitor/Console: File: http://localhost/static/js/main.0e4e27e2.chunk.js - Line 1 - Msg: Mobile: trying to send SMS
I/Capacitor/Console: File: http://localhost/static/js/main.0e4e27e2.chunk.js - Line 1 - Msg: Setting up verification callback
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 30367582, pluginId: CapacitorFirebaseAuth, methodName: addListener
V/Capacitor: callback: 30367582, pluginId: CapacitorFirebaseAuth, methodName: addListener, methodData: {"eventName":"cfaSignInPhoneOnCodeSent"}
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 30367583, pluginId: CapacitorFirebaseAuth, methodName: addListener
V/Capacitor: callback: 30367583, pluginId: CapacitorFirebaseAuth, methodName: addListener, methodData: {"eventName":"cfaSignInPhoneOnCodeReceived"}
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 30367584, pluginId: CapacitorFirebaseAuth, methodName: signIn
V/Capacitor: callback: 30367584, pluginId: CapacitorFirebaseAuth, methodName: signIn, methodData: {"providerId":"phone","data":{"phone":"+447522600335"}}
D/Capacitor: Handling local request: http://localhost/static/js/76.98a23f9c.chunk.js
I/BiChannelGoogleApi: [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq@e56dece
V/Capacitor/Plugin/Keyboard: Notifying listeners for event keyboardWillHide
D/Capacitor/Plugin/Keyboard: No listeners found for event keyboardWillHide
V/Capacitor/Plugin/Keyboard: Notifying listeners for event keyboardDidHide
D/Capacitor/Plugin/Keyboard: No listeners found for event keyboardDidHide
D/PhoneProviderHandler: onCodeSent:AM5PThADF3TJEGfvuIY1XUpHhr153WlzHSegm3O6Aw6QZE4kPitT2jzO9cL7-Mp9ao7LsKNIm4Ezrum9AcbAyXa2b2oA6-8JKEeOWiF1j7d6IKTjTru3OO19solUciXUR5JElt1rhbMPwwQ5XlMXSc267JFP8xnGWW3Q8EKeEM6nUIFBedbVZ9r2l9gLvVwlhN04R6JxQKStMr5fRxIxYae6Oe8ubg8wmISBYjauwsR_HMLgFtEHhYM
V/Capacitor/Plugin/CapacitorFirebaseAuth: Notifying listeners for event ePhoneOnCodeSent
D/Capacitor/Plugin/CapacitorFirebaseAuth: No listeners found for event ePhoneOnCodeSent
I/PhoneAuthProvider: Sms auto retrieval timed-out.
sabahang commented 4 years ago

I believe that my problem is in the following two lines:

V/Capacitor/Plugin/CapacitorFirebaseAuth: Notifying listeners for event ePhoneOnCodeSent
D/Capacitor/Plugin/CapacitorFirebaseAuth: No listeners found for event ePhoneOnCodeSent

Why are there no listeners registered? I have tried everything including, calling cfaSignInPhoneOnCodeSent().subscribe before call to cfaSignInPhone, calling it inside useEffect React hook, calling it after cfaSignInPhone but none of them seem to register the listener properly. What am I doing wrong?

I can even see that in the logs the following listener is registered:

V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 35125965, pluginId: CapacitorFirebaseAuth, methodName: addListener
V/Capacitor: callback: 35125965, pluginId: CapacitorFirebaseAuth, methodName: addListener, methodData: {"eventName":"cfaSignInPhoneOnCodeSent"}

Isn't this the same as ePhoneOnCodeSent?

baumblatt commented 4 years ago

Hi Saba,

You are right, there is a typo in event name at your runtime, but as I can see at code, this typo is not there.

Please take a look at line 84: https://github.com/baumblatt/capacitor-firebase-auth/blob/master/android/capacitor-firebase-auth/src/main/java/com/baumblatt/capacitor/firebase/auth/handlers/PhoneProviderHandler.java

Anyway, this weekend I don't have access to my computer, but I can take a look at this tomorrow (Monday).

Is there a way that you can share your project?

I'm looking forward to hearing from you.

Best regards, Bernardo Baumblatt

sabahang commented 4 years ago

@baumblatt thanks for reply. You mentioning typo helped me solve it. I have no idea how this typo was introduced but I cleaned my entire android project and setup everything from scratch and this time paid more attention to details. I personally think your documentation can benefit from being a bit more thorough or having some working full examples...that being said here are my 2 cents:

  1. cfaSignInPhoneOnCodeSent listener or it's other counterpart should be set before call to cfaSignInPhone. In my humble opinion although this is common sense it should be mentioned in the documentation. I experimented with setting them up inside next() call of cfaSignInPhone and after it and when things were not working it was hard to be sure where is the right place to call it

  2. Everyone using this plugin should know at which point to present a a dialog to the user asking for PIN. This is not clarified in documentation. Again I experimented with triggering the PIN code popup inside the cfaSignInPhone and cfaSignInPhoneOnCodeSent next() function or complete() functions and finally decided that inside cfaSignInPhoneOnCodeSent complete() function is the best place to ask because at that point we are sure we have verificationId but cfaSignInPhone doesn't guarantee that

  3. Not everyone is familiar with RxJS. I personally wasn't. I had to read their documentation to even realize that there is an (error)=> {} and complete()=>{} functions that can be used with cfaSignInPhoneOnCodeSent and cfaSignInPhone. These hooks can prove really important in narrowing down the issue and understanding what errors are happening, otherwise things might just fail silently and it's hard to figure out why. I think this should also be mentioned in the documentation

  4. It's not clear from the documentation that your library is not offering any ways to authorize the user with firebase (final step). I had to read all the issues in this repo and thanks to one issue I realized that the final verification only happens when I manually do the following: I think this should also be clarified in the documentation that basically this library only helps to get your the verificationId (except on Android that auto login can be used) and the rest is on the developer to do

    const credential = firebase.auth.PhoneAuthProvider.credential(verificationId, users_input_PIN);
    firebase.auth().signInWithCredential(credential).then().catch()
  5. In the documentation it is mentioned to follow instructions to Add Firebase to your Android project. In reality Step 4: Add Firebase SDKs to your app) of those instructions are not needed at all because your library is already importing all the necessary firebase dependencies. This is important because as soon as you add the latest version of firebase dependencies to your own project you will start running into AndroidX dependency inconsistency issues and if you take the bait and start migrating to AndroidX you will soon realize that Capacitor doesn't yet have support for AndroidX and this is a huge headache that can waste hours. I finally avoided adding any firebase dependency directly to my own project and everything started working without need to mess with AndroidX. I think this is also important to mention in documentation

  6. I didn't add the the following to the project and everything still seems to work (I'm only using Phone auth). Maybe documentation should clarify what is really needed for any given auth method. I wouldn't want to add non-related configuration to my project if they are not needed by my auth method

    android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    }
    ///
      "permissions": {
           "google": ["profile", "https://www.googleapis.com/auth/drive", ...]
       }

Thanks a lot for the helpful library and thanks for being responsive. I appreciate your work. Right now this is the only solution with Capacitor. I do hope that you also could add PWA support soon. It has great potential, only has some rough edges that needs to be polished both in documentation and in code but really good start and timing is great with Capacitor

baumblatt commented 4 years ago

Hi Saba,

Great news that everything is working for you now.

Really thank you for your review, I agree with you that is time to review the entire documentation.

We have tree big step to move forward with the plugin: Apple provider, PWA and review docs.

Please, fell free to help if you can, I will love to accept PRs.

Happy new year.

Best regards , Bernardo Baumblatt.

akshat-ilen commented 4 years ago

I have followed the steps as mentioned, still I am not able to get the observable. @sabahang Can you help me with what I m missing?

Angular service code

sendOTPWithSDK(mobileNo:string):Observable<any> {

    let phone = "+91"+mobileNo

    return from(cfaSignInPhone(phone)) .pipe(
      map(response=> {
        console.log(response)
        return response}),
      catchError((error) => {
        this.common.displayErrorMessage(error['message'],true)
        return throwError(error);
      })
    )
  }

Native Android Log

2020-05-13 12:58:44.066 4393-4393/com.linckup D/PhoneProviderHandler: PhoneAuth:onVerificationCompleted:com.google.firebase.auth.PhoneAuthCredential@e7e3d85
2020-05-13 12:58:44.066 4393-4393/com.linckup V/Capacitor/CapacitorFirebaseAuth: Notifying listeners for event cfaSignInPhoneOnCodeReceived
2020-05-13 12:58:44.066 4393-4393/com.linckup D/Capacitor/CapacitorFirebaseAuth: No listeners found for event cfaSignInPhoneOnCodeReceived

capacitor.config.json

{
  "appId": "com.linckup",
  "appName": "Linckup",
  "bundledWebRuntime": false,
  "npmClient": "npm",
  "webDir": "www",
  "cordova": {
    "preferences": {
      "ScrollEnabled": "false",
      "android-minSdkVersion": "19",
      "BackupWebStorage": "none",
      "SplashMaintainAspectRatio": "true",
      "FadeSplashScreenDuration": "300",
      "SplashShowOnlyFirstTime": "false",
      "SplashScreen": "screen",
      "SplashScreenDelay": "3000"
    }
  },
  "plugins": {
    "CapacitorFirebaseAuth": {
      "providers": [
        "phone"
      ],
      "languageCode": "en",
      "nativeAuth": false
    }
  },
  "server": {
    "url": "http://192.168.1.103:8100",
    "cleartext": true
  }
}