Skip to main content

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",
});
} 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,
};
} 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,
};
} 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.