How to Create a Secure Login Page with Keycloak and Flutter using flutter_appauth Package
Integrating a robust authentication system in your mobile application is crucial for security and user management. Keycloak, an open-source identity and access management solution, simplifies this process by providing comprehensive authentication and authorization capabilities. In this article, we will walk you through creating a secure login page in a Flutter application using the flutter_appauth
package and Keycloak. This step-by-step guide covers everything from setting up a Keycloak realm and client to configuring your Flutter app for authentication.
Introduction to Keycloak and Flutter AppAuth
Keycloak
Keycloak is an open-source identity and access management solution that provides features such as single sign-on (SSO), user federation, identity brokering, and social login. It simplifies securing applications by handling user authentication and authorization.
Flutter AppAuth
flutter_appauth
is a Flutter wrapper for the AppAuth library, which provides SDKs for communicating with OAuth 2.0 and OpenID Connect providers. This package allows Flutter apps to authenticate users using external identity providers.
Setting Up Keycloak
Installing Keycloak
Download Keycloak: Visit the Keycloak download page and download the latest version.
Extract the Archive: Extract the downloaded archive to a preferred directory.
Start Keycloak: Navigate to the Keycloak bin directory and start the server:
cd keycloak/bin ./standalone.sh
Access Keycloak Admin Console: Open your browser and navigate to
http://localhost:8080/auth
. Log in using the default admin credentials and create a new admin user.
Creating a Realm
Log in to the Admin Console: Navigate to
http://localhost:8080/auth/admin
and log in.Create a New Realm:
Click on the drop-down menu in the top-left corner.
Click on
Add realm
.Enter a name for the new realm (e.g.,
myrealm
) and clickCreate
.
Creating a Client
Navigate to Clients:
In the new realm, click on
Clients
in the left sidebar.Click
Create
.
Configure the Client:
Client ID: Enter a client ID (e.g.,
flutter-client
).Client Protocol: Ensure it is set to
openid-connect
.Root URL: Enter the root URL of your Flutter app (e.g.,
http://localhost:8080
for testing).Click
Save
.
Client Settings:
Access Type: Set to
public
.Valid Redirect URIs: Enter the redirect URI for your app (e.g.,
com.example.app:/oauthredirect
for mobile apps).Web Origins: Enter
*
or the specific origins that are allowed.Click
Save
.
Credentials: Note the
Client Secret
if the client is configured asconfidential
.
Setting Up Flutter Project
Installing flutter_appauth
Create a Flutter Project:
flutter create myapp cd myapp
Add Dependencies: Open
pubspec.yaml
and addflutter_appauth
andflutter_secure_storage
(for securely storing tokens):dependencies: flutter: sdk: flutter flutter_appauth: ^0.9.1+2 flutter_secure_storage: ^5.0.2
Install Dependencies:
flutter pub get
Configuring OAuth2 Settings
Android Configuration:
- Open
android/app/src/main/AndroidManifest.xml
and add the intent filter:
- Open
<activity
android:name="com.linusu.flutter_appauth.CallbackActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.example.app" android:host="oauthredirect" />
</intent-filter>
</activity>
iOS Configuration:
- Open
ios/Runner/Info.plist
and add the URL types:
- Open
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.example.app</string>
</array>
</dict>
</array>
Implementing the Login Page
Main Dart File (
lib/main.dart
):import 'package:flutter/material.dart'; import 'package:flutter_appauth/flutter_appauth.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter AppAuth Example', theme: ThemeData( primarySwatch: Colors.blue, ), home: LoginPage(), ); } } class LoginPage extends StatefulWidget { @override _LoginPageState createState() => _LoginPageState(); } class _LoginPageState extends State<LoginPage> { final FlutterAppAuth _appAuth = FlutterAppAuth(); final FlutterSecureStorage _secureStorage = FlutterSecureStorage(); final String _clientId = 'flutter-client'; final String _redirectUri = 'com.example.app:/oauthredirect'; final String _issuer = 'http://localhost:8080/auth/realms/myrealm'; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Login'), ), body: Center( child: ElevatedButton( onPressed: _login, child: Text('Login with Keycloak'), ), ), ); } Future<void> _login() async { try { final AuthorizationTokenResponse? result = await _appAuth.authorizeAndExchangeCode( AuthorizationTokenRequest( _clientId, _redirectUri, issuer: _issuer, scopes: ['openid', 'profile', 'email'], ), ); if (result != null) { await _secureStorage.write(key: 'access_token', value: result.accessToken); await _secureStorage.write(key: 'refresh_token', value: result.refreshToken); print('Login successful: ${result.accessToken}'); } } catch (e) { print('Login error: $e'); } } }
Conclusion
Setting up a secure login page with Keycloak and Flutter using the flutter_appauth
package is a powerful way to manage authentication in your mobile applications. Keycloak provides a comprehensive and flexible identity management solution, while flutter_appauth
simplifies the integration process. By following the steps outlined in this guide, you can implement a robust authentication system that enhances security and user experience.
Start integrating Keycloak with your Flutter applications today to leverage the benefits of centralized identity management and secure authentication. Happy coding!