GithubHelp home page GithubHelp logo

rekire / autologin_plugin Goto Github PK

View Code? Open in Web Editor NEW
4.0 4.0 3.0 36.6 MB

Autologin plugin for Flutter

License: MIT License

Kotlin 7.23% Swift 3.68% Objective-C 0.03% Dart 75.91% HTML 2.74% Ruby 2.87% CMake 0.65% C++ 6.34% C 0.54%
flutter flutter-plugin smartlock android

autologin_plugin's Introduction

Autologin plugin for Flutter

Build status Pub Version

This Flutter package helps the user to login quickly. When the user has saved in the platform specific password manager credentials will be filled out by a simple confirmation or account chooser depending on the platform. You can also save the users credentials with a simply API call. On supported platforms those credentials will be synced on all your devices.

On Android and Apple devices you can also store a login token to sign in seamlessly without any interaction. So when your user uses your app on a new device for the first time your user will be already signed in.

An animated image of the Android login flow with autologin      An animated image of the iOS login flow with autologin

You can check the web example app on the GitHub page in supported (Chromium based) browsers.

Features and compatibilities

You can safe and request Credentials and store and read Login Tokens for automatic logins without any user interaction.

Android iOS Linux MacOS Web Windows
Credentials ✅* ✅** ✅***
LoginToken

*) It seems that saving is just supported on iOS
**) Just on chromium based browsers
***) The documentation of the API mentions that a "Pro" Version is required

Supported platforms

Android

On Android CredentialManager is used. The documentation is not very clear, but it seems that with the PlayServices devices back to Android 4.4 are supported. There is currently no documentation how or if it works on non Google Play certificated devices.

Change your app to use FlutterFragmentActivity

The Android implementation uses the CredentialManager API to query the credentials. This API requires native asynchronous code. This code is written in Kotlin and uses Coroutines. Since the CredentialManager starts a System Activity the Activity lifecycle needs to be maintained, this is managed with the Android Jetpack's Lifecycle API.

The simplest way to add to your MainActivity the LiveCycleOwner interface is to change the base class of your MainActivity to FlutterFragmentActivity. If you MainActivity is empty you can directly reference the base class in your AndroidManifest, then you can delete your MainActivity entirely. In that case you can simply replace in your AndroidManifest (the default path is android/app/main/src/AndroidManifest.xml) the line: android:name=".MainActivity" by android:name="io.flutter.embedding.android.FlutterFragmentActivity".

Important notes on digital asset links

Digital asset links is a way to link your app with a website also called App Links. In order to provide a full example, the example app needs to be signed correctly. Right now the signing key is not checked in, but might be the CI will get the ability to sign the example app in the future so that you can test it by your own.

For the demo you need to publish a .well-known/assetlinks.json which is mirrored in example/web/.well-known/assetlinks.json. However since this is published on github.io the folder will be visible at https://rekire.github.io/autologin_plugin/.well-known/assetlinks.json instead of https://rekire.github.io/.well-known/assetlinks.json, therefore I uploaded that file in a second repository rekire/rekire.github.io where the latest version is actually hosted. In order to publish "dot" directories I had also to define a _config.yaml.

If you want to test your own setup use the Statement List Generator and Tester.

As simple check if the linking works fine check this link on your Android phone, if that opens in Chrome the Example App without an Intent Chooser then this works correctly.

iOS and MacOS

For storing credentials the Shared Web Credentials are used. In order to make this working you need to setup the Associated Domains Entitlement. The main documentation can be found on the Apple Developer site. At least the apple-app-site-association file must be reachable at https://<your-domain>/.well-known/apple-app-site-association and must contain something like:

{
  "webcredentials": {
    "apps": [
      "<your-team-id>.<your-bundle-id>"
    ]
  }
}

Your team id can be found e.g. in ios/Runner.xcodeproj/project.pbxproj look for the key DEVELOPMENT_TEAM, the bundle id is there too look for PRODUCT_BUNDLE_IDENTIFIER. Apple is caching that requests to the file above with their CDN, but you can check the cached value here: https://app-site-association.cdn-apple.com/a/v1/<your-domain>

If you have not setup your app check https://developer.apple.com/account/resources/identifiers/list

In order to use the zero touch login on iOS and MacOS you need to add the iCloud capability and configure iCloud Key-Value Storage in your Xcode project. Here is a step per step guide:

  1. Open your Xcode project.
  2. Select your project in the Project Navigator to open the project settings.
  3. Select your target under "Targets."
  4. Go to the "Signing & Capabilities" tab.
  5. Click the "+ Capability" button.
  6. Scroll down and select "iCloud."
  7. In the iCloud section, enable the "Key-Value storage" checkbox.

Linux

On Linux the D-Bus is used to save an query the password of your app. The native code uses for that like the flutter_secure_storage plugin libsecret. Based on a Blog entry you can store your secrets also directly in KeepassXC, however I was unable to test this integration.

Web

On Web Credential Management API, but be aware that just Chrome, Edge and Opera support this feature (Source).

Windows

On Windows the APIs CredRead and CredWrite are used. Like on Linux that API is used without any user interface.

TODO

  • Extend installation documentation. In the mean time you can use the example app.
  • Build and sign the Android sample app and publish it as artifact (ideally via GitHub Action and as instant app)

