Skip to content

feat: integrate Apple hardware security-key 2FA - #267

Open
Olafejs wants to merge 3 commits into
malmeloo:mainfrom
Olafejs:feat/experimental-apple-security-key
Open

Olafejs wants to merge 3 commits into
malmeloo:mainfrom
Olafejs:feat/experimental-apple-security-key

Conversation

@Olafejs

@Olafejs Olafejs commented Sep 9, 2026 •

Copy link
Copy Markdown

Summary

Related to #159 and parawanderer/OpenTagViewer#18.

Integrates Apple HSA2 hardware-security-key authentication into FindMy.py's existing second-factor model.

  • Adds dependency-free SecurityKeyChallenge and SecurityKeyAssertion value types.
  • Exposes native async/sync security-key factors through get_2fa_methods().
  • Uses additive authenticate(signer) instead of forcing an assertion through submit(code: str).
  • Keeps the existing SMS/trusted-device APIs and custom BaseAppleAccount implementations compatible.
  • Keeps challenge parsing, assertion validation/encoding, continuation headers, bounded verified-TLS transport, and post-key GrandSlam/MobileMe transitions inside the library.
  • The application supplies the signer using its own WebAuthn frontend. No FIDO2 runtime dependency or bundled USB adapter is required.

Review follow-up

Removed the standalone security-key example additions as requested. Removed their dependency/configuration changes and obsolete documentation links. The native implementation is unchanged from the previous revision; this PR now contains only library integration and the corresponding account/API documentation.

Validation

Offline validation of native authentication APIs, compatibility and rejection guards passed on Python 3.10, 3.11, 3.12, 3.13 and 3.14. Ruff, basedpyright and all configured pre-commit checks passed. The source distribution and wheel build successfully. A separately installed wheel was exercised without python-fido2, including the native async account flow and synchronous security-key factor using synthetic data. The HTML documentation build succeeds with warnings outside the edited account page, including missing local Graphviz support.

Evidence and limitations

The original adapter completed login on one real Apple Account protected by a Yubico USB Security Key on Linux, and the resulting FindMy session was subsequently reused. The extracted native integration has been validated offline; this cleanup does not add a new real-account or hardware trial.

This is experimental. It does not claim universal hardware/account compatibility, official Apple support, legacy FSA1/U2F support, or primary-FSA2/passwordless login. No account-security changes, key removal or weaker fallback were used. No private account data, sessions, tokens, accessory exports, locations or homelab configuration are included.

Contributed by Olafejs with AI-assisted implementation and validation. Existing FindMy.py code and dependencies retain their authorship and licenses; this contribution follows the repository's MIT license.

@malmeloo

Copy link
Copy Markdown
Owner

This is very cool, thank you very much for working on this! I see a lot of example code and tests, but no additions or changes to the library itself. It's awesome that you got this working, but I feel like it would be more useful for end users if FIDO auth was integrated into the library itself. There are existing base classes for this (e.g. BaseSecondFactorMethod) that are intended to implement 2FA methods.

Do you think you could retrofit your solution into the existing 2FA model? Or would we need API changes / additions to properly implement this?

@Olafejs

Olafejs commented Sep 15, 2026

Copy link
Copy Markdown
Author

Yes, I agree that native integration would be much more useful for end users.

I think the protocol can be retrofitted into the existing 2FA model, but not cleanly through the current request() -> None / submit(code: str) interface alone. That interface assumes a code-based factor, while WebAuthn is a challenge -> local authenticator interaction -> signed assertion flow.

My preferred approach would be a small, backward-compatible API addition:

  • keep the existing SMS and trusted-device methods unchanged;
  • add security-key challenge/assertion types and async/sync security-key factor implementations returned by get_2fa_methods();
  • keep the Apple protocol parsing, assertion encoding, and account state transitions in the library;
  • keep python-fido2 optional by letting the factor accept a signer/authenticator callback, with an optional helper adapter for USB keys.

I would avoid forcing the assertion through submit(code: str) or making that method ignore a dummy string. A security-key-specific authenticate(signer) method seems like the smallest clean extension and leaves room for other authenticator frontends later.

So the short answer is: yes, I can rework this into the library's 2FA model, but I recommend a small additive API extension rather than fitting it into the code-based interface unchanged. If that direction works for you, I can retrofit the PR around it.

Refs malmeloo#159. Opt-in Linux HSA2 FIDO2/WebAuthn adapter, checked authentication transport, private CLI and synthetic tests. No default SDK API changes.

Coding-Model: gpt-6-astra
Move the proven HSA2 challenge, assertion, and authentication flow into FindMy's native BaseSecondFactorMethod model with async and sync APIs. Keep python-fido2 optional through a signer callback, preserve code-based factors, bound the 2FA transport, and update docs/tests.

Coding-Model: gpt-5.6-sol-900k
@Olafejs
Olafejs force-pushed the feat/experimental-apple-security-key branch from 3ad09f3 to 58b5c84 Compare September 15, 2026 20:29
@Olafejs Olafejs changed the title feat: add experimental Apple hardware-security-key login example feat: integrate Apple hardware security-key 2FA Sep 15, 2026
@Olafejs

Olafejs commented Sep 15, 2026

Copy link
Copy Markdown
Author

Thanks — I reworked the PR around the existing second-factor model as suggested.

The native library now exposes AsyncSecurityKeySecondFactor and SyncSecurityKeySecondFactor through get_2fa_methods(), with a small additive authenticate(signer) API. SMS and trusted-device methods remain unchanged, and security-key assertions are not forced through submit(code: str). python-fido2 stays optional and is used only by the Linux USB example adapter.

The Apple HSA2 parser, assertion codec, continuation handling, bounded verified-TLS 2FA transport and post-key GrandSlam/MobileMe transitions are now in findmy/; the example only supplies USB signing and the private CLI boundary. Existing custom BaseAppleAccount implementations are not made abstractly incompatible.

Verification on the rebased branch: 173 tests passed on Python 3.10–3.14, Ruff, basedpyright and pre-commit passed, and the built wheel contains the native security-key modules. I also kept the real-account evidence and universal-compatibility limitations explicit in the PR description; no account data or session material is included.

@malmeloo

Copy link
Copy Markdown
Owner

Thanks, I agree that this is probably the correct approach. I can't review your changes in detail right now so give me some time to look into it. One more thing: I'd suggest that we drop the current example additions entirely. It doesn't add a whole lot to the library (they appear to bypass the library entirely), and while it's certainly interesting, I think it serves more as documentation on how the spec works. It definitely has a purpose somewhere (dedicated FindMy docs, anyone???), but probably not in this library.

@Olafejs

Olafejs commented Oct 11, 2026

Copy link
Copy Markdown
Author

Thanks, I've removed the example additions as requested and updated the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants