Skip to content

Conversation

@DIYgod
Copy link
Member

@DIYgod DIYgod commented Jan 1, 2026

Summary

Implements native Sign in with Apple for Mac App Store builds using macOS AuthenticationServices framework. This replaces the web-based login flow with a system-native dialog as required by Apple for MAS submission.

Changes

  • Swift Helper Tool (apps/desktop/resources/apple-auth-helper/): Command-line utility that uses ASAuthorizationAppleIDProvider to perform native authentication and returns JSON with identity token and user credentials
  • IPC Service (auth.ts): Added two methods - signInWithApple() to execute the helper and isNativeAppleAuthAvailable() to check MAS availability
  • Frontend Handler (renderer/src/lib/auth.ts): Enhanced login handler that detects MAS builds and routes Apple auth through native flow, using better-auth's idToken mode
  • Entitlements (entitlements.mas.plist): Added com.apple.developer.applesignin capability
  • Packaging (forge.config.cts): Configured to include Swift helper in MAS builds only

Technical Details

The implementation flows as:

  1. User clicks Apple login button
  2. Frontend detects MAS build and calls IPC service
  3. Main process executes Swift helper (timeout: 2 minutes)
  4. Helper displays system authentication dialog
  5. On success, helper returns identity token in JSON
  6. Frontend authenticates with backend using idToken, completing OAuth flow

Graceful fallback to web-based Apple login if native flow fails or unavailable.

Add native Sign in with Apple support for MAS builds using macOS AuthenticationServices framework.
This replaces the web-based Apple login flow with a system-native dialog that meets MAS requirements.

Changes:
- Create Swift Helper tool for native ASAuthorizationController
- Add IPC service to execute helper and return identity token
- Enhance renderer auth handler to use native login on MAS builds
- Add Sign in with Apple entitlements for MAS builds
- Configure forge to include helper in MAS package

The implementation uses better-auth's idToken flow for server-side verification,
ensuring seamless integration with existing authentication system.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@safedep
Copy link

safedep bot commented Jan 1, 2026

SafeDep Report Summary

Green Malicious Packages Badge Green Vulnerable Packages Badge Green Risky License Badge

No dependency changes detected. Nothing to scan.

This report is generated by SafeDep Github App

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

DIYgod and others added 2 commits January 1, 2026 20:18
Extend native Apple authentication to work on both DMG and MAS builds,
not just MAS. This provides a better user experience on all macOS versions.

Changes:
- Add Sign in with Apple entitlement to entitlements.mac.plist
- Include Apple Auth Helper in all macOS builds (darwin and mas)
- Update IPC service to check isMacOS instead of isMAS
- Update renderer to detect darwin platform for native auth

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Replace DispatchGroup.wait() with RunLoop-based waiting to avoid blocking
the main thread while ASAuthorizationController delivers delegate callbacks.

The previous implementation caused a deadlock:
1. performSignIn() called dispatchGroup.wait() on main thread
2. ASAuthorizationController callbacks need main thread to execute
3. Main thread blocked → callbacks never fire → timeout

Now using RunLoop.current.run() which allows the main thread to continue
processing events (including delegate callbacks) while waiting for completion.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@DIYgod
Copy link
Member Author

DIYgod commented Jan 1, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

When the helper exits with non-zero status (e.g., user canceled),
execFileAsync rejects but error.stdout still contains the JSON result.
Parse it to properly detect cancellation and return the correct error.

Previously, error.message would be "Command failed with exit code 1"
which doesn't indicate cancellation, causing unnecessary fallback to
web-based login after the user already canceled.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@DIYgod
Copy link
Member Author

DIYgod commented Jan 1, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Fix the relative path from services directory to resources:
- From: apps/desktop/layer/main/src/ipc/services/
- To:   apps/desktop/resources/apple-auth-helper/

The path needed 5 levels up (../../../../../) not 4 (../../../../).
This was preventing native Sign in with Apple from working in dev mode.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@DIYgod
Copy link
Member Author

