Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,7 @@ jobs:
flet-flashlight
flet-geolocator
flet-lottie
flet-local-auth
flet-map
flet-permission-handler
flet-rive
Expand Down Expand Up @@ -995,6 +996,7 @@ jobs:
flet_flashlight \
flet_geolocator \
flet_lottie \
flet_local_auth \
flet_map \
flet_permission_handler \
flet_rive \
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## Unreleased

### New features

* Add `flet-local-auth` extension with a `LocalAuthentication` service for on-device biometric and credential authentication on Android, iOS, macOS, and Windows via the [`local_auth`](https://pub.dev/packages/local_auth) Flutter plugin. Linux and Web are not supported.

### Improvements

* Android host apps now use `FlutterFragmentActivity` and an AppCompat `LaunchTheme` so biometric authentication dialogs work on API 24–27. A `biometric` cross-platform permission bundle adds `NSFaceIDUsageDescription` for iOS and macOS builds.

## 0.86.3

### Bug fixes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.appveyor.flet_client

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterFragmentActivity

class MainActivity : FlutterActivity()
class MainActivity : FlutterFragmentActivity()
2 changes: 1 addition & 1 deletion client/android/app/src/main/res/values-night/styles.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<style name="LaunchTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
Expand Down
2 changes: 1 addition & 1 deletion client/android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<style name="LaunchTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
Expand Down
2 changes: 2 additions & 0 deletions client/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
</dict>
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to capture photos and video.</string>
<key>NSFaceIDUsageDescription</key>
<string>This app uses biometrics to authenticate you.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs access to location.</string>
<key>NSMicrophoneUsageDescription</key>
Expand Down
2 changes: 2 additions & 0 deletions client/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import 'package:flet_datatable2/flet_datatable2.dart' as flet_datatable2;
import "package:flet_flashlight/flet_flashlight.dart" as flet_flashlight;
import 'package:flet_geolocator/flet_geolocator.dart' as flet_geolocator;
import 'package:flet_lottie/flet_lottie.dart' as flet_lottie;
import 'package:flet_local_auth/flet_local_auth.dart' as flet_local_auth;
import 'package:flet_map/flet_map.dart' as flet_map;
import 'package:flet_permission_handler/flet_permission_handler.dart'
as flet_permission_handler;
Expand Down Expand Up @@ -57,6 +58,7 @@ void main([List<String>? args]) async {
flet_flashlight.Extension(),
flet_geolocator.Extension(),
flet_lottie.Extension(),
flet_local_auth.Extension(),
flet_map.Extension(),
flet_permission_handler.Extension(),
flet_secure_storage.Extension(),
Expand Down
2 changes: 2 additions & 0 deletions client/macos/Flutter/GeneratedPluginRegistrant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import device_info_plus
import file_picker
import flutter_secure_storage_darwin
import geolocator_apple
import local_auth_darwin
import media_kit_libs_macos_video
import media_kit_video
import package_info_plus
Expand All @@ -35,6 +36,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin"))
GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
LocalAuthPlugin.register(with: registry.registrar(forPlugin: "LocalAuthPlugin"))
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
Expand Down
47 changes: 47 additions & 0 deletions client/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,13 @@ packages:
relative: true
source: path
version: "0.86.0"
flet_local_auth:
dependency: "direct main"
description:
path: "../sdk/python/packages/flet-local-auth/src/flutter/flet_local_auth"
relative: true
source: path
version: "0.1.0"
flet_lottie:
dependency: "direct main"
description:
Expand Down Expand Up @@ -897,6 +904,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.1"
local_auth:
dependency: transitive
description:
name: local_auth
sha256: ecf24edf2283c509ecd217e3595f6f71034b68888d28ad1dae6bfa0857b816ac
url: "https://pub.dev"
source: hosted
version: "3.0.2"
local_auth_android:
dependency: transitive
description:
name: local_auth_android
sha256: fdb936d59ab945c7af297defd67bd1ed87b11b6db1bc16d01e94677a8f1c38ec
url: "https://pub.dev"
source: hosted
version: "2.0.9"
local_auth_darwin:
dependency: transitive
description:
name: local_auth_darwin
sha256: a8c3d4e17454111f7fd31ff72a31222359f6059f7fe956c2dcfe0f88f49826d4
url: "https://pub.dev"
source: hosted
version: "2.0.3"
local_auth_platform_interface:
dependency: transitive
description:
name: local_auth_platform_interface
sha256: f98b8e388588583d3f781f6806e4f4c9f9e189d898d27f0c249b93a1973dd122
url: "https://pub.dev"
source: hosted
version: "1.1.0"
local_auth_windows:
dependency: transitive
description:
name: local_auth_windows
sha256: be12c5b8ba5e64896983123655c5f67d2484ecfcc95e367952ad6e3bff94cb16
url: "https://pub.dev"
source: hosted
version: "2.0.1"
logging:
dependency: transitive
description:
Expand Down
3 changes: 3 additions & 0 deletions client/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ dependencies:
flet_lottie:
path: ../sdk/python/packages/flet-lottie/src/flutter/flet_lottie

flet_local_auth:
path: ../sdk/python/packages/flet-local-auth/src/flutter/flet_local_auth

flet_map:
path: ../sdk/python/packages/flet-map/src/flutter/flet_map

Expand Down
3 changes: 3 additions & 0 deletions client/windows/flutter/generated_plugin_registrant.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <geolocator_windows/geolocator_windows.h>
#include <local_auth_windows/local_auth_plugin.h>
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
#include <media_kit_video/media_kit_video_plugin_c_api.h>
#include <pasteboard/pasteboard_plugin.h>
Expand All @@ -34,6 +35,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
GeolocatorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("GeolocatorWindows"));
LocalAuthPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("LocalAuthPlugin"));
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
MediaKitVideoPluginCApiRegisterWithRegistrar(
Expand Down
1 change: 1 addition & 0 deletions client/windows/flutter/generated_plugins.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
connectivity_plus
flutter_secure_storage_windows
geolocator_windows
local_auth_windows
media_kit_libs_windows_video
media_kit_video
pasteboard
Expand Down
3 changes: 3 additions & 0 deletions sdk/python/examples/apps/flet_build_test/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies = [
"flet-flashlight",
"flet-geolocator",
"flet-lottie",
"flet-local-auth",
"flet-map",
"flet-permission-handler",
"flet-rive",
Expand Down Expand Up @@ -52,6 +53,7 @@ flet-datatable2 = { path = "../../../packages/flet-datatable2", editable = true
flet-flashlight = { path = "../../../packages/flet-flashlight", editable = true }
flet-geolocator = { path = "../../../packages/flet-geolocator", editable = true }
flet-lottie = { path = "../../../packages/flet-lottie", editable = true }
flet-local-auth = { path = "../../../packages/flet-local-auth", editable = true }
flet-map = { path = "../../../packages/flet-map", editable = true }
flet-permission-handler = { path = "../../../packages/flet-permission-handler", editable = true }
flet-rive = { path = "../../../packages/flet-rive", editable = true }
Expand All @@ -73,6 +75,7 @@ flet-datatable2 = "../../../packages/flet-datatable2"
flet-flashlight = "../../../packages/flet-flashlight"
flet-geolocator = "../../../packages/flet-geolocator"
flet-lottie = "../../../packages/flet-lottie"
flet-local-auth = "../../../packages/flet-local-auth"
flet-map = "../../../packages/flet-map"
flet-permission-handler = "../../../packages/flet-permission-handler"
flet-rive = "../../../packages/flet-rive"
Expand Down
52 changes: 52 additions & 0 deletions sdk/python/examples/extensions/local_auth/local_auth/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import flet as ft
import flet_local_auth as auth


def main(page: ft.Page):
status = ft.Text(theme_style=ft.TextThemeStyle.TITLE_MEDIUM)
local_auth = auth.LocalAuthentication()

async def refresh_capabilities(_):
supported = await local_auth.is_device_supported()
can_check = await local_auth.can_check_biometrics()
biometrics = await local_auth.get_available_biometrics()
status.value = (
f"Device supported: {supported}\n"
f"Biometric hardware: {can_check}\n"
f"Enrolled biometrics: {', '.join(b.value for b in biometrics) or 'none'}"
)

async def authenticate(_):
try:
ok = await local_auth.authenticate(
"Authenticate to continue",
android_messages=auth.AndroidAuthMessages(
sign_in_title="Unlock",
cancel_button="Not now",
),
)
status.value = f"Authenticated: {ok}"
except auth.LocalAuthException as e:
status.value = f"Authentication failed: {e.code.value}"

page.add(
ft.SafeArea(
content=ft.Column(
spacing=16,
controls=[
ft.Container(
bgcolor=ft.Colors.SURFACE_CONTAINER_HIGHEST,
border_radius=12,
padding=16,
content=status,
),
ft.Button("Check capabilities", on_click=refresh_capabilities),
ft.Button("Authenticate", on_click=authenticate),
],
),
)
)


if __name__ == "__main__":
ft.run(main)
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[project]
name = "local_auth"
version = "1.0.0"
description = "Prompts for on-device biometric or credential authentication."
requires-python = ">=3.10"
keywords = ["local auth", "biometric", "example", "services", "async"]
authors = [{ name = "Flet team", email = "hello@flet.dev" }]
dependencies = ["flet", "flet-local-auth"]

[dependency-groups]
dev = ["flet-cli", "flet-desktop", "flet-web"]

[tool.flet.gallery]
categories = ["Utility/LocalAuthentication"]

[tool.flet.metadata]
title = "Local authentication"
controls = ["SafeArea", "Column", "Page", "LocalAuthentication", "Button", "Text"]
layout_pattern = "inline-actions"
complexity = "basic"
features = ["biometric authentication", "device capability checks"]

[tool.flet]
org = "dev.flet"
company = "Flet"
copyright = "Copyright (C) 2023-2026 by Flet"
platforms = ["ios", "android", "windows", "macos"]
11 changes: 11 additions & 0 deletions sdk/python/packages/flet-cli/src/flet_cli/commands/build_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,17 @@ def __init__(self, parser: argparse.ArgumentParser) -> None:
},
"android_features": {},
},
"biometric": {
"ios_info_plist": {
"NSFaceIDUsageDescription": "This app uses biometrics to authenticate you." # noqa: E501
},
"macos_info_plist": {
"NSFaceIDUsageDescription": "This app uses biometrics to authenticate you." # noqa: E501
},
"macos_entitlements": {},
"android_permissions": {},
"android_features": {},
},
}

