Basic Usage
This guide provides a quick overview of how to use React Native Credentials Manager to implement different authentication methods in your app.
Import the Library
First, import the necessary functions and types from the package:
import {
  signUpWithPasskeys,
  signUpWithPassword,
  signUpWithGoogle,
  signUpWithApple,
  signIn,
  signOut,
  type Credential,
  type GoogleCredential,
  type AppleCredential,
  type SignInOption,
} from "react-native-credentials-manager";
import { Platform } from "react-native";
Authentication Methods
1. Passkey Authentication
Passkeys provide secure, passwordless authentication using public key cryptography.
Sign Up with Passkeys
async function registerWithPasskey() {
  // Generate a random user ID and encode as base64
  const userId = btoa(`user_${Math.random().toString(36).substring(2)}`);
  const passkeyRequest = {
    challenge: "BASE64_ENCODED_CHALLENGE", // From your server
    rp: {
      name: "Your App Name",
      id: "yourdomain.com",
    },
    user: {
      id: userId,
      name: "user@example.com",
      displayName: "User Name",
    },
    pubKeyCredParams: [
      {
        type: "public-key",
        alg: -7, // ES256
      },
      {
        type: "public-key",
        alg: -257, // RS256
      },
    ],
    timeout: 60000, // 60 seconds
    attestation: "none",
    excludeCredentials: [], // Existing credentials to exclude
    authenticatorSelection: {
      authenticatorAttachment: "platform",
      requireResidentKey: true,
      residentKey: "required",
      userVerification: "required",
    },
  };
  try {
    const response = await signUpWithPasskeys(
      passkeyRequest,
      false // preferImmediatelyAvailableCredentials (Android only)
    );
    // Send the response to your server
    console.log("Passkey registration successful:", response);
    return response;
  } catch (error) {
    console.error("Passkey registration failed:", error);
    throw error;
  }
}
2. Password Authentication
Sign Up with Password (Android Only)
async function registerWithPassword(username: string, password: string) {
  // iOS doesn't support manual password storage
  if (Platform.OS !== "android") {
    console.warn("Manual password storage is not supported on iOS");
    return null;
  }
  try {
    const result = await signUpWithPassword({ username, password });
    console.log("Password registration successful");
    return result;
  } catch (error) {
    console.error("Password registration failed:", error);
    throw error;
  }
}
3. Platform-Specific Sign-Up
Google Sign-In (Android) and Apple Sign-In (iOS)
async function registerWithPlatformSignIn() {
  const WEB_CLIENT_ID = "YOUR_GOOGLE_WEB_CLIENT_ID";
  try {
    let credential;
    // Use platform-specific sign-in methods
    if (Platform.OS === "android") {
      // Google Sign-In on Android
      credential = await signUpWithGoogle({
        serverClientId: WEB_CLIENT_ID,
        autoSelectEnabled: true,
        nonce: "OPTIONAL_NONCE_FOR_SECURITY",
        filterByAuthorizedAccounts: false, // Show all accounts for sign-up
      });
    } else {
      // Apple Sign In on iOS
      credential = await signUpWithApple({
        requestedScopes: ["fullName", "email"],
      });
    }
    // Handle credential based on type
    if (credential.type === "google-signin") {
      // Android response
      const { id, idToken, displayName } = credential;
      console.log("Google Sign-In successful:", { id, idToken, displayName });
    } else if (credential.type === "apple-signin") {
      // iOS response
      const { id, idToken, email } = credential;
      console.log("Apple Sign In successful:", { id, idToken, email });
    }
    return credential;
  } catch (error) {
    console.error("Platform sign-in failed:", error);
    throw error;
  }
}
Unified Sign-In Flow
The library supports multiple authentication methods in a single sign-in flow, making it easy to offer users various ways to authenticate:
async function signInUser() {
  const WEB_CLIENT_ID = "YOUR_GOOGLE_WEB_CLIENT_ID";
  try {
    // Determine which sign-in methods to offer based on platform
    const signInMethods: SignInOption[] = ["passkeys", "password"];
    // Add platform-specific method
    if (Platform.OS === "android") {
      signInMethods.push("google-signin");
    } else {
      signInMethods.push("apple-signin");
    }
    // Prepare parameters for sign-in
    const params: any = {
      // Passkey authentication parameters
      passkeys: {
        challenge: "BASE64_ENCODED_CHALLENGE", // From your server
        timeout: 60000,
        userVerification: "required",
        rpId: "yourdomain.com",
      },
    };
    // Add platform-specific parameters
    if (Platform.OS === "android") {
      params.googleSignIn = {
        serverClientId: WEB_CLIENT_ID,
        autoSelectEnabled: true,
        filterByAuthorizedAccounts: true, // Only show previously authorized accounts
      };
    } else {
      params.appleSignIn = {
        requestedScopes: ["fullName", "email"],
      };
    }
    // Perform the sign-in
    const credential = await signIn(signInMethods, params);
    // Handle different credential types
    switch (credential.type) {
      case "passkey":
        console.log(
          "Passkey authentication successful:",
          credential.authenticationResponseJson
        );
        // Send the authentication response to your server for verification
        return handlePasskeyAuthentication(
          credential.authenticationResponseJson
        );
      case "password":
        console.log("Password authentication successful:", credential.username);
        // Verify password with your backend
        return handlePasswordAuthentication(
          credential.username,
          credential.password
        );
      case "google-signin":
        console.log("Google Sign-In successful:", credential.idToken);
        // Verify the Google token with your backend
        return handleGoogleAuthentication(credential.idToken);
      case "apple-signin":
        console.log("Apple Sign In successful:", credential.idToken);
        // Verify the Apple token with your backend
        return handleAppleAuthentication(credential.idToken);
      default:
        throw new Error(
          `Unsupported credential type: ${(credential as any).type}`
        );
    }
  } catch (error) {
    // Handle common errors
    if (error.message?.includes("CANCELLED")) {
      console.log("User cancelled the sign-in process");
    } else if (error.message?.includes("NO_CREDENTIAL_AVAILABLE")) {
      console.log("No credentials available for the requested methods");
    } else {
      console.error("Sign-in failed:", error);
    }
    throw error;
  }
}
Sign Out
To sign out the user:
async function signOutUser() {
  try {
    await signOut();
    console.log("Successfully signed out");
    // Note: On iOS, signOut() is a no-op as Authentication Services
    // doesn't provide a sign-out method. You should handle
    // sign-out logic in your app separately on iOS.
    // Clear your app's authentication state
    clearAuthState();
  } catch (error) {
    console.error("Sign-out failed:", error);
    throw error;
  }
}
Type Definitions
The library provides TypeScript definitions for all credential types:
// Common credential type (union of all possible credential types)
type Credential =
  | PasskeyCredential
  | PasswordCredential
  | GoogleCredential
  | AppleCredential;
// Passkey credential
type PasskeyCredential = {
  type: "passkey";
  authenticationResponseJson: string;
};
// Password credential
type PasswordCredential = {
  type: "password";
  username: string;
  password: string;
};
// Google credential (Android)
type GoogleCredential = {
  type: "google-signin";
  id: string;
  idToken: string;
  displayName?: string;
  familyName?: string;
  givenName?: string;
  profilePicture?: string;
  phoneNumber?: string;
};
// Apple credential (iOS)
type AppleCredential = {
  type: "apple-signin";
  id: string;
  idToken: string;
  displayName?: string;
  familyName?: string;
  givenName?: string;
  email?: string;
};
// Available sign-in methods
type SignInOption = "passkeys" | "password" | "google-signin" | "apple-signin";
Complete Example
Here's a complete example showing how to implement a flexible authentication system:
import React, { useState } from "react";
import { View, Button, Text, Platform, Alert } from "react-native";
import {
  signUpWithPasskeys,
  signUpWithPassword,
  signUpWithGoogle,
  signIn,
  signOut,
} from "react-native-credentials-manager";
// Configuration
const WEB_CLIENT_ID = "YOUR_GOOGLE_WEB_CLIENT_ID";
const DOMAIN = "yourdomain.com";
export default function AuthScreen() {
  const [loading, setLoading] = useState(false);
  const [user, setUser] = useState(null);
  // Helper to generate a random challenge
  const generateChallenge = () => {
    const array = new Uint8Array(32);
    window.crypto.getRandomValues(array);
    return btoa(String.fromCharCode.apply(null, Array.from(array)));
  };
  // Register with passkey
  const handlePasskeyRegistration = async () => {
    setLoading(true);
    try {
      const userId = btoa(`user_${Math.random().toString(36).substring(2)}`);
      const challenge = generateChallenge();
      const request = {
        challenge,
        rp: { name: "Your App", id: DOMAIN },
        user: { id: userId, name: "user@example.com", displayName: "User" },
        pubKeyCredParams: [
          { type: "public-key", alg: -7 },
          { type: "public-key", alg: -257 },
        ],
        timeout: 60000,
        attestation: "none",
        authenticatorSelection: {
          authenticatorAttachment: "platform",
          requireResidentKey: true,
          residentKey: "required",
          userVerification: "required",
        },
      };
      const response = await signUpWithPasskeys(request);
      // In a real app, you would send this to your server
      // await api.registerPasskey(response);
      Alert.alert("Success", "Passkey registered successfully");
      setUser({ id: userId, type: "passkey" });
    } catch (error) {
      Alert.alert("Error", `Registration failed: ${error.message}`);
    } finally {
      setLoading(false);
    }
  };
  // Sign in with any available method
  const handleSignIn = async () => {
    setLoading(true);
    try {
      const methods = ["passkeys", "password"];
      // Add platform-specific method
      if (Platform.OS === "android") {
        methods.push("google-signin");
      } else {
        methods.push("apple-signin");
      }
      const params = {
        passkeys: {
          challenge: generateChallenge(),
          rpId: DOMAIN,
          timeout: 60000,
          userVerification: "required",
        },
      };
      if (Platform.OS === "android") {
        params.googleSignIn = {
          serverClientId: WEB_CLIENT_ID,
          autoSelectEnabled: true,
          filterByAuthorizedAccounts: true,
        };
      } else {
        params.appleSignIn = {
          requestedScopes: ["fullName", "email"],
        };
      }
      const credential = await signIn(methods, params);
      // Handle different credential types
      let userData = null;
      switch (credential.type) {
        case "passkey":
          userData = { type: "passkey", verified: true };
          break;
        case "password":
          userData = { type: "password", username: credential.username };
          break;
        case "google-signin":
          userData = {
            type: "google",
            id: credential.id,
            name: credential.displayName,
          };
          break;
        case "apple-signin":
          userData = {
            type: "apple",
            id: credential.id,
            email: credential.email,
          };
          break;
      }
      setUser(userData);
      Alert.alert("Success", `Signed in with ${credential.type}`);
    } catch (error) {
      Alert.alert("Error", `Sign in failed: ${error.message}`);
    } finally {
      setLoading(false);
    }
  };
  // Sign out
  const handleSignOut = async () => {
    setLoading(true);
    try {
      await signOut();
      setUser(null);
      Alert.alert("Success", "Signed out successfully");
    } catch (error) {
      Alert.alert("Error", `Sign out failed: ${error.message}`);
    } finally {
      setLoading(false);
    }
  };
  return (
    <View style={{ flex: 1, justifyContent: "center", padding: 20 }}>
      {user ? (
        <>
          <Text style={{ marginBottom: 20, fontSize: 18 }}>
            Signed in as: {JSON.stringify(user, null, 2)}
          </Text>
          <Button title="Sign Out" onPress={handleSignOut} disabled={loading} />
        </>
      ) : (
        <>
          <Button
            title="Register with Passkey"
            onPress={handlePasskeyRegistration}
            disabled={loading}
          />
          <View style={{ height: 20 }} />
          <Button title="Sign In" onPress={handleSignIn} disabled={loading} />
          {loading && <Text>Loading...</Text>}
        </>
      )}
    </View>
  );
}
This example showcases the core functionality of React Native Credentials Manager, allowing users to sign up with passkeys and sign in with any available method. In a real application, you would need to add server-side verification for the authentication responses.