flutterfire
flutterfire copied to clipboard
🐛 [firebase_auth] linkWithCredential throws Exception operation-not-allowed even when provider is enabled
Bug report
When I setup a Firebase Project and enable Anonymous and Email/Password Auth providers:
and I perform FirebaseAuth.instance.signInAnonymously(), it works:
but when after that I perform:
final credential = EmailAuthProvider.credential(
email: '[email protected]', password: 'Flutter123!');
FirebaseAuth.instance.currentUser
?.linkWithCredential(credential);
it throws:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: [firebase_auth/operation-not-allowed] The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section. [ Please verify the new email before changing email. ]
E/flutter ( 5468): #0 FirebaseAuthUserHostApi.linkWithCredential (package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart:1622:7)
E/flutter ( 5468): <asynchronous suspension>
E/flutter ( 5468): #1 MethodChannelUser.linkWithCredential (package:firebase_auth_platform_interface/src/method_channel/method_channel_user.dart:73:22)
E/flutter ( 5468): <asynchronous suspension>
E/flutter ( 5468): #2 User.linkWithCredential (package:firebase_auth/src/user.dart:190:9)
E/flutter ( 5468): <asynchronous suspension>
E/flutter ( 5468):
I would expect this action to be successful since the Anonymous provider is enabled.
On the other hand, FirebaseAuth.instance.createUserWithEmailAndPassword(email: '[email protected]', password: 'Flutter123!'); works.
Steps to reproduce
Steps to reproduce the behavior:
- Launch the sample project
- Click on "Sign-in anonymously"
- Click on "Link with credentials"
- Assess the error in the logs.
Expected behavior
I would expect the method FirebaseAuth.instance.currentUser?.linkWithCredential(credential); to work when the Anonymous provider is enabled.
Sample project
https://github.com/VincentJouanne/bug_anonymous_auth
Additional context
Here is my google-services.json:
{
"project_info": {
"project_number": "234247651900",
"project_id": "bug-anonymous-auth",
"storage_bucket": "bug-anonymous-auth.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:234247651900:android:7440cec1790171d6db3939",
"android_client_info": {
"package_name": "com.example.bug_anonymous_auth"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyB9SwWRdNCsh_8ZKURmQBBfX7lHah7xoK4"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
Flutter doctor
Run flutter doctor and paste the output below:
Click To Expand
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.13.0, on macOS 12.6 21G115 darwin-arm64, locale en-FR)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.3)
[✓] VS Code (version 1.82.2)
[✓] Connected device (3 available)
[✓] Network resources
• No issues found!
Flutter dependencies
Run flutter pub deps -- --style=compact and paste the output below:
Click To Expand
Dart SDK 3.1.0
Flutter SDK 3.13.0
bug_anonymous_auth 1.0.0+1
dependencies:
- cupertino_icons 1.0.6
- firebase_auth 4.10.0 [firebase_auth_platform_interface firebase_auth_web firebase_core firebase_core_platform_interface flutter meta]
- firebase_core 2.16.0 [firebase_core_platform_interface firebase_core_web flutter meta]
- flutter 0.0.0 [characters collection material_color_utilities meta vector_math web sky_engine]
dev dependencies:
- flutter_lints 2.0.3 [lints]
- flutter_test 0.0.0 [flutter test_api matcher path fake_async clock stack_trace vector_math async boolean_selector characters collection material_color_utilities meta source_span stream_channel string_scanner term_glyph web]
transitive dependencies:
- _flutterfire_internals 1.3.6 [collection firebase_core firebase_core_platform_interface flutter meta]
- async 2.11.0 [collection meta]
- boolean_selector 2.1.1 [source_span string_scanner]
- characters 1.3.0
- clock 1.1.1
- collection 1.17.2
- fake_async 1.3.1 [clock collection]
- firebase_auth_platform_interface 6.19.0 [_flutterfire_internals collection firebase_core flutter meta plugin_platform_interface]
- firebase_auth_web 5.8.1 [firebase_auth_platform_interface firebase_core firebase_core_web flutter flutter_web_plugins http_parser js meta]
- firebase_core_platform_interface 4.8.0 [collection flutter flutter_test meta plugin_platform_interface]
- firebase_core_web 2.8.0 [firebase_core_platform_interface flutter flutter_web_plugins js meta]
- flutter_web_plugins 0.0.0 [flutter characters collection material_color_utilities meta vector_math web]
- http_parser 4.0.2 [collection source_span string_scanner typed_data]
- js 0.6.7 [meta]
- lints 2.1.1
- matcher 0.12.16 [async meta stack_trace term_glyph test_api]
- material_color_utilities 0.5.0 [collection]
- meta 1.9.1
- path 1.8.3
- plugin_platform_interface 2.1.6 [meta]
- sky_engine 0.0.99
- source_span 1.10.0 [collection path term_glyph]
- stack_trace 1.11.0 [path]
- stream_channel 2.1.1 [async]
- string_scanner 1.2.0 [source_span]
- term_glyph 1.2.1
- test_api 0.6.0 [async boolean_selector collection meta source_span stack_trace stream_channel string_scanner term_glyph]
- typed_data 1.3.2 [collection]
- vector_math 2.1.4
- web 0.1.4-beta
Thanks for the report @VincentJouanne
I am able to replicate the reported behavior using the repo provided, after following: signInAnonymously and then create user and then link with credential throws below error which seems to be expected:
E/flutter ( 7949): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: [firebase_auth/provider-already-linked] User has already been linked to the given provider.
E/flutter ( 7949): #0 FirebaseAuthUserHostApi.linkWithCredential (package:firebase_auth_platform_interface/src/pigeon/messages.pigeon.dart:1622:7)
E/flutter ( 7949): <asynchronous suspension>
E/flutter ( 7949): #1 MethodChannelUser.linkWithCredential (package:firebase_auth_platform_interface/src/method_channel/method_channel_user.dart:73:22)
E/flutter ( 7949): <asynchronous suspension>
E/flutter ( 7949): #2 User.linkWithCredential (package:firebase_auth/src/user.dart:190:9)
E/flutter ( 7949): <asynchronous suspension>
E/flutter ( 7949):
But if we sign in anonymously and then try to link with credential, it throws the reported exception, but it seems the plugin is catching the error properly as [firebase_auth/operation-not-allowed] which might indicate the order in which the sequence is executed could be leading to the the error.
I see that the exception also contains Please verify the new email before changing email. . I see a similar issue asked on StackOverflow recently but with react-native app: https://stackoverflow.com/q/77147854, so the issue may not be specific to Flutter + firebase.
There's a similar error thrown but for a different use case though : https://github.com/firebase/flutterfire/issues/10736
I'll keep the issue open for team's attention / input on the error received.
/cc @Lyokone
Hello @VincentJouanne. I did a little digging on this issue, and it seems to be an issue with the server.
Based on the docs, converting an anonymous user to a permanent account is a valid use case.
Here is a simple example using the JS SDK using Vite to bundle and run the TS:
// main.ts
import {initializeApp} from 'firebase/app';
import {
getAuth,
signInAnonymously,
linkWithCredential,
EmailAuthProvider
} from 'firebase/auth';
const firebaseConfig = {
apiKey: ...,
authDomain: ...,
projectId: ...,
storageBucket: ...,
messagingSenderId: ...,
appId: ...,
};
initializeApp(firebaseConfig)
const auth = getAuth();
async function anon() {
await signInAnonymously(auth);
}
async function link() {
const credential = EmailAuthProvider.credential('[email protected]', 'password');
await linkWithCredential(auth.currentUser!, credential);
}
document.getElementById('#anon-button')!.addEventListener('click', anon);
document.getElementById('#link-button')!.addEventListener('click', link);
<!-- index.html -->
...
<button id="anon-button">Sign in Anonymously</button>
<button id="link-button">Link with Email</button>
<script src="main.ts" type="module"></script>
...
After clicking on Sign in Anonymously, clicking on Link with Email gives the following error:
Uncaught (in promise) FirebaseError: Firebase: Please verify the new email before changing email. (auth/operation-not-allowed).
The network request can also be inspected to see the response from the Firebase servers, which proves that this is an error on the servers itself:
Response from linkWithCredential server request:
{
"error": {
"code": 400,
"message": "OPERATION_NOT_ALLOWED : Please verify the new email before changing email.",
"errors": [
{
"message": "OPERATION_NOT_ALLOWED : Please verify the new email before changing email.",
"domain": "global",
"reason": "invalid"
}
]
}
}
The issue will be raised with the Firebase team. I'll keep this issue open in the meantime. Thank you
Thank you very much for your deepdive @exaby73 🙏 !
great work @exaby73 !
same issue here. @exaby73 ,what does that mean? Does it mean that google servers are down/hacked/insecure?
@tomasbaran I can assure you that it's not any of those :) As far as I know, this was an unintentional bug with regards to a change that is actually improving security. Rest assured, the Firebase team is aware of this issue and will be fixed soon
I raised an issue and got a response. This is known and being fixed on. The next release should fix this issue. This is caused by Email Enumeration Protection and can be disabled for your project.
I've disabled "Email Enumeration Protection" for my project, but oath parameters are still missing in google-services.json
It seems this issue has been resolved. Please don't hesitate to open a new issue if you encounter any further problems. We're here to help!