New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details
Socket
Book a DemoSign in
Socket

@forward-software/react-auth-apple

Package Overview
Dependencies
Maintainers
2
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@forward-software/react-auth-apple

Apple Sign-In adapter for @forward-software/react-auth - Web and React Native/Expo

latest
Source
npmnpm
Version
1.0.0
Version published
Weekly downloads
12
-80%
Maintainers
2
Weekly downloads
 
Created
Source

@forward-software/react-auth-apple

Apple Sign-In adapter for @forward-software/react-auth - Web and React Native

license Build & Test Github Issues

npm NPM downloads

Self-contained Apple Sign-In integration with no external auth wrapper dependencies. Provides a ready-made AuthClient implementation and a drop-in AppleSignInButton for both platforms.

Installation

npm install @forward-software/react-auth-apple @forward-software/react-auth
# or
pnpm add @forward-software/react-auth-apple @forward-software/react-auth

React Native (Expo)

This package includes an Expo native module. You need a development build (not Expo Go):

npx expo prebuild
npx expo run:ios

No additional CocoaPods are required -- Apple Sign-In uses the system AuthenticationServices framework.

Quick Start

Web

import { createAuth } from '@forward-software/react-auth';
import { AppleAuthClient, AppleSignInButton } from '@forward-software/react-auth-apple';

const appleClient = new AppleAuthClient({
  clientId: 'com.example.service', // Your Apple Services ID
  redirectURI: 'https://example.com/auth/apple/callback',
});

const { AuthProvider, useAuthClient } = createAuth(appleClient);

function App() {
  return (
    <AuthProvider>
      <LoginScreen />
    </AuthProvider>
  );
}

function LoginScreen() {
  const auth = useAuthClient();

  return (
    <AppleSignInButton
      config={{
        clientId: 'com.example.service',
        redirectURI: 'https://example.com/auth/apple/callback',
      }}
      onCredential={(credentials) => auth.login(credentials)}
      onError={(error) => console.error(error)}
    />
  );
}

React Native

import { createAuth } from '@forward-software/react-auth';
import { AppleAuthClient, AppleSignInButton } from '@forward-software/react-auth-apple';
import { MMKV } from 'react-native-mmkv';

const mmkv = new MMKV();
const storage = {
  getItem: (key: string) => mmkv.getString(key) ?? null,
  setItem: (key: string, value: string) => mmkv.set(key, value),
  removeItem: (key: string) => mmkv.delete(key),
};

const appleClient = new AppleAuthClient({
  clientId: 'com.example.app',
  storage,
});

const { AuthProvider, useAuthClient } = createAuth(appleClient);

function LoginScreen() {
  const auth = useAuthClient();

  return (
    <AppleSignInButton
      config={{ clientId: 'com.example.app', storage }}
      onCredential={(credentials) => auth.login(credentials)}
      onError={(error) => console.error(error)}
    />
  );
}

Web Setup

  • Register a Services ID in the Apple Developer Console
  • Configure the Sign in with Apple capability with your domain and redirect URL
  • Pass the Services ID as clientId and your registered redirect URL as redirectURI

React Native Setup

iOS

No additional setup is needed beyond enabling the Sign in with Apple capability in your Xcode project:

  • Open your project in Xcode
  • Go to Signing & Capabilities
  • Click + Capability and add Sign in with Apple

Android

Apple Sign-In on Android uses a web-based OAuth flow via Chrome Custom Tabs. Because Apple uses response_mode=form_post, a backend proxy is required to receive Apple's POST response and redirect it back to your app via a deep link.

How it works

  • The app opens a Chrome Custom Tab pointing to Apple's authorization page
  • The user signs in on Apple's page
  • Apple POSTs the id_token and code to your registered redirect URI (your backend)
  • Your backend extracts the tokens from the POST body and redirects to your app using a deep link
  • The app receives the deep link, calls handleCallback(), and the sign-in promise resolves

1. Apple Developer Console

