How is the ERR_CLEARTEXT_NOT_PERMITTED error overcome?

2.1k Views Asked by At

I am following a tutorial on building a login page for users and for a few days now I have been stuck with a cleartext error.

In response I have noticed directions on creating a network_security_config file and adding to the AndroidManifest files, but these things made no difference.

Then I found a tutorial on hard-coding the Android emulator's settings, and this made a difference, but afterwards the error found is that users in the Firestore are not found at login attempts ... And so it becomes circular, with one thing or another.

The question I have is, is there a solution in January 2023 for overcoming the infamous cleartext error please? ... I thought I had got past this problem having got past this point before, but it seems that everything I did before doesn't work anymore.

Is there a CLI solution for setting up Android emulators and fixing their network security?

main.dart

const bool useEmulator = true;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  if (useEmulator == true) {
    await _connectToFirebaseEmulator();
  }  
  runApp(LoginScreen());
}

/// Connect to the firebase emulator for firestore and authentication
Future _connectToFirebaseEmulator() async {
  final localHostString = Platform.isAndroid ? '10.0.2.2' : 'localhost';

  FirebaseFirestore.instance.settings = Settings(
    host: '$localHostString:2080',
    sslEnabled: false,
    persistenceEnabled: false,
  );
  await auth.FirebaseAuth.instance.useAuthEmulator('http://$localHostString', 9080);
}

LoginPage.dart:

class LoginScreen extends StatelessWidget {
  LoginScreen({super.key});

  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();

  void signUserIn() async {
    await auth.FirebaseAuth.instance.signInWithEmailAndPassword(
        email: emailController.text, password: passwordController.text);
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        resizeToAvoidBottomInset: false,
        backgroundColor: Colors.blue[900],
        body: SafeArea(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Padding(padding: EdgeInsets.only(top: 0, bottom: 37)),

                TextField_Try(
                    hintText: 'Username',
                    obscureText: false,
                    controller: emailController),

                Padding(padding: EdgeInsets.only(top: 0, bottom: 0)),

                Padding(
                    padding: EdgeInsets.only(
                        top: 8.0, left: 8.0, right: 8.0, bottom: 28.0),
                    child: TextField_Try(
                      hintText: '**************',
                      obscureText: true,
                      controller: passwordController,
                    )),

                Padding(padding: EdgeInsets.only(bottom: 10)),

                ElevatedButton(onPressed: signUserIn, child: Text('Sign In')),

                Padding(padding: EdgeInsets.only(bottom: 25)),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

Network-Config:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config xmlns:android="http://schemas.android.com/apk/res/android">
        <domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">http://10.0.2.2</domain>
        </domain-config>
</network-security-config>

AndroidManifest - main:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:targetSandboxVersion="1"
    package="com.example.mathems_m">


    <uses-permission android:name="android.permission.INTERNET"></uses-permission>


   <application
        android:label="mathems_m"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
       android:usesCleartextTraffic="true"
       android:roundIcon="@android:interpolator/cycle"
       android:supportsRtl="true"
       android:allowBackup="true">
        <activity
            android:name=".MainActivity"
            android:exported="true"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data
              android:name="io.flutter.embedding.android.NormalTheme"
              android:resource="@style/NormalTheme"
              />
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
       <meta-data
           android:name="com.google.android.gms.wallet.api.enabled"
           android:value="true" />
    </application>
</manifest>

My position is creating a user at the FIRECLOUD console (email + password) and then attempting to login with the created user's details. It hasn't worked out though things I have done have led to different error messages.

The current error message is:

E/flutter (20214): [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: [firebase_auth/unknown] com.google.firebase.FirebaseException: An internal error has occurred. [ Invalid authority field:[http: ]
E/flutter (20214): #0      StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:607:7)
E/flutter (20214): #1      MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:167:18)
E/flutter (20214): <asynchronous suspension>
E/flutter (20214): #2      MethodChannel.invokeMapMethod (package:flutter/src/services/platform_channel.dart:367:43)
E/flutter (20214): <asynchronous suspension>
E/flutter (20214): #3      MethodChannelFirebaseAuth.signInWithEmailAndPassword (package:firebase_auth_platform_interface/src/method_channel/method_channel_firebase_auth.dart:500:12)
E/flutter (20214): <asynchronous suspension>
E/flutter (20214): #4      FirebaseAuth.signInWithEmailAndPassword (package:firebase_auth/src/firebase_auth.dart:584:9)
E/flutter (20214): <asynchronous suspension>
E/flutter (20214): #5      LoginScreen.signUserIn (package:choice_hi/screens/login.dart:15:5)
E/flutter (20214): <asynchronous suspension>
E/flutter (20214): 

The various differing error messages relate to the cleartext error.

Please advise me on a solution for overcoming the cleartext error 100%. Thank you.

2

There are 2 best solutions below

0
On BEST ANSWER

Okay, so in the end, I made useEmulator 'false' so that there's zero reliance on the _connectToFirebaseEmulator() method, which means I have found a solution that does not require a network_security_config.xml file ... To achieve my success I added Firebase to my project automatically, I added Firebase emulators automatically and each package for pubspec was added automatically using Flutter's terminal instead of alternative ways (executing 'flutter pub add firebase_core' in terminal - for example). Generally, relying on Flutter to build Flutter where the option is available.

build.gradle

android {
compileSdkVersion 33
ndkVersion ndkVersion

main-AndroidManifest

<application
    android:label="mathems_m"
    android:name="${applicationName}"
    android:icon="@mipmap/ic_launcher"
   android:usesCleartextTraffic="true"

debug-AndroidManifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mathems_m">
<meta-data
    android:value="true"/>
    <!-- The INTERNET permission is required for development. Specifically,
         the Flutter tool needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
    <application android:usesCleartextTraffic="true" />
</manifest>

That's about it really ... So, this shows how simple the Firebase-authentication can be to set up ... In minutes instead of days : )

0
On

for simulator Add line before call auth function

FirebaseAuth.instance.useAuthEmulator('127.0.0.1', 9080);

Android - In Android main/menifest file for network issue handle

<application

android:usesCleartextTraffic="true" // Add line             
android:name="io.flutter.app.FlutterApplication"
android:label="firebaseauthexample"> 

</application>

iOS - iOS/runner/info.plist

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>