autologin_plugin's People

Contributors

dependabot[bot] avatar patricknicolosi avatar rekire avatar simonit avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

autologin_plugin's Issues

Linux Support

I think the best way to integrate is to use libsecret. KDE and GNOME seem to use it.
flutter_secure_storage seems to use it too.

Plugin lets app crash

I don't know the reason for the crash, but it crashed multiple times by clicking on the button for not selecting an email address from the list and once after clicking on the save button I added in #1.

E/AndroidRuntime( 8501): FATAL EXCEPTION: main
E/AndroidRuntime( 8501): Process: de.wbtsolutions.openproject_app, PID: 8501
E/AndroidRuntime( 8501): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=48233, result=-1, data=null} to activity {de.wbtsolutions.openproject_app/de.wbtsolutions.openproject_app.MainActivity}: java.util.ConcurrentModificationException
E/AndroidRuntime( 8501): 	at android.app.ActivityThread.deliverResults(ActivityThread.java:4845)
E/AndroidRuntime( 8501): 	at android.app.ActivityThread.handleSendResult(ActivityThread.java:4886)
E/AndroidRuntime( 8501): 	at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
E/AndroidRuntime( 8501): 	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
E/AndroidRuntime( 8501): 	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
E/AndroidRuntime( 8501): 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
E/AndroidRuntime( 8501): 	at android.os.Handler.dispatchMessage(Handler.java:107)
E/AndroidRuntime( 8501): 	at android.os.Looper.loop(Looper.java:214)
E/AndroidRuntime( 8501): 	at android.app.ActivityThread.main(ActivityThread.java:7356)
E/AndroidRuntime( 8501): 	at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 8501): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime( 8501): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
E/AndroidRuntime( 8501): Caused by: java.util.ConcurrentModificationException
E/AndroidRuntime( 8501): 	at java.util.HashMap$HashIterator.nextNode(HashMap.java:1441)
E/AndroidRuntime( 8501): 	at java.util.HashMap$KeyIterator.next(HashMap.java:1465)
E/AndroidRuntime( 8501): 	at io.flutter.embedding.engine.FlutterEnginePluginRegistry$FlutterEngineActivityPluginBinding.onActivityResult(FlutterEnginePluginRegistry.java:689)
E/AndroidRuntime( 8501): 	at io.flutter.embedding.engine.FlutterEnginePluginRegistry.onActivityResult(FlutterEnginePluginRegistry.java:378)
E/AndroidRuntime( 8501): 	at io.flutter.embedding.android.FlutterActivityAndFragmentDelegate.onActivityResult(FlutterActivityAndFragmentDelegate.java:597)
E/AndroidRuntime( 8501): 	at io.flutter.embedding.android.FlutterFragment.onActivityResult(FlutterFragment.java:699)
E/AndroidRuntime( 8501): 	at io.flutter.embedding.android.FlutterFragmentActivity.onActivityResult(FlutterFragmentActivity.java:510)
E/AndroidRuntime( 8501): 	at android.app.Activity.dispatchActivityResult(Activity.java:8110)
E/AndroidRuntime( 8501): 	at android.app.ActivityThread.deliverResults(ActivityThread.java:4838)
E/AndroidRuntime( 8501): 	... 11 more
I/Process ( 8501): Sending signal. PID: 8501 SIG: 9

MissingPluginException on iOS

MissingPluginException: MissingPluginException(No implementation found for method disableAutoLogIn on channel autologin_plugin)
  File "platform_channel.dart", line 165, in MethodChannel._invokeMethod
  File "<asynchronous suspension>"
  File "autologin_plugin.dart", line 31, in AutologinPlugin.disableAutoLogIn
  File "<asynchronous suspension>"
  File "future.dart", in Future.wait.<fn>

Don't use exceptions

In my opinion, using exceptions for saying that the user has no saved credentials is pretty bad design. It's common to use null for this case. This won't let my error reporting tool freak out.

Another idea is a isSupported method to prevent an exception raised because of a not existing Google API. This would also be very helpful with different platforms.

Roadmap for 1.0.0

For the best login experience it should be as simple as possible to get the user signed in (again) and in best case with zero touch.

Faster logins

Should allow using login data from other devices or the browser. On Android OneTap or the CredeitialManager API #20 the should be used. For iOS I plan to use shared web credentials as mentioned in #11. Both APIs should provide a simple way to access the credentials. On the other hand both APIs have a hard requirement to prove the connection between the APP and the website. On Android assetlinks are required while for Apple associated Domains are required. The documentation need to explain the steps which are required for this.

Zero touch

Should allow the user to fetch some session data to recover the account. For Android I want to use BlockStore. On iOS I want simply to read out the keychain might be with secure storage which is already syncing their data with the keychain.

Possibility to set under which account credentials are saved

If I'm signed in with multiple Google accounts on my device I would like to have the possibility to save for example my works login under the works account and my private ones under my private account.

Referring to this https://developers.google.com/android/reference/com/google/android/gms/auth/api/credentials/package-summary, there seem to be setAccountName for archiving this. There would be also a method needed to get all available accounts to let the user choose the preferred one

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.