keycloak_client 1.0.1 copy "keycloak_client: ^1.0.1" to clipboard
keycloak_client: ^1.0.1 copied to clipboard

A Flutter package for Keycloak authentication using the Authorization Code flow.

keycloak_client #

Cross-platform Keycloak authentication for Flutter with:

  • Authorization Code + PKCE
  • mobile deep links
  • desktop loopback callbacks
  • web redirect callbacks
  • secure credential persistence
  • automatic token refresh
  • auth and user streams

Install #

dependencies:
  keycloak_client: ^1.0.0

Quick Start #

import 'package:keycloak_client/keycloak_client.dart';

final client = KeycloakClient(
  config: ClientConfig(
    baseUrl: 'https://auth.example.com',
    realm: 'my-realm',
    clientId: 'my-client',
  ),
);

Initialize early:

@override
void initState() {
  super.initState();
  client.initialize();
}

@override
void dispose() {
  client.dispose();
  super.dispose();
}

Login:

await client.login();

Logout:

await client.logout();

Get a valid access token:

final token = await client.getAuthToken();

Configuration #

Everything is configured through ClientConfig.

final client = KeycloakClient(
  config: ClientConfig(
    baseUrl: 'https://auth.example.com',
    realm: 'my-realm',
    clientId: 'my-client',
  ),
);

Main fields:

  • baseUrl: Keycloak server root
  • realm: Keycloak realm name
  • clientId: OAuth client ID
  • clientSecret: for confidential clients only
  • scopes: defaults to openid, email, profile
  • logLevel: package logging verbosity

Platform config defaults:

  • MobileConfig.redirectUri: myapp://auth
  • DesktopConfig.redirectUri: https://winchetechnologies.co.uk/tools/oauth_redirect
  • DesktopConfig.loopbackUri: http://localhost:8765/callback
  • WebConfig.redirectUri: https://winchetechnologies.co.uk/tools/oauth_redirect

For desktop, these two values have different jobs:

  • DesktopConfig.redirectUri: the URI sent to Keycloak
  • DesktopConfig.loopbackUri: the local URI the desktop app listens on

Dev Redirect Helper #

Recent Keycloak versions can be awkward about using localhost as an allowed redirect URI. To make local development easier, this package ships with a public redirect endpoint by default:

https://winchetechnologies.co.uk/tools/oauth_redirect

The idea is:

  1. Register that public URL in Keycloak as a valid redirect URI.
  2. Use that public URL as DesktopConfig.redirectUri during desktop dev.
  3. Keep DesktopConfig.loopbackUri on a local address such as http://localhost:8765/callback.
  4. Keycloak redirects the browser to the public helper page after login.
  5. That page lets the you enter your loopback uri.
  6. The page forwards the full callback, including Keycloak query parameters, to the local loopback server.

Web Startup #

Web login is redirect-based. Call handleWebCallback(Uri.base) on startup before rendering the app:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  if (kIsWeb) {
    await client.handleWebCallback(Uri.base);
  }

  runApp(const MyApp());
}

On web, login() redirects the current tab and does not complete before navigation.

Streams #

Auth state:

StreamBuilder<AuthState>(
  stream: client.onAuthChange,
  builder: (context, snapshot) {
    final state = snapshot.data ?? AuthState.unknown;
    return Text('$state');
  },
);

User info:

StreamBuilder<UserInfo?>(
  stream: client.onUserChange,
  builder: (context, snapshot) {
    final user = snapshot.data;
    return Text(user?.username ?? 'No user');
  },
);

Platform Setup #

Keycloak #

Register the correct redirect URIs in your Keycloak client.

Typical values:

  • Android/iOS: myapp://auth
  • Desktop dev: https://winchetechnologies.co.uk/tools/oauth_redirect
  • Desktop local listener: http://localhost:8765/callback
  • Web dev: https://winchetechnologies.co.uk/tools/oauth_redirect
  • Web prod: your real public web callback URL

For desktop dev with the helper endpoint:

  • redirectUri is the public URL you register in Keycloak
  • loopbackUri is the local listener inside your desktop app
  • the helper page bridges the public redirect back to the local loopback server

Android #

Add the deep-link intent filter to your MainActivity in android/app/src/main/AndroidManifest.xml:

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTop">
    <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="myapp" android:host="auth"/>
    </intent-filter>
</activity>

Also ensure internet permission exists:

<uses-permission android:name="android.permission.INTERNET"/>

Your MobileConfig.redirectUri must match the scheme/host you register here.

iOS #

Add your custom scheme to ios/Runner/Info.plist:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLName</key>
    <string>myapp</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myapp</string>
    </array>
  </dict>
</array>

Only the scheme goes in CFBundleURLSchemes. For the default MobileConfig.redirectUri of myapp://auth, iOS registers myapp here and your Dart config keeps the full redirect URI.

macOS / Windows / Linux #

Desktop login uses a system browser plus a local HTTP listener.

Important fields:

  • DesktopConfig.redirectUri: the redirect URI sent to Keycloak
  • DesktopConfig.loopbackUri: the local URI the desktop app listens on (default: http://localhost:8765/callback)
  • DesktopConfig.loopbackTimeout: how long to wait for the callback

The app always listens on loopbackUri while Keycloak redirects to redirectUri. For local development:

  • register https://winchetechnologies.co.uk/tools/oauth_redirect in Keycloak
  • keep loopbackUri on a local port like http://localhost:8765/callback
  • when the helper page opens, enter that local port so it forwards the callback back to your app

Web #

For local development, you can use the same public helper endpoint:

web: const WebConfig(
  redirectUri: 'https://winchetechnologies.co.uk/tools/oauth_redirect',
),

For production, use your own public callback URL instead.

Always:

  • register the web redirect URI in Keycloak
  • call handleWebCallback(Uri.base) on app startup

Main API #

  • initialize(): restore any existing session
  • login(): start authentication
  • handleWebCallback(uri): resume a web redirect flow
  • logout(): clear session and notify Keycloak when possible
  • getAuthToken(): return a valid access token or null
  • reloadUser(): reload profile data from /userinfo
  • onAuthChange: stream of AuthState
  • onUserChange: stream of UserInfo?

Auth States #

  • AuthState.unknown
  • AuthState.signedOut
  • AuthState.signedIn
  • AuthState.sessionExpired

Exceptions #

The package throws typed exceptions:

  • KeycloakNetworkException
  • KeycloakServerException
  • KeycloakSessionExpiredException
  • KeycloakTimeoutException

Notes #

  • Call initialize() before login(), logout(), or reloadUser()
  • Credentials are stored with flutter_secure_storage
  • User profile data comes from Keycloak's /userinfo endpoint
5
likes
150
points
130
downloads

Documentation

API reference

Publisher

verified publisherwinchetechnologies.co.uk

Weekly Downloads

A Flutter package for Keycloak authentication using the Authorization Code flow.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

app_links, crypto, dio, flutter, flutter_secure_storage, logger, oauth2, url_launcher, web

More

Packages that depend on keycloak_client