auth 3.2.0

Auth Class #

This class library works with two plugins: firebase_auth and google_sign_in to log into a Firebase backend using a Firebase account or a Google account. If you're familiar with these plugins, you will find the same functions used in this class library. Auth Package

How it Works #

Below are a series of screenshots depicting how to initialize and authenticate or 'sign in' an individual into your app's Firebase database using a either an email and password or a Google account. The following will sign in 'silently' (i.e. automatically if the user had already signed in in the past.). Note, settings are passed as parameters in the screenshot below. 09inistate These examples have the class library called in the State object's iniState() function, but, of course, you could instead 'initialize' the class library in the initState() function and then 'sign in' elsewhere. Below, the init() function is used instead just to initialize the class library. authinit auth3 anyomous google properties

On Medium #

This is a class library is covered again in the Medium article, Auth in Flutter. AuthArticle

3.2.0 #

  • Provided new functions: getIdToken(); updatePhoneNumberCredential(); linkWithCredential(); updatePassword(); sendEmailVerification(); updateProfile(); reload(); reauthenticateWithCredential();
    delete(); unlinkFromProvider(); updateEmail();

3.1.1 #

  • set listen(GoogleListener f) => _googleListeners.add(f);

3.1.0 #

  • void return type in some functions.
  • Introduced the setters, listener and listen.

3.0.0 #

August 06, 2019

  • Removed parameters onError, onDone(), and cancelOnError from the Constructor
  • Introduced getEventErrors() and eventErrors
  • CustomAlertDialog class in example app

2.1.0 #

August 02, 2019

  • Introduced signedInGoogle(), signedInFirebase()
  • Adjusted example main.dart

2.0.0 #

August 02, 2019

  • Abandoned the Singleton design pattern
  • Factory constructor to ensure only one Auth instance.
  • Renamed signIn functions.

1.3.1 #

August 02, 2019

  • Removed properties: signInOption scopes hostedDomain onError, onDone, cancelOnError
  • Set{} for list of listeners
  • Rearranged code for readability

1.3.0 #

