react-native-apple-authentication
A well-typed React Native library that brings native Sign In with Apple to iOS and a web-based equivalent to Android.
Repository Health
Technical Analysis
react-native-apple-authentication wraps Apple’s AuthenticationServices framework (ASAuthorizationAppleIDProvider) on iOS and provides a companion WebView-driven OAuth flow on Android, so a single JavaScript API can drive Sign In with Apple across both platforms. It exports a themeable AppleButton component with the official style/type variants (White, WhiteOutline, Black; SignIn, Continue, SignUp), plus an appleAuth (iOS) and appleAuthAndroid (Android) object for performing the request, checking credential state, and listening for credential revocation.
The library is maintained by Invertase, the team behind React Native Firebase, and is commonly paired with Firebase Authentication or Auth0 as the identity backend. It handles nonce generation and SHA256 hashing automatically, ships full TypeScript typings for the entire public API, and documents platform-specific setup (entitlements, Android developer-console configuration, Expo config) in a dedicated docs folder.
What You Get
- A themeable
AppleButtoncomponent with official Apple style variants (White, WhiteOutline, Black) and type variants (SignIn, Continue, SignUp), resolved per-platform via.ios/.android/.macosfile extensions - An
appleAuthobject for iOS exposingperformRequest,getCredentialStateForUser, andonCredentialRevoked, plus its enums (Operation,Scope,State,UserStatus,Error) attached directly to the object - An
appleAuthAndroidobject that configures and drives a WebView-based Sign In with Apple OAuth flow (configure()thensignIn()), since no native Android SDK exists for it - Automatic nonce generation and SHA256 hashing before requests are sent to Apple, with server-side verification guidance in the README
- Full TypeScript declarations (
index.d.ts) covering every exported type, enum, and response shape - Dedicated guides for Firebase, Auth0, Expo, and MacOS (via react-native-macos) integration under
docs/
Common Use Cases
- Adding Sign In with Apple as a login option in a React Native iOS app to satisfy App Store guideline 4.8 (mandatory when other third-party login is offered)
- Pairing with React Native Firebase Authentication to exchange the returned identity token for a Firebase credential
- Using the Auth0 integration guide to route the Apple identity token through an Auth0-backed authentication flow
- Building a unified cross-platform login screen where the same
AppleButtonrenders correctly on both iOS and Android
Under The Hood
Architecture
The library follows a thin JS-bridge-over-native-module architecture: lib/index.js and lib/AppleAuthModule.js expose a small JS layer that validates/normalizes request options and throws descriptive errors for unsupported platforms or malformed arguments (throwIfNotSupported, argument checks in performRequest), while the actual authentication logic lives in native code — ios/RNAppleAuthentication/RNAppleAuthModule.m bridges to ASAuthorizationAppleIDProvider and RNAppleAuthASAuthorizationDelegates.m handles the native delegate callbacks, and android/.../AppleAuthenticationAndroidModule.java drives a custom WebView OAuth flow via SignInWithAppleService.kt and SignInWebViewClient.kt. AppleButton.ios.js/.android.js/.macos.js/.shared.js provide per-platform view wrappers resolved through React Native’s file-extension platform dispatch rather than runtime Platform.OS branching, keeping the exported component surface uniform. If Apple changed the shape of ASAuthorizationAppleIDRequest, only the iOS native module and its mirrored TypeScript types would need updates.
Tech Stack
The JS/TS layer targets React Native ^0.82.1 with TypeScript ^5.9.3 (strict mode) for type declarations, ESLint 9 flat config extending @react-native/eslint-config, and Prettier 3 for formatting; API docs are generated via typedoc/typedoc-plugin-markdown into a checked-in typedocs/ folder, and releases are cut with release-it plus conventional-changelog. iOS native code uses Objective-C against Apple’s AuthenticationServices framework directly; Android uses Kotlin/Java with a hand-rolled WebView-based OAuth flow, since Apple provides no native Sign In with Apple SDK for Android. The project builds with Yarn 4 (Berry) workspaces and runs separate GitHub Actions workflows for Android, iOS, linting, and npm publishing.
Code Quality
No dedicated unit or spec test files exist under lib/, ios/, or android/ — there is no Jest, Detox, or XCTest suite exercising runtime behavior. Instead, quality assurance leans on type-test.tsx, a compile-time TypeScript check (tsc --noEmit) run in CI to catch API-surface regressions, and a tests_e2e.yml workflow that builds (but does not deeply assert against) the example apps for Android and iOS. The .d.ts typings are strict (strict: true, noUnusedLocals, noImplicitReturns), while the JS implementation itself relies on manual runtime validation with explicit thrown errors rather than compiler-enforced types. ESLint and Prettier are enforced via a dedicated CI linting job. The absence of behavioral tests is the clearest quality gap for a security-sensitive auth library.
API Design
The public API is compact: a single appleAuth object (iOS) and appleAuthAndroid object (Android) expose two or three methods each, with all enums (Operation, Scope, State, ResponseType) attached directly to the object so consumers avoid extra imports. AppleButton unifies cross-platform rendering behind one component name, eliminating manual Platform.OS branching in consumer code. Documentation is strong for a package this size — generated typedocs/, a docs/ folder covering initial setup, Firebase, Auth0, Android-specific developer console steps, and a migration guide, plus inline JSDoc on every exported type explaining subtleties like nonce hashing and credential-state semantics with links to Apple’s own docs. Friction remains on Android, where configure() must be called before signIn() in a separate step that’s easy to miss, and nonce-hashing behavior differs subtly enough between platforms that the docs have to call it out explicitly.