Add authentication to your Flutter web applications with Ory Kratos
Add open source login to any Flutter Web App using free open source.

Ory Guest
Add open source login to any Flutter Web App using free open source.

Ory Guest
In this guide, we will set up a hardened, fully functional authentication system with Flutter Web using Ory Kratos, an open-source identity and authentication service written in Golang.
It will take you about ~10 minutes to complete this guide. This guide is for you if you are looking to:
Follow the step-by-step guide to add authentication to your Flutter web application and screens for:
You can find the source code for this guide on GitHub: iglu-ory-kratos-example.
To run the example, clone the repository to your computer.
git clone https://github.com/IGLU-Agency/iglu-ory-kratos-example.git
cd iglu-ory-kratos-example
Should you not have Ory Kratos installed, please follow these instructions.
To test the features of this example run Kratos locally:
kratos serve --config ./test/kratos.yml --dev
Should you have problems running this command, you check the identity schema
path in the Ory Kratos configuration kratos.yml.
Now run the project on Chrome and test how it works.
First of all, we implement flows essential for Ory Kratos to work.
This code generates the SelfServiceLoginFlow, which will be used in the
Login screen:
// ...
Future<SelfServiceLoginFlow?> initHandlersLoginScreen(
BuildContext context,
) async {
final query = ModalRoute.of(context)?.settings.name?.getQueryParameters() ??
<String, String>{};
final flow = query['flow'];
const aal = '';
const refresh = '';
const returnTo = '';
final initFlowUrl = getUrlForFlow(
base: global.baseUrl,
flow: 'login',
query: {'aal': aal, 'refresh': refresh, 'return_to': returnTo},
);
if (!isQuerySet(flow)) {
open(
url: initFlowUrl,
name: '_self',
);
return null;
}
// ...
This code generates the SelfServiceRegistrationFlow, which will be used in the
Registration screen:
// ...
Future<SelfServiceRegistrationFlow?> initHandlersRegistrationScreen(
BuildContext context,
) async {
final query = ModalRoute.of(context)?.settings.name?.getQueryParameters() ??
<String, String>{};
final flow = query['flow'];
const returnTo = '';
final initFlowUrl = getUrlForFlow(
base: global.baseUrl,
flow: 'registration',
query: {'return_to': returnTo},
);
if (!isQuerySet(flow)) {
open(
url: initFlowUrl,
name: '_self',
);
return null;
}
// ...
This code generates the SelfServiceSettingsFlow, which will be used in the
Settings screen.
// ...
Future<SelfServiceSettingsFlow?> initHandlersSettingsScreen(
BuildContext context,
) async {
final query = ModalRoute.of(context)?.settings.name?.getQueryParameters() ??
<String, String>{};
final flow = query['flow'];
const returnTo = '';
final initFlowUrl = getUrlForFlow(
base: global.baseUrl,
flow: 'settings',
query: {'return_to': returnTo},
);
if (!isQuerySet(flow)) {
open(
url: initFlowUrl,
name: '_self',
);
return null;
}
// ...
Now let us take a look at the different screens you can find in lib/screens.
There isn't anything special happening there, but if you intend to change the
layout you can look here. For example like so:

The User Login widget uses the dart native code and performs a User Login
API Flow.
// ...
Widget build(BuildContext context) {
return AbsorbPointer(
absorbing: isLoading,
child: Scaffold(
backgroundColor: Colors.white,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Builder(
builder: (ctx) => Center(
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Align(
child: Container(
alignment: Alignment.center,
width: 500,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
: (
: .,
: <>[
(: ),
(
: .(
,
),
),
(: ),
(
: .(
: ,
: ,
: ,
: ,
),
: (
: .,
: .(
: .(
,
,
,
,
),
),
: .(),
),
: (
: [
(
,
: .,
: (
: .,
: textColor,
: ,
),
),
(: ),
(),
(: ),
(),
(: ),
(),
(: ),
(
: ,
: isLoginButtonEnabled
? _signInAction
: ,
: isLoading,
),
(: ),
(),
],
),
),
(
: +
.(context)..,
),
],
),
),
],
),
),
),
),
),
),
),
),
),
);
}

