[PR #4944] [MERGED] Feat/add support for forcing device auth flow on ios #24566

Closed
opened 2026-08-05 06:08:51 -04:00 by saavagebueno · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbirdio/netbird/pull/4944
Author: @shuuri-labs
Created: 12/12/2025
Status: Merged
Merged: 12/30/2025
Merged by: @shuuri-labs

Base: mainHead: feat/add-support-for-forcing-device-auth-flow-on-ios


📝 Commits (10+)

  • 1d9f1f0 updates to client file writing
  • ea81144 numerous
  • c64f76a minor
  • 4aa7151 Merge branch 'main' into feat/add-support-for-forcing-device-auth-flow-on-ios
  • f76f762 - Align OnLoginSuccess behavior with Android (only call on nil error)
  • 285086e Add nolint directive for staticcheck SA1029 in login.go
  • b96d41e Fix CodeRabbit review issues for iOS/tvOS SDK
  • 25934e0 Address additional CodeRabbit review issues for iOS/tvOS SDK
  • 202b6f6 Make urlOpener.Open() synchronous in device auth flow
  • 57564ab Merge branch 'main' into feat/add-support-for-forcing-device-auth-flow-on-ios

📊 Changes

5 files changed (+392 additions, -29 deletions)

View changed files

📝 client/iface/device/device_ios.go (+24 -2)
📝 client/internal/profilemanager/config.go (+83 -0)
📝 client/ios/NetBirdSDK/client.go (+88 -14)
📝 client/ios/NetBirdSDK/login.go (+194 -12)
📝 client/ios/NetBirdSDK/preferences.go (+3 -1)

📄 Description

Describe your changes

This PR adds support for forcing device authentication flow on iOS/tvOS, enabling Apple TV (tvOS) support similar to what was done for Android TV.

Background

tvOS (Apple TV) cannot use the standard PKCE authentication flow because:

  1. Safari is not available on Apple TV
  2. The tvOS sandbox blocks atomic file operations (temp file + rename) in App Group containers
  3. Shared App Group UserDefaults doesn't sync between the main app and Network Extension on tvOS

This implementation uses the device code flow where users scan a QR code or enter a code on another device to authenticate.


SDK Changes (client/ios/NetBirdSDK/)

login.go

  • URLOpener interface - Extended with userCode parameter and OnLoginSuccess() callback
  • SSOListener / ErrListener - New async listener interfaces for mobile framework
  • SaveConfigIfSSOSupported - Changed from sync (bool, error) to async with SSOListener callback
  • LoginWithSetupKeyAndSaveConfig - Changed from sync error to async with ErrListener callback
  • Login() renamed to LoginSync() - Original sync method renamed, now used for background VPN without UI
  • New Login() - Interactive login with forceDeviceAuth flag
  • New LoginWithDeviceName() - Interactive login with custom device name support (required for tvOS)
  • GetConfigJSON() / SetConfigFromJSON() - New methods for alternative config storage (UserDefaults on tvOS)
  • DirectWriteOutConfig usage - All file writes use non-atomic operations for tvOS compatibility
  • Nil guards - Added nil checks for listener interfaces to prevent panics
  • Config save ordering - Config saved before OnLoginSuccess callback to ensure persistence
  • Timeout contexts - Added bounded timeouts for RequestAuthInfo calls

client.go

  • IsLoginRequired - Improved error handling, returns true on config load failure
  • LoginForMobile - Added timeout context for auth info request

device_ios.go

  • ErrInvalidTunnelFD - New exported error for invalid tunnel file descriptor
  • tunFd == 0 handling - Now a hard error instead of fallback (no viable fallback on iOS/tvOS)

config.go (profilemanager)

  • DirectUpdateOrCreateConfig - Added permission enforcement for existing config files
  • ConfigFromJSON - Now applies defaults after unmarshaling

Breaking API Changes

These are intentional breaking changes for the iOS SDK to support tvOS:

  1. URLOpener interface: Open(string)Open(url, userCode) + OnLoginSuccess()
  2. SaveConfigIfSSOSupported: Sync → Async with listener
  3. LoginWithSetupKeyAndSaveConfig: Sync → Async with listener
  4. Login(): Renamed to LoginSync(), new Login() has different signature

The iOS client app has been updated to use these new APIs. Existing iOS functionality is preserved.

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Summary by CodeRabbit

  • New Features

    • tvOS in-memory preloaded config with JSON import/export and a synchronous LoginSync.
  • New Behavior

    • Reworked login orchestration: device-name-aware interactive flows, foreground OAuth/device flow with bounded timeouts, and UI notification on successful login.
    • tvOS now prefers in-memory/config paths that avoid atomic file operations.
  • Bug Fixes

    • Improved detection and clearer error reporting when tunnel/socket initialization fails on iOS/tvOS.

✏️ Tip: You can customize this high-level summary in your review settings.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbirdio/netbird/pull/4944 **Author:** [@shuuri-labs](https://github.com/shuuri-labs) **Created:** 12/12/2025 **Status:** ✅ Merged **Merged:** 12/30/2025 **Merged by:** [@shuuri-labs](https://github.com/shuuri-labs) **Base:** `main` ← **Head:** `feat/add-support-for-forcing-device-auth-flow-on-ios` --- ### 📝 Commits (10+) - [`1d9f1f0`](https://github.com/netbirdio/netbird/commit/1d9f1f08548c511664f0cde3a76d0c1742552c37) updates to client file writing - [`ea81144`](https://github.com/netbirdio/netbird/commit/ea811442c756295a79db03fd1d7f40d4ccf78bc5) numerous - [`c64f76a`](https://github.com/netbirdio/netbird/commit/c64f76a10dc5fb85dab22854bc8028c052a5b765) minor - [`4aa7151`](https://github.com/netbirdio/netbird/commit/4aa71517b0d5ef02abfc55e2b236fe52adb91a96) Merge branch 'main' into feat/add-support-for-forcing-device-auth-flow-on-ios - [`f76f762`](https://github.com/netbirdio/netbird/commit/f76f7622b53a693f4633d73dd0f3ff1b19ef41a0) - Align OnLoginSuccess behavior with Android (only call on nil error) - [`285086e`](https://github.com/netbirdio/netbird/commit/285086e9393fe5e3a9ac78bb9d6a0918ca049ebd) Add nolint directive for staticcheck SA1029 in login.go - [`b96d41e`](https://github.com/netbirdio/netbird/commit/b96d41eb5293ffebc484642b6692f6ef30858438) Fix CodeRabbit review issues for iOS/tvOS SDK - [`25934e0`](https://github.com/netbirdio/netbird/commit/25934e0efc105d672a100b7cc4c38947cbb12896) Address additional CodeRabbit review issues for iOS/tvOS SDK - [`202b6f6`](https://github.com/netbirdio/netbird/commit/202b6f69d5e0396ddab9fce10032b83971a6448f) Make urlOpener.Open() synchronous in device auth flow - [`57564ab`](https://github.com/netbirdio/netbird/commit/57564ab9652e6d5afc0d78ae170c99cb99418501) Merge branch 'main' into feat/add-support-for-forcing-device-auth-flow-on-ios ### 📊 Changes **5 files changed** (+392 additions, -29 deletions) <details> <summary>View changed files</summary> 📝 `client/iface/device/device_ios.go` (+24 -2) 📝 `client/internal/profilemanager/config.go` (+83 -0) 📝 `client/ios/NetBirdSDK/client.go` (+88 -14) 📝 `client/ios/NetBirdSDK/login.go` (+194 -12) 📝 `client/ios/NetBirdSDK/preferences.go` (+3 -1) </details> ### 📄 Description ## Describe your changes This PR adds support for forcing device authentication flow on iOS/tvOS, enabling Apple TV (tvOS) support similar to what was done for Android TV. ### Background tvOS (Apple TV) cannot use the standard PKCE authentication flow because: 1. Safari is not available on Apple TV 2. The tvOS sandbox blocks atomic file operations (temp file + rename) in App Group containers 3. Shared App Group UserDefaults doesn't sync between the main app and Network Extension on tvOS This implementation uses the **device code flow** where users scan a QR code or enter a code on another device to authenticate. --- ### SDK Changes (`client/ios/NetBirdSDK/`) #### `login.go` - **URLOpener interface** - Extended with userCode parameter and OnLoginSuccess() callback - **SSOListener / ErrListener** - New async listener interfaces for mobile framework - **SaveConfigIfSSOSupported** - Changed from sync (bool, error) to async with SSOListener callback - **LoginWithSetupKeyAndSaveConfig** - Changed from sync error to async with ErrListener callback - **Login() renamed to LoginSync()** - Original sync method renamed, now used for background VPN without UI - **New Login()** - Interactive login with forceDeviceAuth flag - **New LoginWithDeviceName()** - Interactive login with custom device name support (required for tvOS) - **GetConfigJSON() / SetConfigFromJSON()** - New methods for alternative config storage (UserDefaults on tvOS) - **DirectWriteOutConfig usage** - All file writes use non-atomic operations for tvOS compatibility - **Nil guards** - Added nil checks for listener interfaces to prevent panics - **Config save ordering** - Config saved before OnLoginSuccess callback to ensure persistence - **Timeout contexts** - Added bounded timeouts for RequestAuthInfo calls #### `client.go` - **IsLoginRequired** - Improved error handling, returns true on config load failure - **LoginForMobile** - Added timeout context for auth info request #### `device_ios.go` - **ErrInvalidTunnelFD** - New exported error for invalid tunnel file descriptor - **tunFd == 0 handling** - Now a hard error instead of fallback (no viable fallback on iOS/tvOS) #### `config.go` (profilemanager) - **DirectUpdateOrCreateConfig** - Added permission enforcement for existing config files - **ConfigFromJSON** - Now applies defaults after unmarshaling --- ### Breaking API Changes These are **intentional breaking changes** for the iOS SDK to support tvOS: 1. **URLOpener interface**: `Open(string)` → `Open(url, userCode)` + `OnLoginSuccess()` 2. **SaveConfigIfSSOSupported**: Sync → Async with listener 3. **LoginWithSetupKeyAndSaveConfig**: Sync → Async with listener 4. **Login()**: Renamed to `LoginSync()`, new `Login()` has different signature The iOS client app has been updated to use these new APIs. Existing iOS functionality is preserved. ## Issue ticket number and link ## Stack <!-- branch-stack --> ### Checklist - [ ] Is it a bug fix - [ ] Is a typo/documentation fix - [x] Is a feature enhancement - [ ] It is a refactor - [ ] Created tests that fail without the change (if possible) > By submitting this pull request, you confirm that you have read and agree to the terms of the [Contributor License Agreement](https://github.com/netbirdio/netbird/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT.md). ## Documentation Select exactly one: - [ ] I added/updated documentation for this change - [x] Documentation is **not needed** for this change (explain why) ### Docs PR URL (required if "docs added" is checked) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * tvOS in-memory preloaded config with JSON import/export and a synchronous LoginSync. * **New Behavior** * Reworked login orchestration: device-name-aware interactive flows, foreground OAuth/device flow with bounded timeouts, and UI notification on successful login. * tvOS now prefers in-memory/config paths that avoid atomic file operations. * **Bug Fixes** * Improved detection and clearer error reporting when tunnel/socket initialization fails on iOS/tvOS. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
saavagebueno added the pull-request label 2026-08-05 06:08:51 -04:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#24566