Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 550ba3c

Browse files
authored
[local_auth] Windows support. (#4806)
1 parent a692f84 commit 550ba3c

38 files changed

+2407
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Below is a list of people and organizations that have contributed
2+
# to the Flutter project. Names should be added to the list like so:
3+
#
4+
# Name/Organization <email address>
5+
6+
Google Inc.
7+
Alexandre Zollinger Chohfi <[email protected]>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 1.0.0
2+
3+
* Initial release of Windows support.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
Copyright 2013 The Flutter Authors. All rights reserved.
2+
3+
Redistribution and use in source and binary forms, with or without modification,
4+
are permitted provided that the following conditions are met:
5+
6+
* Redistributions of source code must retain the above copyright
7+
notice, this list of conditions and the following disclaimer.
8+
* Redistributions in binary form must reproduce the above
9+
copyright notice, this list of conditions and the following
10+
disclaimer in the documentation and/or other materials provided
11+
with the distribution.
12+
* Neither the name of Google Inc. nor the names of its
13+
contributors may be used to endorse or promote products derived
14+
from this software without specific prior written permission.
15+
16+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# local\_auth\_windows
2+
3+
The Windows implementation of [`local_auth`][1].
4+
5+
## Usage
6+
7+
This package is [endorsed][2], which means you can simply use `local_auth`
8+
normally. This package will be automatically included in your app when you do.
9+
10+
[1]: https://pub.dev/packages/local_auth
11+
[2]: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#endorsed-federated-plugin
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
12+
# IntelliJ related
13+
*.iml
14+
*.ipr
15+
*.iws
16+
.idea/
17+
18+
# The .vscode folder contains launch configuration and tasks you configure in
19+
# VS Code which you may wish to be included in version control, so this line
20+
# is commented out by default.
21+
#.vscode/
22+
23+
# Flutter/Dart/Pub related
24+
**/doc/api/
25+
**/ios/Flutter/.last_build_id
26+
.dart_tool/
27+
.flutter-plugins
28+
.flutter-plugins-dependencies
29+
.packages
30+
.pub-cache/
31+
.pub/
32+
/build/
33+
34+
# Web related
35+
lib/generated_plugin_registrant.dart
36+
37+
# Symbolication related
38+
app.*.symbols
39+
40+
# Obfuscation related
41+
app.*.map.json
42+
43+
# Android Studio will place build artifacts here
44+
/android/app/debug
45+
/android/app/profile
46+
/android/app/release
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: c860cba910319332564e1e9d470a17074c1f2dfd
8+
channel: stable
9+
10+
project_type: app
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# local_auth_example
2+
3+
Demonstrates how to use the local_auth plugin.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter_test/flutter_test.dart';
6+
import 'package:integration_test/integration_test.dart';
7+
8+
import 'package:local_auth_windows/local_auth_windows.dart';
9+
10+
void main() {
11+
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
12+
13+
testWidgets('canCheckBiometrics', (WidgetTester tester) async {
14+
expect(
15+
LocalAuthWindows().getEnrolledBiometrics(),
16+
completion(isList),
17+
);
18+
});
19+
}
Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// ignore_for_file: public_member_api_docs
6+
7+
import 'dart:async';
8+
9+
import 'package:flutter/material.dart';
10+
import 'package:flutter/services.dart';
11+
import 'package:local_auth_platform_interface/local_auth_platform_interface.dart';
12+
import 'package:local_auth_windows/local_auth_windows.dart';
13+
14+
void main() {
15+
runApp(const MyApp());
16+
}
17+
18+
class MyApp extends StatefulWidget {
19+
const MyApp({Key? key}) : super(key: key);
20+
21+
@override
22+
State<MyApp> createState() => _MyAppState();
23+
}
24+
25+
class _MyAppState extends State<MyApp> {
26+
_SupportState _supportState = _SupportState.unknown;
27+
bool? _deviceSupportsBiometrics;
28+
List<BiometricType>? _enrolledBiometrics;
29+
String _authorized = 'Not Authorized';
30+
bool _isAuthenticating = false;
31+
32+
@override
33+
void initState() {
34+
super.initState();
35+
LocalAuthPlatform.instance.isDeviceSupported().then(
36+
(bool isSupported) => setState(() => _supportState = isSupported
37+
? _SupportState.supported
38+
: _SupportState.unsupported),
39+
);
40+
}
41+
42+
Future<void> _checkBiometrics() async {
43+
late bool deviceSupportsBiometrics;
44+
try {
45+
deviceSupportsBiometrics =
46+
await LocalAuthPlatform.instance.deviceSupportsBiometrics();
47+
} on PlatformException catch (e) {
48+
deviceSupportsBiometrics = false;
49+
print(e);
50+
}
51+
if (!mounted) {
52+
return;
53+
}
54+
55+
setState(() {
56+
_deviceSupportsBiometrics = deviceSupportsBiometrics;
57+
});
58+
}
59+
60+
Future<void> _getEnrolledBiometrics() async {
61+
late List<BiometricType> availableBiometrics;
62+
try {
63+
availableBiometrics =
64+
await LocalAuthPlatform.instance.getEnrolledBiometrics();
65+
} on PlatformException catch (e) {
66+
availableBiometrics = <BiometricType>[];
67+
print(e);
68+
}
69+
if (!mounted) {
70+
return;
71+
}
72+
73+
setState(() {
74+
_enrolledBiometrics = availableBiometrics;
75+
});
76+
}
77+
78+
Future<void> _authenticate() async {
79+
bool authenticated = false;
80+
try {
81+
setState(() {
82+
_isAuthenticating = true;
83+
_authorized = 'Authenticating';
84+
});
85+
authenticated = await LocalAuthPlatform.instance.authenticate(
86+
localizedReason: 'Let OS determine authentication method',
87+
authMessages: <AuthMessages>[const WindowsAuthMessages()],
88+
options: const AuthenticationOptions(
89+
useErrorDialogs: true,
90+
stickyAuth: true,
91+
),
92+
);
93+
setState(() {
94+
_isAuthenticating = false;
95+
});
96+
} on PlatformException catch (e) {
97+
print(e);
98+
setState(() {
99+
_isAuthenticating = false;
100+
_authorized = 'Error - ${e.message}';
101+
});
102+
return;
103+
}
104+
if (!mounted) {
105+
return;
106+
}
107+
108+
setState(
109+
() => _authorized = authenticated ? 'Authorized' : 'Not Authorized');
110+
}
111+
112+
Future<void> _authenticateWithBiometrics() async {
113+
bool authenticated = false;
114+
try {
115+
setState(() {
116+
_isAuthenticating = true;
117+
_authorized = 'Authenticating';
118+
});
119+
authenticated = await LocalAuthPlatform.instance.authenticate(
120+
localizedReason:
121+
'Scan your fingerprint (or face or whatever) to authenticate',
122+
authMessages: <AuthMessages>[const WindowsAuthMessages()],
123+
options: const AuthenticationOptions(
124+
useErrorDialogs: true,
125+
stickyAuth: true,
126+
biometricOnly: true,
127+
),
128+
);
129+
setState(() {
130+
_isAuthenticating = false;
131+
_authorized = 'Authenticating';
132+
});
133+
} on PlatformException catch (e) {
134+
print(e);
135+
setState(() {
136+
_isAuthenticating = false;
137+
_authorized = 'Error - ${e.message}';
138+
});
139+
return;
140+
}
141+
if (!mounted) {
142+
return;
143+
}
144+
145+
final String message = authenticated ? 'Authorized' : 'Not Authorized';
146+
setState(() {
147+
_authorized = message;
148+
});
149+
}
150+
151+
Future<void> _cancelAuthentication() async {
152+
await LocalAuthPlatform.instance.stopAuthentication();
153+
setState(() => _isAuthenticating = false);
154+
}
155+
156+
@override
157+
Widget build(BuildContext context) {
158+
return MaterialApp(
159+
home: Scaffold(
160+
appBar: AppBar(
161+
title: const Text('Plugin example app'),
162+
),
163+
body: ListView(
164+
padding: const EdgeInsets.only(top: 30),
165+
children: <Widget>[
166+
Column(
167+
mainAxisAlignment: MainAxisAlignment.center,
168+
children: <Widget>[
169+
if (_supportState == _SupportState.unknown)
170+
const CircularProgressIndicator()
171+
else if (_supportState == _SupportState.supported)
172+
const Text('This device is supported')
173+
else
174+
const Text('This device is not supported'),
175+
const Divider(height: 100),
176+
Text(
177+
'Device supports biometrics: $_deviceSupportsBiometrics\n'),
178+
ElevatedButton(
179+
onPressed: _checkBiometrics,
180+
child: const Text('Check biometrics'),
181+
),
182+
const Divider(height: 100),
183+
Text('Enrolled biometrics: $_enrolledBiometrics\n'),
184+
ElevatedButton(
185+
onPressed: _getEnrolledBiometrics,
186+
child: const Text('Get enrolled biometrics'),
187+
),
188+
const Divider(height: 100),
189+
Text('Current State: $_authorized\n'),
190+
if (_isAuthenticating)
191+
ElevatedButton(
192+
onPressed: _cancelAuthentication,
193+
child: Row(
194+
mainAxisSize: MainAxisSize.min,
195+
children: const <Widget>[
196+
Text('Cancel Authentication'),
197+
Icon(Icons.cancel),
198+
],
199+
),
200+
)
201+
else
202+
Column(
203+
children: <Widget>[
204+
ElevatedButton(
205+
onPressed: _authenticate,
206+
child: Row(
207+
mainAxisSize: MainAxisSize.min,
208+
children: const <Widget>[
209+
Text('Authenticate'),
210+
Icon(Icons.perm_device_information),
211+
],
212+
),
213+
),
214+
ElevatedButton(
215+
onPressed: _authenticateWithBiometrics,
216+
child: Row(
217+
mainAxisSize: MainAxisSize.min,
218+
children: <Widget>[
219+
Text(_isAuthenticating
220+
? 'Cancel'
221+
: 'Authenticate: biometrics only'),
222+
const Icon(Icons.fingerprint),
223+
],
224+
),
225+
),
226+
],
227+
),
228+
],
229+
),
230+
],
231+
),
232+
),
233+
);
234+
}
235+
}
236+
237+
enum _SupportState {
238+
unknown,
239+
supported,
240+
unsupported,
241+
}

0 commit comments

Comments
 (0)