# create and display build-platform-matrix table
Expand Down
3 changes: 3 additions & 0 deletions sdk/python/packages/flet-local-auth/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
3 changes: 3 additions & 0 deletions sdk/python/packages/flet-local-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Flet Local Authentication

`LocalAuthentication` service for Flet apps. Authenticate users with biometrics, PIN, passcode, or pattern via the [`local_auth`](https://pub.dev/packages/local_auth) Flutter plugin.
26 changes: 26 additions & 0 deletions sdk/python/packages/flet-local-auth/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[project]
name = "flet-local-auth"
version = "0.1.0"
description = "Local authentication service for Flet"
authors = [{name = "Appveyor Systems Inc.", email = "hello@flet.dev"}]
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"flet",
]

[project.urls]
Homepage = "https://flet.dev"
Documentation = "https://flet.dev/docs/services/localauthentication"
Repository = "https://github.com/flet-dev/flet/tree/main/sdk/python/packages/flet-local-auth"
Issues = "https://github.com/flet-dev/flet/issues"

[tool.setuptools.package-data]
"flutter.flet_local_auth" = [
"pubspec.yaml",
"lib/**",
]

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from flet_local_auth.local_auth import LocalAuthentication
from flet_local_auth.types import (
AndroidAuthMessages,
BiometricType,
IOSAuthMessages,
LocalAuthErrorCode,
LocalAuthException,
WindowsAuthMessages,
)

__all__ = [
"AndroidAuthMessages",
"BiometricType",
"IOSAuthMessages",
"LocalAuthErrorCode",
"LocalAuthentication",
"LocalAuthException",
"WindowsAuthMessages",
]
Loading