The User Registration widget uses the dart native code and performs a
User Registration API Flow.
// ...
Widget build(BuildContext context) {
return AbsorbPointer(
absorbing: isLoading,
child: Scaffold(
backgroundColor: Colors.white,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Center(
child: Builder(
builder: (ctx) => Form(
key: _formKey,
child: SingleChildScrollView(
child: Align(
child: Container(
alignment: Alignment.center,
width: 500,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
: (
: .,
: <>[
(: ),
(
: .(
,
),
),
(: ),
(
: .(
: ,
: ,
: ,
: ,
),
: (
: .,
: .(
: .(
,
,
,
,
),
),
: .(),
),
: (
: [
(
,
: .,
: (
: .,
: textColor,
: ,
),
),
(: ),
(),
(: ),
(),
(: ),
(
: ,
: isSignupButtonEnabled
? _signupAction
: ,
: isLoading,
),
(: ),
(),
],
),
),
(
: +
.(context)..,
),
],
),
),
],
),
),
),
),
),
),
),
),
),
);
}

The User Settings widget performs a User Settings API Flow, receives the
users authentication session and displays all relevant information, and also
gives users the ability to change the password and to change their profile
traits.
// ...
Widget build(BuildContext context) {
return AbsorbPointer(
absorbing: isLoading,
child: Scaffold(
backgroundColor: Colors.white,
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Center(
child: Builder(
builder: (ctx) => Form(
key: _formKey,
child: Builder(
builder: (context) {
return SingleChildScrollView(
child: Column(
children: [
Container(
constraints: const BoxConstraints(maxWidth: 500),
child: Image.asset(
'assets/images/ory+iglu_profile.png',
),
),
_returnProfileValuesSection(),
],
),
);
},
),
),
),
),
),
),
);
}
Widget () {
final scrollableContent = (
: (
: ,
: (
: .,
: .(: .(, , , )),
: .(),
),
: .(: ),
: .(: , : ),
: (
: scrollController,
: (
: ,
: scrollController,
: .(
: ,
: + .(context)..,
),
: <>[
(
: .,
: [
(
,
: .,
: (
: .,
: textColor,
: ,
),
),
(
: ,
: .,
: .(.),
: () {
..();
},
: .(: , : ),
: ,
),
],
),
(: ),
(
: .,
: [
(
: isEditMode ? : ,
: () {
(isEditMode) {
();
} {
( isEditMode = !isEditMode);
}
},
: .(: , : ),
: ,
: isLoading,
),
],
),
(: ),
(
: _emailController,
: ,
: isEmailValid || _firstNameController..,
: ,
: (val) {
(() {
isEmailValid = val. || val.;
});
},
: .(),
),
(: ),
(
: _firstNameController,
: (isNameValid && _firstNameController..) ||
_firstNameController..,
: (val) {
(() {
isNameValid = val. || val. >= ;
});
},
: isEditMode,
: ,
: isEditMode
? (
.,
: ,
: textColor,
)
: .(),
),
(: ),
(
: _lastNameController,
: (isNameValid && _lastNameController..) ||
_lastNameController..,
: (val) {
(() {
isLastNameValid = val. || val. >= ;
});
},
: isEditMode,
: ,
: isEditMode
? (
.,
: ,
: textColor,
)
: .(),
),
(: ),
(
: ,
: .,
),
(: ),
(
: .,
: [
(
: ,
: () ? _passwordChange : ,
: .(: , : ),
: ,
: isLoadingPassword,
),
],
),
(: ),
(
: _passwordController,
: !isPasswordVisible,
: _passwordController.. ||
(isPasswordValid &&
(_passwordController. ==
_repeatPasswordController. ||
_repeatPasswordController..)),
: (val) {
(() {
isPasswordValid = val. || val. >= ;
});
},
: (
: () {
(() {
isPasswordVisible = !isPasswordVisible;
});
},
: (
isPasswordVisible ? . : .,
: ,
: textSecondaryColor,
),
),
: ,
),
(: ),
(
: _repeatPasswordController,
: _repeatPasswordController.. ||
(isRepeatPasswordValid &&
(_repeatPasswordController. ==
_passwordController. ||
_passwordController..)),
: !isPasswordVisible,
: (val) {
(() {
isRepeatPasswordValid = val. || val. >= ;
});
},
: ,
: (
: () {
(() {
isPasswordVisible = !isPasswordVisible;
});
},
: (
isPasswordVisible ? . : .,
: ,
: textSecondaryColor,
),
),
),
],
),
),
),
);
scrollableContent;
With this example, you have a starter project to add user authentication out of the box with Ory Kratos in Flutter.
If you are interested in seeing an actual project based on this, we invite you to look at our unique solution that offers Ory Kratos based on this example.
We have now implemented Ory Kratos Authentication with Login, Registration,
Profile Management in Flutter Web!
Thanks for taking the time to follow this guide and hopefully, it helps you build
secure web apps more smoothly. The IGLU Ory Kratos example is open source and available
on github, please consider
starring the repository.
If you want to skip set up and managing Kubernetes, Docker and others, check out Ory Network for the fastest way to run Ory services.