August 02, 2019

  • async isSignedIn(), isLoggedIn()
  • Library-private _initFireBase()
  • _setUserFromFireBase() in _listFireBaseListeners()
  • _setFireBaseUserFromGoogle() in _listGoogleListeners()
  • Introduced IdTokenResult
  • if (ex is! Exception) {

1.2.1 #

July 29, 2019

  • Latest firebase_auth version
  • Format code
  • signInWithTwitter()

1.2.0 #

  • Include the new classes AuthResult and AdditionalUserInfo from firebase_auth

1.1.0+1 #

Mar. 21, 2019

  • move FlutterOAuth library to oauth directory

1.1.0 #

Mar. 21, 2019

  • incorporated Joe Birch's FlutterOAuth library
  • introduced signInWithFacebook() function

1.0.1 #

Mar. 07, 2019

  • import 'package:flutter/material.dart';

1.0.0 #

Mar. 07, 2019

  • Added signInWithCredential, linkWithCredential, fetchSignInMethodsForEmail
  • Breaking Change Removed signInWithFacebook, signInWithTwitter, signInWithGoogle,
  • Breaking Change linkWithEmailAndPassword, linkWithGoogleCredential, linkWithFacebookCredential

0.1.1 #

Jan. 17, 2019

  • await _setFireBaseUserFromGoogle(currentUser);

0.1.0 #

Dec. 10, 2018

  • Change semantic version number to convey development phase.

0.0.3 #

  • await _user?.reload();

0.0.2 #

  • Format code with dartfmt

0.0.1 #

  • Initial github release

example/main.dart

// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

import 'package:google_sign_in/google_sign_in.dart' show GoogleUserCircleAvatar;

import 'package:auth/auth.dart';

void main() {
  runApp(
    MaterialApp(
      home: SignInDemo(),
      debugShowCheckedModeBanner: false,
    ),
  );
}

class SignInDemo extends StatefulWidget {
  @override
  State createState() => SignInDemoState();
}

class SignInDemoState extends State<SignInDemo>
    with SingleTickerProviderStateMixin {
  Auth auth;
  bool loggedIn = false;
  TabController tabController;

  @override
  void initState() {
    super.initState();

    tabController = TabController(length: 2, vsync: this);

    auth = Auth.init(
        scopes: [
          'email',
          'https://www.googleapis.com/auth/contacts.readonly',
        ],
        listener: (user) {
          loggedIn = user != null;
          setState(() {});
        });

    auth.signInSilently(
      listen: (account) {
        loggedIn = account != null;
        setState(() {});
      },
    );
  }

  @override
  void dispose() {
    /// Important to dispose of the Auth's resources.
    auth.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text("Sign In Demo"),
          bottom: TabBar(
            tabs: [
              Tab(text: "Sign In"),
              Tab(text: "Results"),
            ],
            controller: tabController,
          ),
        ),
        body: Center(
          child: TabBarView(
            controller: tabController,
            children: <Widget>[
              ConstrainedBox(
                constraints: const BoxConstraints.expand(),
                child: _buildBody(),
              ),
              ConstrainedBox(
                constraints: const BoxConstraints.expand(),
                child: _authResults,
              ),
            ],
          ),
        ));
  }

  Widget _buildBody() {
    if (loggedIn) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          ListTile(
            leading: auth.signedInGoogle()
                ? GoogleUserCircleAvatar(
                    identity: auth.googleUser,
                  )
                : Text(''),
            title: Text(auth.displayName),
            subtitle: Text(auth.email),
          ),
          const Text("Signed in successfully."),
          RaisedButton(
            child: const Text('Sign Out'),
            onPressed: () {
              auth.signOut();
            },
          ),
          RaisedButton(
            child: const Text('Sign Out & Disconnect'),
            onPressed: () {
              auth.disconnect();
            },
          ),
        ],
      );
    } else {
      return Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          const Text("You are not currently signed in."),
          RaisedButton(
            child: const Text('Sign In With Google'),
            onPressed: () {
              auth.signIn();
            },
          ),
          RaisedButton(
            child: const Text('Log in anonymously'),
            onPressed: () {
              auth.signInAnonymously();
            },
          ),
          RaisedButton(
            child: const Text('Sign in with Email & Password'),
            onPressed: () async {
              List<String> ep = await dialogBox(context: context);
              if (ep == null || ep.isEmpty) return;
              auth.signInWithEmailAndPassword(email: ep[0], password: ep[1]);
            },
          ),
        ],
      );
    }
  }

  Widget get _authResults => ListView(
        padding: const EdgeInsets.all(30.0),
        itemExtent: 80.0,
        children: <Widget>[
          Text("uid: ${auth.uid}"),
          Text("name: ${auth.displayName}"),
          Text("photo: ${auth.photoUrl}"),
          Text("new login: ${auth.isNewUser}"),
          Text("user name: ${auth.username}"),
          Text("email: ${auth.email}"),
          Text("email verified: ${auth.isEmailVerified}"),
          Text("anonymous login: ${auth.isAnonymous}"),
          Text("id token: ${auth.idToken}"),
          Text("access token: ${auth.accessToken}"),
          Text("information provider: ${auth.providerId}"),
          Text("expire time: ${auth.expirationTime}"),
          Text("auth time: ${auth.authTime}"),
          Text("issued at: ${auth.issuedAtTime}"),
          Text("signin provider: ${auth.signInProvider}"),
        ],
      );
}

// Creates an alertDialog for the user to enter their email
Future<List<String>> dialogBox({
  Key key,
  @required BuildContext context,
  bool barrierDismissible = false,
}) {
  return showDialog<List<String>>(
    context: context,
    barrierDismissible: barrierDismissible, // user must tap button!
    builder: (BuildContext context) {
      return CustomAlertDialog(
        key: key,
        title: "Email & Password",
      );
    },
  );
}

class CustomAlertDialog extends StatefulWidget {
  final String title;
  const CustomAlertDialog({Key key, this.title}) : super(key: key);

  @override
  CustomAlertDialogState createState() => CustomAlertDialogState();
}

class CustomAlertDialogState extends State<CustomAlertDialog> {
  final _resetKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  bool _resetValidate = false;
  bool _hidePassword = true;

