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",
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.