
How to use Corbado to build a Flutter app using passkey authentication
The following article describes how you can use Corbado's authentication package for Flutter to effortlessly offer your users passkeys. The package comes with passkey-first authentication as well as complete session and user management solution.
Hello Flutter developers,
In our last tutorial, we introduced the open-source Flutter passkeys package that allows an easy and flexible integration of passkeys into your Flutter app with any passkey backend provider.
To go one step further, we now want to showcase how you can build a Flutter app with a fully passkey-centered authentication and user management solution (not just the passkey login itself). This solution comes in the form of the corbado_auth package. Besides the pure passkey login and sign-up functionality (which are offered by the passkeys package already), the corbado_auth package currently comes with the following additional features:
- Session management
- Email magic link as fallback and double opt-in
Setting up passkeys on your own is still a struggle, but also taking care of these additional features on your own requires a lot of developer resources if done properly, so we want to take that burden for you and let you focus on your core features of your Flutter app.
The corbado_auth package together with Corbado’s service is a full authentication SDK that covers all aspects of user management and authentication for you (e.g.,recovery, fallbacks, etc.). The corbado_auth package currently supports Android and iOS (more platforms to come).
You can use the package as well as Corbado completely for free, as this is another step in our journey to make the Internet a safer place.
The main goals of the corbado_auth Flutter package are:
- Simplicity: Build an easy-to-use Flutter passkey package that enables every Flutter developer to implement passkey-based authentication with little effort.
- Holistic: All aspects are covered, so you can tick user management and authentication for your app.
- Support: There are a few pitfalls when setting up authentication. We try to provide guidance and help for common mistakes.
This tutorial is structured as follows:
3.2. Login and Content activity
4. (Optional) Bind passkeys to specific domain
6.1. Weak SHA-1 algorithm for Android keystore
6.2. Android screen lock not set up on virtual Android device
The code of this tutorial is taken from our corbado_auth integration example, which you can find here.
Here’s a preview of the running example app in Android:
.gif)
To better understand the architecture of the corbado_auth package, we look at the relationship of the corbado_auth package and the passkeys package.
corbado_auth is Corbado’s full-fledged authentication SDK which utilizes the passkeys package for passkey authentication. While any passkey backend can theoretically be plugged into the passkeys package, the corbado_auth package plugs in Corbado's passkeys backend, so no additional infrastructure is needed.
For a more detailed overview of the passkeys package, and further elaboration on the role of passkey backend providers, please have a look at the overview of the first Flutter blog post.
Go to the Corbado developer panel and create a new account and project. After successful sign up, in the wizard, select ‘Integration guide’, ‘Native / Flutter app’ and ‘No existing users’.
Note: Please make sure that under Settings -> User interface -> Identity verification "Option 2: No verification required" is selected. This should be set by default, when selecting “Native / Flutter app” in the previous step.
Now, some platform-specific settings have to be made. Navigate to the Native Apps settings and add a new Android / iOS app as shown in the next steps.
Set up an Android app by clicking "Add new". You will need your package name (e.g. com.corbado.passkeys.example) and your SHA-256 fingerprint (e.g.54:4C:94:2C:E9:...).
The package name of your app is defined in /android/app/build.gradle (applicationId). Its default value for the example app is com.corbado.passkeys.example.

You can obtain the SHA-256 fingerprint of your debug signing certificate by executing the following command:
macOS / Linux:
Windows:

If you encounter any issues, please have a look Troubleshooting.
We need to establish trust between your iOS app and the relying party server. Your app will be identified through your Application Identifier Prefix (e.g. 9RF9KY77B2) and your Bundle Identifier (e.g. com.corbado.passkeys). You need an Apple developer account to set up both. If you haven't got one yet, set up a new account.
Note: When creating your Bundle Identifier, make sure that the "Associated Domains" capability is enabled.

The Application Identifier Prefix can be obtained by going to your Apple Developer Certificates, Identifier & Profiles associated with your Apple Developer account.
Open the example in Xcode now by opening /packages/passkeys/passkeys/example/ios. In "Runner -> Signing & Capabilities" enter your Application Identifier Prefix and your Bundle Identifier.
Set up an iOS app by clicking "Add New". You will need your Application Identifier Prefix and your Bundle Identifier that we set up in step 2.2.1.

Afterwards, the Corbado relying party server will host an apple-app-site-association file at https://{ CORBADO_PROJECT_ID }}.frontendapi.corbado.io/.well-known/apple-app-site-association. This file will by downloaded by iOS when you install your app. To tell iOS where to look for the file, we need the next step in our setup.
In your Xcode workspace, you need to configure the following settings: In "Signing & Capabilities" tab, add the "Associated Domains" capability and add the following domain: webcredentials:{CORBADO_PROJECT_ID}.frontendapi.corbado.io Now, iOS knows where to download the apple-app-site-association file from.
If you forget about this step, the example will show you an error message like “Your app is not associated with your relying party server. You have to add...”.
Your configuration inside Xcode should look similar to what is shown in the screenshot below (you will have your own Corbado project ID and a different Bundle Identifier).

