Repository navigation
feat(ios): sign in with apple - #8
Merged
Merged
Conversation
Introduces the `AppleSignIn` runtime API under `src/apple/`, mirroring the per-provider layout of `src/google/`. Decisions taken at this milestone: - iOS-only. Apple has no native Android SDK, so `NativeAppleSignIn` uses `TurboModuleRegistry.get` (nullable) rather than `getEnforcing`: importing the spec must never throw on Android. The wrapper translates a missing native module into a typed `NOT_SUPPORTED` error. - The API deliberately diverges from Google's instead of being forced to match. Apple has no client-side sign-out and no persistent in-memory user, so there is no `signOut`/`revokeAccess`/`getCurrentUser`. Instead the surface is `configure`, `signIn`, `getCredentialState(userId)` and `isAvailable()`. - `AppleUser.email` and `fullName` are typed nullable because Apple returns them only on the first authorization; this is called out in the JSDoc so callers persist them server-side on first sign-in.
Implements the `AppleSignIn` TurboModule in Objective-C++ against the codegen-generated `NativeAppleSignInSpec`. Decisions taken at this milestone: - Objective-C++ (not Swift), to mirror the existing GoogleSignIn module and avoid the Swift/TurboModule interop the library does not set up. The Obj-C class name matches the JS module name so RN resolves it via `NSClassFromString` (the library uses no `RCT_EXPORT_MODULE`). - Uses the system `AuthenticationServices` framework, declared in the podspec; no third-party pod is added. The minimum deployment target is iOS 15.1, so no `@available` guards are required. - The `ASAuthorizationController`, its delegate (self) and the pending resolve/reject blocks are retained as ivars for the duration of the async flow, because the controller keeps only a weak delegate reference. - `ASAuthorizationError` codes are mapped to the library's platform-agnostic string codes (cancelled / failed / invalid-response / not-handled).
Adds `AppleSignInButton`, exported from the `@thoughtbot/react-native-social-auth/apple-button` subpath (parallel to the existing `google-button` entry point). Decisions taken at this milestone: - Uses Apple's native `ASAuthorizationAppleIDButton`, bridged as a Fabric component, rather than a pure-JS/SVG button. This guarantees the button always matches Apple's Human Interface Guidelines and localizes automatically, and it needs no `react-native-svg` dependency. - `codegenConfig.type` is switched from `modules` to `all`, and an `ios.componentProvider` map is added. On RN 0.83 the app-level `RCTThirdPartyComponentsProvider` only registers a third-party Fabric view that is listed in `componentProvider`; a library with no component annotations is never reached by the deprecated source-crawl fallback, so without the map the component is silently dropped from the registry. - The friendly string props (`type`, `buttonStyle`) map to Apple's integer enums in JS. The button renders `null` on Android, where Apple Sign-In is unsupported.
Adds an `enableAppleSignIn` prop to the config plugin. Decisions taken at this milestone: - Apple needs only the `com.apple.developer.applesignin` entitlement — no URL scheme, no AppDelegate URL forwarding, and no modular headers (all of which Google requires). The plugin therefore adds just that entitlement via `withEntitlementsPlist`. - The plugin is restructured so the Google (`iosClientId`) and Apple (`enableAppleSignIn`) configuration apply independently. The previous early-return when `iosClientId` was absent would have skipped Apple setup for Apple-only or Android-Google + iOS-Apple apps. - The entitlement merge is extracted as a pure `applyAppleSignInEntitlement` helper and unit-tested, matching the plugin's existing "export pure helpers for tests" pattern.
Adds the native Apple buttons (three type/style variants) and a sign-in handler to the example, and sets `enableAppleSignIn: true` on the plugin entry so `expo prebuild` writes the entitlement. Decision: the handler persists nothing and simply surfaces the returned credential in an alert, keeping the demo self-contained; `SIGN_IN_CANCELLED` is ignored, consistent with the Google example's handling.
Adds a "Sign in with Apple" section to the README and updates the intro, feature list, platform-support line and Expo plugin props table. Covers the decisions made during implementation so consumers understand the shape: iOS-only scope and the Android `NOT_SUPPORTED` behaviour, entitlement setup (Expo `enableAppleSignIn` prop and the bare-RN Xcode capability), the `AppleSignIn` API, `AppleSignInButton` props, the error-code table, and the first-authorization-only caveat for email/name.
Each provider's API is now importable on its own subpath, cleanly separating
Apple from Google at the import level:
import { GoogleSignIn } from '@thoughtbot/react-native-social-auth/google';
import { AppleSignIn } from '@thoughtbot/react-native-social-auth/apple';
Decisions taken at this milestone:
- The new `./google` and `./apple` exports point at the existing per-provider
barrels (`src/google/index.ts`, `src/apple/index.ts`), which already export
only each provider's API. No new source files.
- The buttons stay on their own `./google-button` and `./apple-button`
subpaths so `react-native-svg` remains isolated to the Google button rather
than being pulled into a provider's core import.
- The package root `.` is kept as a convenience aggregate (non-breaking) and is
simplified to `export * from './google'` / `'./apple'` so it can never drift
from the barrels.
CI runs `yarn typecheck` before `yarn prepare`, so there is no built `lib/`. The root tsconfig only aliased the bare package name and `/google-button` to source, so the `/google`, `/apple` and `/apple-button` subpaths fell back to the `exports` `types` condition (`./lib/typescript/...`), which does not exist in CI — producing TS2307 "cannot find module" and cascading TS18046 "error is of type unknown" (the failed type-guard imports left `error` un-narrowed). Add the missing subpath aliases to the root tsconfig `paths`, mirroring the existing `/google-button` entry, so `tsc` resolves every entry point to source without needing a build.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sign in with Apple feature on iOS
ScreenRecording_10-09-2026.19-25-32_1.MP4