Skip to content

Commit 79896c2

Browse files
committed
Don't try to focus the nonexistent Next button when holding Shift on a Hello TPM (PIN/biometrics) prompt. Initialize logging faster using reflection instead of stacktraces.
1 parent 60d2b3f commit 79896c2

File tree

3 files changed

+24
-14
lines changed

3 files changed

+24
-14
lines changed

AuthenticatorChooser/Startup.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public int OnExecute() {
4646
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
4747

4848
Logging.initialize(log.enabled, log.filename);
49-
logger = LogManager.GetCurrentClassLogger();
49+
logger = LogManager.GetLogger(typeof(Startup).FullName);
5050

5151
try {
5252
if (help) {

AuthenticatorChooser/WindowsSecurityKeyChooser.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class WindowsSecurityKeyChooser: AbstractSecurityKeyChooser<SystemWindow>
1515
private const string WINDOW_CLASS_NAME = "Credential Dialog Xaml Host";
1616
private const string ALT_TAB_CLASS_NAME = "XamlExplorerHostIslandWindow";
1717

18-
private static readonly Logger LOGGER = LogManager.GetCurrentClassLogger();
18+
private static readonly Logger LOGGER = LogManager.GetLogger(typeof(WindowsSecurityKeyChooser).FullName);
1919

2020
public bool skipAllNonSecurityKeyOptions { get; init; }
2121

@@ -54,7 +54,7 @@ public override void chooseUsbSecurityKey(SystemWindow fidoPrompt) {
5454
maxAttempts: 127, delay: Retrier.Delays.Power(TimeSpan.FromMilliseconds(1), max: TimeSpan.FromMilliseconds(500)));
5555
LOGGER.Trace("Found authenticator choices after {0:N3} sec", authenticatorChoicesStopwatch.Elapsed.TotalSeconds);
5656
} catch (Exception e) when (e is not OutOfMemoryException) {
57-
LOGGER.Error(e, "Could not find authenticator choices after retrying for {0:N3} sec due to the following exception. Giving up and not automatically selecting Security Key.",
57+
LOGGER.Warn(e, "Could not find authenticator choices after retrying for {0:N3} sec due to the following exception. Giving up and not automatically selecting Security Key.",
5858
authenticatorChoicesStopwatch.Elapsed.TotalSeconds);
5959
return;
6060
}
@@ -74,18 +74,19 @@ public override void chooseUsbSecurityKey(SystemWindow fidoPrompt) {
7474

7575
bool isShiftDown = Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift);
7676

77-
if (!isLocalWindowsHelloTpmPrompt || !isShiftDown) {
77+
if (!(isLocalWindowsHelloTpmPrompt && isShiftDown)) {
7878
((SelectionItemPattern) desiredChoice.GetCurrentPattern(SelectionItemPattern.Pattern)).Select();
79-
if (isLocalWindowsHelloTpmPrompt) {
80-
LOGGER.Info("Use another device selected after {0:N3} sec", overallStopwatch.Elapsed.TotalSeconds);
81-
return;
82-
} else {
83-
LOGGER.Info("USB security key selected");
84-
}
79+
LOGGER.Info("{choice} selected after {0:N3} sec", isLocalWindowsHelloTpmPrompt ? "Use another device" : "USB security key", overallStopwatch.Elapsed.TotalSeconds);
8580
}
8681

87-
AutomationElement nextButton = fidoEl!.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "OkButton"));
88-
if (isShiftDown) {
82+
if (isLocalWindowsHelloTpmPrompt) {
83+
return;
84+
}
85+
86+
AutomationElement? nextButton = fidoEl!.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "OkButton"));
87+
if (nextButton == null) {
88+
LOGGER.Error("Could not find Next button in Windows Security dialog box, skipping this dialog box instance");
89+
} else if (isShiftDown) {
8990
nextButton.SetFocus();
9091
LOGGER.Info("Shift is pressed, not submitting dialog box");
9192
} else if (!skipAllNonSecurityKeyOptions && !authenticatorChoices.All(choice => choice == desiredChoice || nameContainsAny(choice, I18N.getStrings(I18N.Key.SMARTPHONE)))) {
@@ -97,7 +98,7 @@ public override void chooseUsbSecurityKey(SystemWindow fidoPrompt) {
9798
LOGGER.Info("Next button pressed after {0:N3} sec", overallStopwatch.Elapsed.TotalSeconds);
9899
}
99100
} catch (COMException e) {
100-
LOGGER.Warn(e, "UI Automation error while selecting security key, skipping this dialog box instance");
101+
LOGGER.Error(e, "UI Automation error while selecting security key, skipping this dialog box instance");
101102
}
102103
}
103104

Readme.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ This is a background program that runs headlessly in your Windows user session.
3939
Internally, this program uses [Microsoft UI Automation](https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-uiautomationoverview) to read and interact with the dialog boxes.
4040

4141
### Overriding the automatic next behavior
42+
4243
By default, this program does not interfere with local TPM passkey prompts (like requesting your Windows Hello PIN or biometrics). It also does not automatically submit FIDO prompts that contain additional options besides a USB security key and pairing a new Bluetooth smartphone, such as the cases when you already have a paired phone, or you previously declined a Windows Hello factor like a PIN but want to try a PIN again from the authenticator choice dialog. However, you may override this behavior if you wish and force it to **_always_** choose the USB security key in all cases, even if there are other valid options like Windows Hello PIN/biometrics, by passing the command-line argument `--skip-all-non-security-key-options` when starting this program (see [Installation](#installation) for the recommended autostart registry paths if you want to change it there).
4344

4445
If a paired phone option appears in the dialog box and you want to remove it, [you can edit the registry to unpair an existing phone](https://github.com/Aldaviva/AuthenticatorChooser/wiki/Unpairing-Bluetooth-smartphone). This is useful if your old phone [bricked itself](https://en.wikipedia.org/wiki/Pixel_5a#Known_issues), or you just upgraded to a new phone.
@@ -83,6 +84,7 @@ Even if this program doesn't click the Next button (because an extra choice was
8384
- Use `regedit.exe` interactively to go to the `HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run` key, and then add a new String value with the Name `AuthenticatorChooser` and the Value `"C:\Program Files\AuthenticatorChooser\AuthenticatorChooser.exe"`
8485
8586
## Demo
87+
8688
To test with a sample FIDO authentication prompt, visit [WebAuthn.io](https://webauthn.io) and click the **Authenticate** button.
8789
8890
## Building
@@ -98,6 +100,10 @@ If you want to build this application yourself instead of downloading precompile
98100
```ps1
99101
cd .\AuthenticatorChooser\AuthenticatorChooser\
100102
```
103+
1. Choose one of the [version tags](https://github.com/Aldaviva/AuthenticatorChooser/tags) to build, or skip this step to use the latest commit.
104+
```ps1
105+
git checkout 0.2.0
106+
```
101107
1. Build the program.
102108
```ps1
103109
dotnet publish -p:PublishSingleFile=true
@@ -106,4 +112,7 @@ If you want to build this application yourself instead of downloading precompile
106112
The program will be compiled to the following path, assuming your CPU architecture is x64.
107113
```text
108114
.\bin\Release\net8.0-windows\win-x64\publish\AuthenticatorChooser.exe
109-
```
115+
```
116+
117+
You can also use an IDE like [Visual Studio](https://visualstudio.microsoft.com/vs/) Community 2022 instead of the command line.
118+
- Visual Studio Publishing Profiles have been broken for years unless certain other workloads (like ASP.NET Web Development) are installed, so if you can't publish from VS you'll have to use the `dotnet publish` command above.

0 commit comments

Comments
 (0)