In the following, we explain step-by-step how to implement a basic Flutter app. If you want to see the final version of the example, please check the GitHub repo.
We start byinitiating our project with „flutter create passkeys-demo-flutter“. Under lib/main.dart we will find the default flutter widget.
We will add the following packages
- corbado_auth for authentication
- passkeys for better error handling (corbado_auth uses passkeys under the hood so we can use Exception types from the passkeys package for better error handling)
- get_it for singleton handling.
- rxdart for using BehaviourSubjects
- oktoast for showing error messages to the user
You can add them all at once by executing
Next, we’ll create a folder named “services” which contains all business logic. In there, we create a file called app_locator.dart, which we will use to register our singletons with the get_it package.

The only singleton we got for now, is an instance of CorbadoAuth.dart, the main interface of the corbado_auth package. To initiate CorbadoAuth, we need the Corbado project ID from step 2. When running our app we’ll register it as an environment variable, so we’ll take it from there.
Now that CorbadoAuth is easily available everywhere via GetIt, we create a service which handles all means of authentication for our app and provides the UI with a user object if someone is logged in. For this, we create a file auth_service.dart containing our AuthService class. This class uses the CorbadoAuth instance we registered previously.

To make it easy for our widgets to access our AuthService, we register it as a singleton in app_locator.dart as well. The UI will use the AuthService for all authentication related tasks. The updated app_locator.dart file looks like this:
That’s it concerning the authentication business logic of our application. We can now focus on the UI. First, inside a “components”-folder, let’s create a custom button for our UI to prevent redundant code in our screens:

Our app will have two screens: one for authentication and one for logged-in users. We’ll therefore create two files named login_activity.dart and content_activity.dart:

The login activity will be launched on startup while the content activity will be displayed once a user has authenticated. The login activity offers a text input for the username, as well as a sign up and login button. When clicked, the login activity performs the respective action via our AuthService. If an error occurs, the oktoast package is used to display a toast containing the error message to the user. If the authentication succeeded, the user is directed to the content page.
Now to the final widget: the content activity. As seen in the code snippet above, once authentication succeeds, the ContentActivity is launched. We already created a file for this class: activities/content_activity.dart. Inside of this file, we now create the ContentActivity class which gets accessed by the LoginActivity. It just displays a little bit of text containing the username as well as a logout button.
Finally, we can swap out our main.dart content for the following snippet which directs us to our login activity, when we start the app:
So, when we run the app, we have to add the Corbado project ID as an environment variable like this:
Then, you should be able to sign up and login with an email of your choice. Our example on GitHub only varies slightly, as we’ve kept the design and theme customizations in this tutorial to a minimum to keep the amount of code small.

Each passkey is bound to a certain domain, the so-called relying party ID. If you use the Corbado default settings, passkeys are bound to your project-specific Corbado subdomain at https://<Corbado project ID>.frontendapi.corbado.io.
Of course, you can also use your own domain for passkey binding. To do so, you need to verify that both the native app and domain belong to you. Therefore, you need to host a configuration file on your domain. For Corbado default settings, you can find these files here (it can take up to 5 minutes after you added the native app information in the Corbado developer panel until the files are deployed):
- Android: assetlinks.json at https://your-domain.com/.well-known/assetlinks.json
- iOS: apple-app-site-association at https://your-domain.com/.well-known/apple-app-site-association
To create these files on your own, you can copy the file structure from the project-specifc Corbado subomains above. Then, you need to update the respective relying party ID / specific domain in the file.
In the case of Android, for the assetlinks.json file, you can also use Android Studio’s Digital Asset Links File Generator to generate the file. You find it under “Tools > App Links Assistant > Open Digital Asset Links File Generator“ in Android Studio.



If you’re using Corbado as passkey infrastructure provider, but want to bind the passkey to a specific domain (other than the default one), you need to make sure to also adapt the relying party ID in the Corbado developer panel under “Settings > General > URLs” to be the same as your newly selected, specific domain.
Make sure that you have a running virtual device or a physical device connected to your machine.
Now, you are fully set and you can start signing up with your first passkey in the example by running the following command:
If you run the example from your IDE, please make sure to either:
- set the CORBADO_PROJECT_ID environment variable to your Corbado project ID
- replace const String.fromEnvironment ('CORBADO_PROJECT_ID') directly in the example with your Corbado project ID
If you’ve executed one of the commands in step 2.1.1 to view your SHA-256 fingerprint and you see an error message like the following “SHA1withRSA (weak)”:

Then, you need to create a new Android keystore with a stronger algorithm. You can do so with one of the following commands:
- macOS / Linux:
- Windows:
If you run the application in a virtual Android device, and it says that you can't create a passkey, you have to properly set up a screen lock or biometrics on the device. To do so, open the settings, search for security settings and add a PIN as well as a fingerprint as shown below (PIN is required for fingerprint):

Congrats! You have successfully set up your authentication and user management for your Flutter app with Corbado leveraging the corbado_auth package.
Besides the current focus on passkeys as authentication method, we plan to add more features to the corbado_auth package that can help for more complex apps. Examples of these feature are:
- Support for existing users
- Native email magic links / OTP as fallback (when an existing user has not set up a passkey yet)
- Cross-sync passkeys with a web app
- Advanced passkey management features for different cloud backup systems (e.g. support ofGoogle Password Manager and iCloud Keychain for the same user)
Enjoyed this read?
Stay up to date with the latest news, strategies and insights about passkeys sent straight to your inbox!