  @override
  Widget build(BuildContext context) {
    return Container(
      child: AlertDialog(
        title: Text(widget.title),
        elevation: 20.0,
        content: SingleChildScrollView(
          child: Form(
            key: _resetKey,
            autovalidate: _resetValidate,
            child: ListBody(
              children: <Widget>[
                Text(
                  "Email Address & Password.",
                  style: TextStyle(fontSize: 14.0),
                ),
                Padding(
                  padding: EdgeInsets.all(10.0),
                ),
                Column(
                  children: <Widget>[
                    Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
                      Padding(
                        padding: EdgeInsets.only(top: 8.0),
                        child: Icon(
                          Icons.email,
                          size: 20.0,
                        ),
                      ),
                      SizedBox(
                        width: 250,
                        child: TextFormField(
                          validator: validateEmail,
                          controller: _emailController,
                          keyboardType: TextInputType.emailAddress,
                          autofocus: true,
                          decoration: InputDecoration(
                              border: InputBorder.none,
                              hintText: 'Email',
                              contentPadding:
                                  EdgeInsets.only(left: 70.0, top: 15.0),
                              hintStyle: TextStyle(
                                  color: Colors.black, fontSize: 14.0)),
                          style: TextStyle(color: Colors.black),
                        ),
                      )
                    ]),
                    SizedBox(
                      width: 200,
                      child: TextFormField(
                        validator: (String value) {
                          if (value.length == 0 || value.isEmpty)
                            return "Password required.";
                          return null;
                        },
                        keyboardType: TextInputType.text,
                        controller: _passwordController,
                        obscureText:
                            _hidePassword, //This will obscure text dynamically
                        decoration: InputDecoration(
                          labelText: 'Password',
                          hintText: 'Enter your password',
                          // Here is key idea
                          suffixIcon: IconButton(
                            icon: Icon(
                              // Based on passwordVisible state choose the icon
                              _hidePassword
                                  ? Icons.visibility_off
                                  : Icons.visibility,
                              color: Theme.of(context).primaryColorDark,
                            ),
                            onPressed: () {
                              // Update the state i.e. toogle the state of passwordVisible variable
                              setState(() {
                                _hidePassword = !_hidePassword;
                              });
                            },
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
        actions: <Widget>[
          FlatButton(
            child: Text(
              'CANCEL',
              style: TextStyle(color: Colors.black),
            ),
            onPressed: () {
              Navigator.of(context).pop();
            },
          ),
          FlatButton(
            child: Text(
              'SEND EMAIL',
              style: TextStyle(color: Colors.black),
            ),
            onPressed: () {
              _onPressed();
            },
          ),
        ],
      ),
    );
  }

  void _onPressed() {
    bool valid = true;

    if (!_resetKey.currentState.validate()) {
      valid = false;
    }

    if (valid) {
      Navigator.of(context)
          .pop([_emailController.text, _passwordController.text]);
    } else {
      _resetValidate = true;
      setState(() {});
    }
  }
}

String validateEmail(String value) {
  String pattern =
      r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
  RegExp regExp = RegExp(pattern);
  if (value.length == 0) {
    return "Email is required";
  } else if (!regExp.hasMatch(value)) {
    return "Invalid Email";
  } else {
    return null;
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  auth: ^3.2.0

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:auth/auth.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
51
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
75
Learn more about scoring.

We analyzed this package on Aug 21, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.4.0
  • pana: 0.12.19
  • Flutter: 1.7.8+hotfix.4

Platforms

Detected platforms: Flutter

References Flutter, and has no conflicting libraries.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
firebase_auth ^0.14.0 0.14.0+2
flutter 0.0.0
flutter_webview_plugin ^0.3.5 0.3.7
google_sign_in ^4.0.4 4.0.6
http ^0.12.0+1 0.12.0+2
url_launcher ^5.1.1 5.1.2
Transitive dependencies
async 2.3.0
charcode 1.1.2
collection 1.14.11 1.14.12
firebase_core 0.4.0+8
http_parser 3.1.3
meta 1.1.6 1.1.7
path 1.6.4
pedantic 1.8.0+1
sky_engine 0.0.99
source_span 1.5.5
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test