DIYgod commented Jan 1, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

The AppleAuthHelper binary is embedded in Resources via extraResource
and gets signed with entitlements.mas.child.plist in MAS builds.
Without the applesignin entitlement, ASAuthorizationAppleIDProvider
calls from the helper would be denied by the system.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
@DIYgod
Copy link
Member Author

DIYgod commented Jan 1, 2026

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 98 to 99
// For macOS builds (darwin and mas), include the Apple Auth Helper
const isMacOS = platform === "darwin" || platform === "mas"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include helper when --platform is omitted

Here isMacOS depends only on the --platform CLI arg, but electron-forge make is invoked without --platform in scripts like build:electron/build:electron-forge (apps/desktop/package.json), so on macOS the arg is undefined and isMacOS becomes false. That means the AppleAuthHelper resource is not packaged in those builds, so native Sign in with Apple will fail at runtime and fall back to web despite being on macOS. Consider defaulting to process.platform when the CLI arg is missing so mac builds always include the helper.

Useful? React with 👍 / 👎.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 98 to 100
// For macOS builds (darwin and mas), include the Apple Auth Helper
const isMacOS = platform === "darwin" || platform === "mas"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Default mac builds will skip bundling AppleAuthHelper

Here isMacOS is derived only from the --platform CLI flag. When electron-forge make is invoked without --platform (the default invocation and the build:electron script), platform is undefined and isMacOS becomes false, so the apple-auth-helper directory is not added to extraResource. That produces mac builds without the helper binary, and signInWithApple will fail at runtime because the helper can’t be executed. Consider falling back to process.platform/process.mas when the flag is absent so mac builds always include the helper.

Useful? React with 👍 / 👎.

Comment on lines 135 to 138
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
// Return the key window or create a new window if needed
if let window = NSApplication.shared.keyWindow {
return window

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Import AppKit to compile NSApplication/NSWindow

This helper uses AppKit types (NSApplication, NSWindow), but the file only imports AuthenticationServices and Foundation. Rebuilding the helper (build.sh uses swiftc) will fail with “cannot find 'NSApplication' in scope,” so the binary can’t be recompiled when needed. Add import AppKit (or import Cocoa) to ensure the helper compiles.

Useful? React with 👍 / 👎.

DIYgod and others added 9 commits January 1, 2026 21:49
Native Sign in with Apple via AuthenticationServices framework is only
supported on Mac App Store builds. DMG builds will use web-based login.

- Remove applesignin entitlement from entitlements.mac.plist
- Only include AppleAuthHelper in MAS builds
- Update auth service to check isMAS instead of isMacOS

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Native Sign in with Apple is now MAS-only, so the darwin build
doesn't need the provisioning profile.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Include detailed error information in all ASAuthorizationError cases
to help diagnose authentication failures.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use .regular activation policy to allow system UI display
- Activate app to bring it to front for system dialogs
- Create properly sized and styled presentation window
- Keep strong reference to window to prevent deallocation
- Add stderr debug logs in Swift helper
- Add console.info logs in renderer for debugging auth flow

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The helper now has a proper Bundle ID (is.follow.AppleAuthHelper) which
is required for ASAuthorizationController to work. Standalone executables
without Bundle ID cannot use Sign in with Apple.

- Create Info.plist with bundle configuration
- Update build.sh to create .app bundle structure
- Update helperPath to point to the bundle executable

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move Info.plist generation into build.sh to create it directly inside the .app bundle.

This prevents Apple from treating the apple-auth-helper directory as a nested bundle.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Switch from while+RunLoop to standard NSApp.run() event loop

- Use .accessory activation policy (no Dock icon)

- Create minimal 1x1 transparent window as presentation anchor

- Keep strong reference to ASAuthorizationController

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Apple requires the Bundle ID to be registered for Sign in with Apple.

Using the main app's Bundle ID ensures compatibility with existing config.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@DIYgod DIYgod marked this pull request as draft January 2, 2026 07:59
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