You need a Services ID (separate from your App ID):

  • Go to Certificates, Identifiers & Profiles
  • Create or select a Services ID (e.g., com.example.app.service)
  • Enable Sign in with Apple and click Configure
  • Set the Primary App ID to your app (it must have Sign in with Apple capability enabled)
  • Add your backend's Domain (e.g., api.example.com)
  • Add the Return URL pointing to your backend callback endpoint (e.g., https://api.example.com/auth/apple/callback)

2. Backend proxy

A minimal Express server that receives Apple's POST and redirects to your app:

const express = require('express');
const app = express();

const APP_SCHEME = 'myapp'; // Your app's URL scheme

app.use(express.urlencoded({ extended: true }));

app.post('/auth/apple/callback', (req, res) => {
  const { id_token, code, state, user } = req.body;

  const params = new URLSearchParams();
  if (id_token) params.set('id_token', id_token);
  if (code) params.set('code', code);
  if (state) params.set('state', state);
  if (user) params.set('user', user);

  // Redirect to the app via deep link
  res.redirect(302, `${APP_SCHEME}://auth/apple?${params.toString()}`);
});

app.listen(3000);

3. App URL scheme

Make sure your app has a URL scheme configured in app.json:

{
  "expo": {
    "scheme": "myapp"
  }
}

Create a route to handle the callback deep link. With Expo Router, add a file at app/auth/apple.tsx:

import { useEffect } from 'react';
import { Platform } from 'react-native';
import { useLocalSearchParams, router } from 'expo-router';
import { AppleSignInModule } from '@forward-software/react-auth-apple';

export default function AppleCallback() {
  const params = useLocalSearchParams<{ id_token?: string; code?: string; user?: string }>();

  useEffect(() => {
    if (Platform.OS === 'android' && params.id_token) {
      AppleSignInModule.handleCallback({
        id_token: params.id_token,
        code: params.code,
        user: params.user,
      });
    }
    router.replace('/login');
  }, [params]);

  return null;
}

When the deep link myapp://auth/apple?id_token=...&code=... arrives, Expo Router matches it to this route. The route calls handleCallback() to resolve the pending sign-in promise, then navigates to the login screen where the auth state updates.

5. App configuration

Pass the androidRedirectUri in both the client and button config. On Android, use the Services ID as clientId (not your app bundle ID):

import { Platform } from 'react-native';

const ANDROID_REDIRECT_URI = 'https://api.example.com/auth/apple/callback';

const appleClient = new AppleAuthClient({
  clientId: Platform.OS === 'android' ? 'com.example.app.service' : 'com.example.app',
  storage,
  ...(Platform.OS === 'android' && { androidRedirectUri: ANDROID_REDIRECT_URI }),
});
<AppleSignInButton
  config={{
    clientId: Platform.OS === 'android' ? 'com.example.app.service' : 'com.example.app',
    storage,
    ...(Platform.OS === 'android' && { androidRedirectUri: ANDROID_REDIRECT_URI }),
  }}
  onCredential={(credentials) => auth.login(credentials)}
  onError={(error) => console.error(error)}
/>

Note: On iOS, the clientId should be your App Bundle ID. On Android, it must be the Apple Services ID since the flow uses web-based OAuth.

Button Props

Web (AppleSignInButton)

PropTypeDefaultDescription
configAppleWebAuthConfigrequiredApple Sign-In configuration
onCredential(credentials) => voidrequiredCalled with credentials on success
onError(error) => void-Called on error
color'black' | 'white' | 'white-outline''black'Button color scheme
type'sign-in' | 'continue' | 'sign-up''sign-in'Button label type
labelstringBased on typeCustom label for localization
widthnumberautoButton width in pixels
heightnumber44Button height in pixels

React Native (AppleSignInButton)

PropTypeDefaultDescription
configAppleNativeAuthConfigrequiredApple Sign-In configuration
onCredential(credentials) => voidrequiredCalled with credentials on success
onError(error) => void-Called on error
styleStyleProp<ViewStyle>-Additional button styles
disabledbooleanfalseDisable the button
color'black' | 'white''black'Button color scheme
labelstring'Sign in with Apple'Custom label for localization

Manual Integration

You can use the SDK wrapper directly for custom flows:

// Web
import { loadAppleIdScript, initializeAppleAuth, signInWithApple } from '@forward-software/react-auth-apple/web/appleid';

await loadAppleIdScript();
initializeAppleAuth({
  clientId: 'com.example.service',
  scope: 'name email',
  redirectURI: 'https://example.com/callback',
  usePopup: true,
});
const response = await signInWithApple();
// React Native
import { Platform } from 'react-native';
import { AppleSignInModule } from '@forward-software/react-auth-apple';

AppleSignInModule.configure({ scopes: ['name', 'email'] });
const credentials = await AppleSignInModule.signIn();

// getCredentialState is iOS-only; it rejects with UNSUPPORTED on Android
if (Platform.OS === 'ios') {
  const state = await AppleSignInModule.getCredentialState(credentials.user);
}

Token Behavior

  • Identity Token: Apple issues a JWT identityToken (similar to Google's idToken). The exp claim is extracted automatically for expiration tracking.
  • First Authorization Only: Apple provides user info (email, name) only on the first authorization. Subsequent sign-ins return only the identityToken and user ID. Store user info on your backend after the first login.
  • Credential State: On iOS, you can check if the user's Apple ID is still authorized via getCredentialState(). This is used during token refresh instead of silent re-authentication.
  • No Client-Side Refresh: Apple does not support client-side token refresh. When the identity token expires, the user must re-authenticate.

API Reference

Types

  • AppleAuthTokens - Token object stored after sign-in
  • AppleAuthCredentials - Credentials passed to login()
  • AppleFullName - Structured name (givenName, familyName, etc.)
  • AppleWebAuthConfig - Web configuration
  • AppleNativeAuthConfig - Native configuration
  • AppleScope - 'name' | 'email'
  • TokenStorage - Storage interface for persistence

Classes

  • AppleAuthClient - Implements AuthClient<AppleAuthTokens, AppleAuthCredentials>

Functions (Web SDK)

  • loadAppleIdScript() - Load the Apple JS SDK
  • initializeAppleAuth(config) - Initialize the SDK
  • signInWithApple() - Trigger sign-in flow

Functions (Native Module)

  • AppleSignInModule.configure(config) - Configure the native module
  • AppleSignInModule.signIn() - Trigger native sign-in
  • AppleSignInModule.getCredentialState(userID) - Check credential state (iOS only)
  • AppleSignInModule.handleCallback(params) - Complete a pending Android sign-in from a deep-link callback
  • AppleSignInModule.signOut() - Sign out (no-op, clears JS-side storage)

License

MIT

Keywords

react

FAQs

Package last updated on 28 Mar 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts