Flutter + Firebase Auth : Se connecter avec Apple

La nuit dernière, j’ai mis en ligne ma première application avec Flutter sur l’Apple Store, curieusement elle a été examinée immédiatement. Deux heures plus tard, je reçois un email m’informant que mon application a été rejetée. Les raisons sont assez claires, comme mon application supporte le login avec des tiers (Facebook et Google), elle devrait aussi être capable de supporter le login Apple, j’ai donc commencé à travailler dessus.

Pour les utilisateurs d’iOS, la connexion avec Apple facilite l’ensemble du processus, car nous évitons de remplir des formulaires d’inscription fastidieux, ainsi que la sécurité qu’elle nous offre, car tous les comptes sont protégés par une authentification à deux facteurs.

Depuis Firebase Auth 0.15.3, il est possible de se connecter avec Apple. Il faut donc aller dans la console Firebase, et dans Authentication -> Sign-in method, et activer Apple :

Avant de commencer, vous devez ouvrir votre projet Xcode (dans le projet Flutter, à l’intérieur du dossier ios) et ajouter “Sign In with Apple” sous Capabilities.

https://help.apple.com/developer-account/#/devde676e696

Pour continuer, vous devez installer les dépendances suivantes dans le fichier pubspec.yaml.

apple_sign_in: ^0.1.0
firebase_auth: ^0.15.3
device_info: ^0.4.1+4

Et nous les ajoutons en faisant “flutter pub get” ou si nous travaillons avec Android Studio, nous cliquons simplement sur “Packages get”.

La prochaine chose que nous devons savoir est si notre appareil supporte “Sign In with Apple”, donc nous devons savoir si nous sommes sur iOS 13.

bool isIOS13 = false;
if (Platform.isIOS) {
  var iosInfo = await DeviceInfoPlugin().iosInfo;
  var version = iosInfo.systemVersion;
  if (version.contains('13') == true) {
    isIOS13 = true;
  }
}

Nous avons maintenant besoin d’un bouton pour se connecter si la variable isIOS13 est ‘true’. Dans mon cas, j’ai trois boutons, pour me connecter avec Facebook, avec Google et maintenant avec Facebook. Chaque bouton est inclus dans un conteneur, et tous sont inclus en tant qu’enfants d’une colonne.

child: Column(
    children: <Widget>[
    Text('Astroexif'),
    _buildFacebookLoginButton(),
    _buildGoogleLoginButton(),
    isIOS13 ? _buildAppleLoginButton(): Container()
    ],
)

Et la logique de notre bouton serait la suivante :

Container _buildAppleLoginButton() {
  return Container(
    width: 300,
    margin: EdgeInsets.only(left: 16, top: 16, right: 16, bottom: 0),
    child: ButtonTheme(
      height: 48,
      child: RaisedButton(
          onPressed: () {
            initiateSignIn("A");
          },
          color: Colors.white,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
          textColor: Colors.black,
          child: Text("Connect with Apple",
              style: TextStyle(
                fontWeight: FontWeight.bold,
                fontSize: 20,
              ))),
    ),
  );
}

Ce code affichera un bouton simple avec un fond blanc et un texte noir, des bords arrondis et le texte “Connect with Apple”.

La prochaine chose est d’ajouter le code pour pouvoir se connecter, comme j’utilise plusieurs plateformes pour me connecter, à la méthode initiateSignIn je passe “FB” si je veux me connecter avec Facebook, “G” si je veux me connecter avec Google ou “A” si je veux me connecter avec Apple. Si le processus suivant est correct et que _handleSignIn renvoie un 1, je mets à jour la variable isLoggedIn à true, je cache le widget de connexion et j’affiche le widget de l’utilisateur connecté, ou je navigue vers la page de profil, cela dépend de la façon dont vous voulez gérer votre application.

void initiateSignIn(String type) {
  _handleSignIn(type).then((result) async {
    if (result == 1) {
      setState(() {
        isLoggedIn = true;
      });
    } 
  });

Si nous allons permettre la connexion avec d’autres plateformes, j’ai une méthode asynchrone intermédiaire, où en fonction du type qui arrive, elle génère les appels aux différentes méthodes qui gèrent la connexion pour chacune de ces plateformes.

Future<int> _handleSignIn(String type) async {
  
  switch (type) {
    case "FB": //Facebook
      // ...
      break;
    case "G": //Google
      // ...
      break;
    case "A": //Apple
      final authResult = await _handleAppleSignIn();
      firebaseUser = authResult.user;
      break;
  }
  return 0;
}

Et enfin le code pour pouvoir se connecter avec Apple. Comme nous pouvons le voir dans le code précédent, nous obtenons l’utilisateur firebase avec AuthResult.user. Dans mon cas, je stocke cet utilisateur dans firebaseUser afin de pouvoir l’envoyer à ma base de données Firestore, dessiner l’image du profil de l’utilisateur firebase ou remplir quelques champs dans le widget du profil de l’utilisateur.

Future<AuthResult> _handleAppleSignIn() async {
    AuthResult _res;
    final AuthorizationResult result = await AppleSignIn.performRequests([
      AppleIdRequest(requestedScopes: [Scope.email, Scope.fullName])
    ]);
    switch (result.status) {
      case AuthorizationStatus.authorized:
        try {
          print("successfull sign in");
          final AppleIdCredential appleIdCredential = result.credential;
          OAuthProvider oAuthProvider = new OAuthProvider(providerId: "apple.com");
          final AuthCredential credential = oAuthProvider.getCredential(
            idToken: String.fromCharCodes(appleIdCredential.identityToken),
            accessToken: String.fromCharCodes(appleIdCredential.authorizationCode),
          );
          _res = await FirebaseAuth.instance
              .signInWithCredential(credential);
        } catch (e) {
          print("error");
        }
        break;
      case AuthorizationStatus.error:
        print('User auth error');
        break;
      case AuthorizationStatus.cancelled:
        print('User cancelled');
        break;
    }
    return _res;
  }

Il est également important de savoir qu’avec AppleIdRequest, nous demandons l’accès pour obtenir diverses données du compte Apple, dans ce cas je veux seulement obtenir l’email et le nom complet. C’est à ce moment-là qu’apparaît une fenêtre contextuelle indiquant les autorisations demandées par l’application.

Avec tout ce processus qu’on a mis en place, vous donnez aux utilisateurs de votre application la possibilité de se connecter avec leur Apple ID.

0 Shares:
Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

You May Also Like
Lire plus

Flutter et SQLite

Dans cette histoire, je vais vous raconter mon expérience de l’implémentation d’une base de données hors ligne dans…
Lire plus

Flutter 3.13 : Les dernières fonctionnalités

La dernière mise à jour du framework d'interface utilisateur multiplateforme Flutter de Google fait d'Impeller le moteur de rendu graphique par défaut sur iOS. Le défilement en deux dimensions est aussi de la partie.