Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7ccd968
[local_auth] Windows support.
azchohfi Jan 27, 2022
3906da5
Merge branch 'main' into local_auth_windows
azchohfi Feb 17, 2022
70c341d
Merge branch 'main' into local_auth_windows
azchohfi Feb 23, 2022
c492f89
Merge branch 'main' into local_auth_windows
azchohfi Feb 24, 2022
c997ad8
Handling biometricOnly parameter.
azchohfi Feb 25, 2022
9cf0a1a
Merge branch 'main' into local_auth_windows
azchohfi Apr 7, 2022
975ca8d
Fixed readme
azchohfi Apr 7, 2022
3fcbca7
[local_auth] Fix version and readme.
azchohfi Apr 8, 2022
34afbf5
Merge branch 'main' into local_auth_windows
azchohfi Apr 15, 2022
835f5cc
[local_auth] Small fixes.
azchohfi Apr 15, 2022
9eaba3c
Small fix.
azchohfi Apr 15, 2022
22ec14c
Fixed tests.
azchohfi Apr 15, 2022
9349aab
Added local_auth_windows tests.
azchohfi Apr 15, 2022
1032693
PR Feedback.
azchohfi Apr 18, 2022
1659e49
Merge branch 'local_auth_windows' of https://github.com/azchohfi/plug…
azchohfi Apr 18, 2022
8c7a87b
Fixed tests.
azchohfi Apr 18, 2022
bf47529
Added more tests.
azchohfi Apr 18, 2022
8143983
Revert changes in local_auth.
azchohfi Apr 19, 2022
bcf105b
Merge branch 'main' into local_auth_windows
azchohfi Apr 25, 2022
a4f02f4
Merge branch 'main' into local_auth_windows
azchohfi Apr 26, 2022
7449a5c
Merge branch 'main' into local_auth_windows
azchohfi May 9, 2022
fb26c93
Merge branch 'main' into local_auth_windows
azchohfi May 10, 2022
e9ab4ef
[local_auth_windows] Fixed authors list.
azchohfi May 10, 2022
30f0958
[local_auth_windows] Fixed changelog.
azchohfi May 10, 2022
97e1ee9
[local_auth_windows] PR feedback.
azchohfi May 12, 2022
40aa9a2
Merge branch 'main' into local_auth_windows
azchohfi May 12, 2022
6813b7b
Fixed build
azchohfi May 13, 2022
47823c6
Fixed format.
azchohfi May 13, 2022
45ceb6e
Merge branch 'main' into local_auth_windows
azchohfi May 13, 2022
271a49e
Applied more PR feedback.
azchohfi May 13, 2022
e1e24a6
Added C++ comments.
azchohfi May 13, 2022
cabc43e
Small doc fixes.
azchohfi May 13, 2022
34a58de
Merge branch 'main' into local_auth_windows
azchohfi May 16, 2022
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
Prev Previous commit
Next Next commit
Fixed tests.
  • Loading branch information
azchohfi committed Apr 18, 2022
commit 8c7a87bf43a43790040a8e282de559075a190de8
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,9 @@ class _MyAppState extends State<MyApp> {
return;
}

setState(
() {
_authorized = authenticated ? 'Authorized' : 'Not Authorized';
});
setState(() {
_authorized = authenticated ? 'Authorized' : 'Not Authorized';
});
}

Future<void> _authenticateWithBiometrics() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ add_subdirectory(${FLUTTER_MANAGED_DIR})
add_subdirectory("runner")

# Enable the test target.
set(local_auth_windows_tests TRUE)
set(include_local_auth_windows_tests TRUE)
# Provide an alias for the test target using the name expected by repo tooling.
add_custom_target(unit_tests DEPENDS local_auth_windows_test)

Expand Down
11 changes: 8 additions & 3 deletions packages/local_auth/local_auth_windows/windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@ endif()

include_directories(BEFORE SYSTEM ${CMAKE_BINARY_DIR}/include)

list(APPEND PLUGIN_SOURCES
"local_auth_plugin.cpp"
)

add_library(${PLUGIN_NAME} SHARED
"include/local_auth_windows/local_auth_plugin.h"
"local_auth_plugin.cpp"
"local_auth_windows.cpp"
"local_auth.h"
${PLUGIN_SOURCES}
)
apply_standard_settings(${PLUGIN_NAME})
Expand All @@ -67,7 +72,6 @@ enable_testing()
# TODO(stuartmorgan): Consider using a single shared, pre-checked-in googletest
# instance rather than downloading for each plugin. This approach makes sense
# for a template, but not for a monorepo with many plugins.
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/release-1.11.0.zip
Expand All @@ -84,11 +88,12 @@ FetchContent_MakeAvailable(googletest)
add_executable(${TEST_RUNNER}
test/mocks.h
test/local_auth_plugin_test.cpp
test/local_auth_test.cpp
${PLUGIN_SOURCES}
)
apply_standard_settings(${TEST_RUNNER})
target_include_directories(${TEST_RUNNER} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
target_compile_features(${TEST_RUNNER} PRIVATE cxx_std_20)
target_compile_options(${TEST_RUNNER} PRIVATE /await)
target_link_libraries(${TEST_RUNNER} PRIVATE flutter_wrapper_plugin)
target_link_libraries(${TEST_RUNNER} PRIVATE windowsapp)
target_link_libraries(${TEST_RUNNER} PRIVATE gtest_main gmock)
Expand Down
72 changes: 72 additions & 0 deletions packages/local_auth/local_auth_windows/windows/local_auth.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <UserConsentVerifierInterop.h>

#include "include/local_auth_windows/local_auth_plugin.h"

// This must be included before many other Windows headers.
#include <flutter/encodable_value.h>
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>
#include <pplawait.h>
#include <ppltasks.h>
#include <windows.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Security.Credentials.UI.h>
#include <winstring.h>

#include <map>
#include <memory>
#include <sstream>

namespace local_auth_windows {

using namespace flutter;
using namespace winrt;

class UserConsentVerifier {
public:
UserConsentVerifier() {}
virtual ~UserConsentVerifier() = default;

virtual Windows::Foundation::IAsyncOperation<
Windows::Security::Credentials::UI::UserConsentVerificationResult>
RequestVerificationForWindowAsync(std::wstring localizedReason) = 0;
virtual Windows::Foundation::IAsyncOperation<
Windows::Security::Credentials::UI::UserConsentVerifierAvailability>
CheckAvailabilityAsync() = 0;

// Disallow copy and move.
UserConsentVerifier(const UserConsentVerifier&) = delete;
UserConsentVerifier& operator=(const UserConsentVerifier&) = delete;
};

class LocalAuthPlugin : public Plugin {
public:
static void RegisterWithRegistrar(PluginRegistrarWindows* registrar);

LocalAuthPlugin(std::function<HWND()> window_provider);
LocalAuthPlugin(std::unique_ptr<UserConsentVerifier> user_consent_verifier);

// Called when a method is called on this plugin's channel from Dart.
void HandleMethodCall(const MethodCall<EncodableValue>& method_call,
std::unique_ptr<MethodResult<EncodableValue>> result);

virtual ~LocalAuthPlugin();

private:
std::unique_ptr<UserConsentVerifier> user_consent_verifier_;

winrt::fire_and_forget Authenticate(
const MethodCall<EncodableValue>& method_call,
std::unique_ptr<MethodResult<EncodableValue>> result);
winrt::fire_and_forget GetAvailableBiometrics(
std::unique_ptr<MethodResult<EncodableValue>> result);
winrt::fire_and_forget IsDeviceSupported(
std::unique_ptr<MethodResult<EncodableValue>> result);
};

} // namespace local_auth_windows
163 changes: 86 additions & 77 deletions packages/local_auth/local_auth_windows/windows/local_auth_plugin.cpp
Original file line number Diff line number Diff line change
@@ -1,26 +1,9 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/local_auth_windows/local_auth_plugin.h"

// This must be included before many other Windows headers.
#include <UserConsentVerifierInterop.h>
#include <flutter/encodable_value.h>
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>
#include <pplawait.h>
#include <ppltasks.h>
#include <windows.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Security.Credentials.UI.h>
#include <winstring.h>

#include <map>
#include <memory>
#include <sstream>

namespace {
#include "local_auth.h"

namespace local_auth_windows {

using namespace flutter;
using namespace winrt;
Expand All @@ -45,37 +28,77 @@ HWND GetRootWindow(flutter::FlutterView* view) {
}

// Converts the given UTF-8 string to UTF-16.
std::wstring s2ws(const std::string& s) {
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
std::wstring r(len, L'\0');
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, &r[0], len);
return r;
std::wstring Utf16FromUtf8(const std::string& utf8_string) {
if (utf8_string.empty()) {
return std::wstring();
}
int target_length =
::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(),
static_cast<int>(utf8_string.length()), nullptr, 0);
if (target_length == 0) {
return std::wstring();
}
std::wstring utf16_string;
utf16_string.resize(target_length);
int converted_length =
::MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8_string.data(),
static_cast<int>(utf8_string.length()),
utf16_string.data(), target_length);
if (converted_length == 0) {
return std::wstring();
}
return utf16_string;
}

class LocalAuthPlugin : public Plugin {
class UserConsentVerifierImpl : public UserConsentVerifier {
public:
static void RegisterWithRegistrar(PluginRegistrarWindows* registrar);
explicit UserConsentVerifierImpl(std::function<HWND()> window_provider)
: get_root_window_(std::move(window_provider)){};
virtual ~UserConsentVerifierImpl() = default;

Windows::Foundation::IAsyncOperation<
Windows::Security::Credentials::UI::UserConsentVerificationResult>
RequestVerificationForWindowAsync(std::wstring localizedReason) override {
auto userConsentVerifierInterop = winrt::get_activation_factory<
Windows::Security::Credentials::UI::UserConsentVerifier,
IUserConsentVerifierInterop>();

auto hWnd = get_root_window_();

HSTRING hReason;
if (WindowsCreateString(localizedReason.c_str(),
static_cast<uint32_t>(localizedReason.size()),
&hReason) != S_OK) {
return Windows::Security::Credentials::UI::UserConsentVerificationResult::
Canceled;
}

auto consentResult =
co_await winrt::capture<Windows::Foundation::IAsyncOperation<
Windows::Security::Credentials::UI::UserConsentVerificationResult>>(
userConsentVerifierInterop,
&::IUserConsentVerifierInterop::RequestVerificationForWindowAsync,
hWnd, hReason);

LocalAuthPlugin(flutter::PluginRegistrarWindows* registrar);
WindowsDeleteString(hReason);

virtual ~LocalAuthPlugin();
return consentResult;
}

Windows::Foundation::IAsyncOperation<
Windows::Security::Credentials::UI::UserConsentVerifierAvailability>
CheckAvailabilityAsync() override {
return Windows::Security::Credentials::UI::UserConsentVerifier::
CheckAvailabilityAsync();
}

// Disallow copy and move.
UserConsentVerifierImpl(const UserConsentVerifierImpl&) = delete;
UserConsentVerifierImpl& operator=(const UserConsentVerifierImpl&) = delete;

private:
flutter::PluginRegistrarWindows* registrar_;

// Called when a method is called on this plugin's channel from Dart.
void HandleMethodCall(const MethodCall<EncodableValue>& method_call,
std::unique_ptr<MethodResult<EncodableValue>> result);

winrt::fire_and_forget Authenticate(
const MethodCall<EncodableValue>& method_call,
std::unique_ptr<MethodResult<EncodableValue>> result);
winrt::fire_and_forget GetAvailableBiometrics(
std::unique_ptr<MethodResult<EncodableValue>> result);
winrt::fire_and_forget IsDeviceSupported(
std::unique_ptr<MethodResult<EncodableValue>> result);
// The provider for the root window to attach the dialog to.
std::function<HWND()> get_root_window_;
};

// static
Expand All @@ -84,7 +107,8 @@ void LocalAuthPlugin::RegisterWithRegistrar(PluginRegistrarWindows* registrar) {
registrar->messenger(), "plugins.flutter.io/local_auth_windows",
&StandardMethodCodec::GetInstance());

auto plugin = std::make_unique<LocalAuthPlugin>(registrar);
auto plugin = std::make_unique<LocalAuthPlugin>(
[registrar]() { return GetRootWindow(registrar->GetView()); });

channel->SetMethodCallHandler(
[plugin_pointer = plugin.get()](const auto& call, auto result) {
Expand All @@ -95,8 +119,13 @@ void LocalAuthPlugin::RegisterWithRegistrar(PluginRegistrarWindows* registrar) {
}

// Default constructor for LocalAuthPlugin
LocalAuthPlugin::LocalAuthPlugin(flutter::PluginRegistrarWindows* registrar)
: registrar_(registrar) {}
LocalAuthPlugin::LocalAuthPlugin(std::function<HWND()> window_provider)
: user_consent_verifier_(std::make_unique<UserConsentVerifierImpl>(
std::move(window_provider))) {}

LocalAuthPlugin::LocalAuthPlugin(
std::unique_ptr<UserConsentVerifier> user_consent_verifier)
: user_consent_verifier_(std::move(user_consent_verifier)) {}

LocalAuthPlugin::~LocalAuthPlugin() {}

Expand All @@ -118,7 +147,7 @@ void LocalAuthPlugin::HandleMethodCall(
winrt::fire_and_forget LocalAuthPlugin::Authenticate(
const MethodCall<EncodableValue>& method_call,
std::unique_ptr<MethodResult<EncodableValue>> result) {
auto reasonW = s2ws(GetArgument<std::string>(
auto reasonW = Utf16FromUtf8(GetArgument<std::string>(
"localizedReason", method_call.arguments(), std::string()));

auto biometricOnly =
Expand All @@ -129,8 +158,8 @@ winrt::fire_and_forget LocalAuthPlugin::Authenticate(
co_return;
}

auto ucvAvailability = co_await Windows::Security::Credentials::UI::
UserConsentVerifier::CheckAvailabilityAsync();
auto ucvAvailability =
co_await user_consent_verifier_->CheckAvailabilityAsync();

if (ucvAvailability ==
Windows::Security::Credentials::UI::UserConsentVerifierAvailability::
Expand All @@ -149,39 +178,26 @@ winrt::fire_and_forget LocalAuthPlugin::Authenticate(
co_return;
}

auto userConsentVerifierInterop = winrt::get_activation_factory<
Windows::Security::Credentials::UI::UserConsentVerifier,
IUserConsentVerifierInterop>();

auto hWnd = GetRootWindow(registrar_->GetView());

HSTRING hReason;
WindowsCreateString(reasonW.c_str(), (uint32_t)reasonW.size(), &hReason);

try {
auto consentResult =
co_await winrt::capture<Windows::Foundation::IAsyncOperation<
Windows::Security::Credentials::UI::UserConsentVerificationResult>>(
userConsentVerifierInterop,
&::IUserConsentVerifierInterop::RequestVerificationForWindowAsync,
hWnd, hReason);
co_await user_consent_verifier_->RequestVerificationForWindowAsync(
reasonW);

result->Success(EncodableValue(
consentResult == Windows::Security::Credentials::UI::
UserConsentVerificationResult::Verified));
} catch (...) {
result->Success(EncodableValue(false));
}
WindowsDeleteString(hReason);
}

// Returns biometric types available on device
winrt::fire_and_forget LocalAuthPlugin::GetAvailableBiometrics(
std::unique_ptr<MethodResult<EncodableValue>> result) {
try {
flutter::EncodableList biometrics;
auto ucvAvailability = co_await Windows::Security::Credentials::UI::
UserConsentVerifier::CheckAvailabilityAsync();
auto ucvAvailability =
co_await user_consent_verifier_->CheckAvailabilityAsync();
if (ucvAvailability == Windows::Security::Credentials::UI::
UserConsentVerifierAvailability::Available) {
biometrics.push_back(EncodableValue("fingerprint"));
Expand All @@ -197,18 +213,11 @@ winrt::fire_and_forget LocalAuthPlugin::GetAvailableBiometrics(
// Returns whether the device supports Windows Hello or not
winrt::fire_and_forget LocalAuthPlugin::IsDeviceSupported(
std::unique_ptr<MethodResult<EncodableValue>> result) {
auto ucvAvailability = co_await Windows::Security::Credentials::UI::
UserConsentVerifier::CheckAvailabilityAsync();
auto ucvAvailability =
co_await user_consent_verifier_->CheckAvailabilityAsync();
result->Success(EncodableValue(
ucvAvailability == Windows::Security::Credentials::UI::
UserConsentVerifierAvailability::Available));
}

} // namespace

void LocalAuthPluginRegisterWithRegistrar(
FlutterDesktopPluginRegistrarRef registrar) {
LocalAuthPlugin::RegisterWithRegistrar(
PluginRegistrarManager::GetInstance()
->GetRegistrar<PluginRegistrarWindows>(registrar));
}
} // namespace local_auth_windows
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <flutter/plugin_registrar_windows.h>

#include "include/local_auth_windows/local_auth_plugin.h"
#include "local_auth.h"

void LocalAuthPluginRegisterWithRegistrar(
FlutterDesktopPluginRegistrarRef registrar) {
local_auth_windows::LocalAuthPlugin::RegisterWithRegistrar(
flutter::PluginRegistrarManager::GetInstance()
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
}
Loading