UNPKG

@tradly/auth

Version:

Auth package for Tradly - handles authentication (email, phone, social login)

825 lines (613 loc) 18.9 kB
# @tradly/auth Authentication package for Tradly platform - handles email, phone, and social login with automatic PK key and auth key management. ## Installation ```bash npm install @tradly/auth ``` ## Quick Start ```typescript import { initializeAuth, emailLogin } from "@tradly/auth"; // Initialize the package with your domain and environment initializeAuth("beauty.tradly.co", "production"); // Now you can use all auth functions const response = await emailLogin("user@example.com", "password123"); if (response.status) { console.log("Login successful!", response.data); } ``` ## Initialization **Important:** You must call `initializeAuth()` before using any other functions. This sets up the domain, environment, and base URL for all API calls. **Automatic Features on Initialization:** - ✅ **UUID Auto-Generation** - Automatically generates and stores UUID in cookie/localStorage - ✅ **PK Key Auto-Fetch** - Automatically fetches and caches PK key from API - ✅ **PK Key Encryption** - PK key is stored encrypted in cookie for security ```typescript import { initializeAuth } from "@tradly/auth"; // Initialize with domain and environment // This automatically: // 1. Generates UUID (if not exists) // 2. Fetches PK key from API // 3. Stores PK key encrypted in cookie // 4. Caches everything for fast access initializeAuth("beauty.tradly.co", "production"); // Or with custom base URL initializeAuth("beauty.tradly.co", "production", "https://api.custom.com"); ``` ### Supported Environments - `production` - Uses `https://api.tradly.app` (default) - `development` - Uses `https://api.dev.tradly.app` - `local` - Uses `http://localhost:3000` ### Multi-Domain Support The package supports multiple domains in the same browser session. Each domain maintains its own configuration, auth keys, and PK keys. ```typescript // Initialize first domain initializeAuth("beauty.tradly.co", "production"); // Switch to another domain initializeAuth("fashion.tradly.co", "production"); // Get config for specific domain import { getAuthConfigByDomain } from "@tradly/auth"; const config = getAuthConfigByDomain("beauty.tradly.co"); ``` ## Authentication Methods ### Email Login ```typescript import { emailLogin } from "@tradly/auth"; const response = await emailLogin("user@example.com", "password123"); if (response.status) { const { user } = response.data; // Auth keys are automatically stored in cookies/localStorage console.log("User:", user); } else { console.error("Login failed:", response.error); } ``` ### Phone Login ```typescript import { phoneLogin } from "@tradly/auth"; const response = await phoneLogin( "1234567890", // phone number "+1", // country code "password123" // password ); if (response.status) { console.log("Login successful!", response.data); } ``` ### Social Login ```typescript import { socialLogin } from "@tradly/auth"; // Google login const googleResponse = await socialLogin("google", googleAccessToken); // Facebook login const facebookResponse = await socialLogin("facebook", facebookAccessToken); // Note: // Currently the SDK types support "google" and "facebook" as providers. // Apple login can be added when backend and SDK support are aligned. ``` ## Sign Up ### Email Sign Up ```typescript import { emailSignUp } from "@tradly/auth"; const response = await emailSignUp( "John", // first name "Doe", // last name "user@example.com", // email "password123" // password ); if (response.status) { console.log("Sign up successful!", response.data); } ``` ### Phone Sign Up ```typescript import { phoneSignUp } from "@tradly/auth"; const response = await phoneSignUp( "John", // first name "Doe", // last name "1234567890", // phone number "+1", // country code "password123" // password ); if (response.status) { console.log("Sign up successful!", response.data); } ``` ## Verification ### Verify OTP ```typescript import { verifyUser } from "@tradly/auth"; const response = await verifyUser( verifyId, // Verification ID from sign up response "123456" // OTP code ); if (response.status) { console.log("Verification successful!", response.data.user); } ``` ### Resend OTP ```typescript import { resendOTP } from "@tradly/auth"; const response = await resendOTP({ verify_id: verifyId, // ... other user data }); if (response.status) { console.log("OTP resent successfully!"); } ``` ## User Profile ### Get User Profile ```typescript import { getUserProfile } from "@tradly/auth"; const response = await getUserProfile(); if (response.status) { const user = response.data; console.log("User profile:", user); } ``` ### Update User Profile ```typescript import { updateUserProfile } from "@tradly/auth"; const response = await updateUserProfile({ first_name: "John", last_name: "Doe", phone: "1234567890", country_code: "+1", // ... other fields }); if (response.status) { console.log("Profile updated!", response.data); } ``` ### Get User Info ```typescript import { getUserInfo } from "@tradly/auth"; // Get a specific user by ID const response = await getUserInfo(123); if (response.status) { console.log("User info:", response.data); } ``` ## Auth Key Management The package automatically manages auth keys using domain-scoped cookies and localStorage. ### Get Auth Key ```typescript import { getAuthKey, getUUID, getRefreshKey } from "@tradly/auth"; // Get current auth key (automatically reads from cookies/localStorage) const authKey = getAuthKey(); // Get UUID const uuid = getUUID(); // Get refresh key const refreshKey = getRefreshKey(); ``` ### Set Auth Key ```typescript import { setAuthKey, setUUID } from "@tradly/auth"; // Set auth key (stores in cookies and localStorage) setAuthKey("your-auth-key"); // Set UUID setUUID("your-uuid"); ``` ### Logout ```typescript import { logout, quickLogout } from "@tradly/auth"; // Full logout - calls logout API and clears all data const response = await logout(); if (response.status) { console.log("Logout successful:", response.data?.message); } // Logout with UUID clearing (optional) await logout({ clearUUID: true }); // Quick logout - clears all data without API call (client-side only) quickLogout(); // Keeps UUID quickLogout(true); // Also clears UUID ``` **What `logout()` clears:** - ✅ Auth key (from cache, cookie, localStorage) - ✅ Refresh key (from cache, cookie, localStorage) - ✅ Firebase token (from cache, cookie, localStorage) - ✅ User info (from cache, localStorage) - ✅ PK key cache - ✅ Optionally UUID (default: keeps UUID for future logins) **Note:** The logout function always clears local data even if the API call fails, ensuring users are logged out locally. ### Clear Auth Key (Manual) ```typescript import { clearAuthKey, clearAllUserData } from "@tradly/auth"; // Clear only auth key clearAuthKey(); // Clear all user data (auth_key, refresh_key, firebase_token, user_info) clearAllUserData(); ``` ### Check Auth Key Status ```typescript import { hasAuthKey, hasUUID } from "@tradly/auth"; if (hasAuthKey()) { console.log("User is authenticated"); } if (hasUUID()) { console.log("UUID is set"); } ``` ## PK Key Management ### Automatic PK Key Fetching When you call `initializeAuth()`, the PK key is automatically fetched and: - ✅ Cached in memory (1 hour TTL) - ✅ Stored encrypted in cookie (1 hour TTL) - ✅ Available immediately for all API calls **Security:** PK keys are encrypted using domain-based encryption before storing in cookies. ### Get PK Key by Domain ```typescript import { getPKKeyByDomain } from "@tradly/auth"; // Get PK key (checks cache first, then encrypted cookie, then API) // Automatically stores encrypted in cookie after fetch const pkData = await getPKKeyByDomain("beauty.tradly.co", "production"); if (pkData) { const pkKey = pkData.key; console.log("PK Key:", pkKey); console.log("Domain Info:", pkData.domain); } ``` **Note:** PK key is automatically fetched during `initializeAuth()`, so you rarely need to call this manually. ### Get Cached PK Key ```typescript import { getCachedPKKey } from "@tradly/auth"; // Get PK key from cache (no API call) const cachedPkKey = getCachedPKKey("beauty.tradly.co", "production"); if (cachedPkKey) { console.log("Cached PK Key:", cachedPkKey.key); } ``` ### Clear PK Key Cache ```typescript import { clearPKKeyCache } from "@tradly/auth"; // Clear cached PK key clearPKKeyCache("beauty.tradly.co", "production"); ``` ## Auth Type Validation ### Get Auth Type ```typescript import { getAuthType } from "@tradly/auth"; // Get auth type configuration const authType = await getAuthType(); // authType can be: // - 1: Email only // - 2: Phone only // - 3: Both email and phone // - null: Not configured ``` ### Check Auth Methods ```typescript import { isEmailAuthEnabled, isPhoneAuthEnabled } from "@tradly/auth"; // Check if email auth is enabled const emailEnabled = await isEmailAuthEnabled(); // Check if phone auth is enabled const phoneEnabled = await isPhoneAuthEnabled(); ``` ## Configuration ### Get Configuration ```typescript import { getAuthConfig, getDomain, getEnv, getBaseUrl, isAuthInitialized, } from "@tradly/auth"; // Get full config const config = getAuthConfig(); console.log(config); // { domain, env, baseUrl } // Get individual values const domain = getDomain(); const env = getEnv(); const baseUrl = getBaseUrl(); // Check if initialized if (isAuthInitialized()) { console.log("Auth package is initialized"); } ``` ### Clear Configuration ```typescript import { clearAuthConfig, clearAuthConfigByDomain } from "@tradly/auth"; // Clear current domain config clearAuthConfig(); // Clear specific domain config clearAuthConfigByDomain("beauty.tradly.co"); ``` ## Custom Auth Key Source (Advanced) For custom implementations (e.g., Next.js server-side with cookies-next): ```typescript import { setAuthKeySource } from "@tradly/auth"; import { getCookie } from "cookies-next"; setAuthKeySource({ getAuthKey: () => { // Custom implementation return getCookie(`${domain}_auth_key`, { req, res }); }, getUUID: () => { return getCookie(`${domain}_uuid`, { req, res }); }, getDomain: () => { return req.headers.host || window.location.host; }, }); ``` ## API Fetch Utilities The package provides low-level fetch utilities that automatically handle PK keys and auth keys: ```typescript import { get, post, put, del } from "@tradly/auth"; // GET request (automatically includes auth key or PK key) const response = await get("/v1/users/me"); // POST request const response = await post("/v1/users", { name: "John Doe", }); // PUT request const response = await put("/v1/users/123", { name: "Jane Doe", }); // DELETE request const response = await del("/v1/users/123"); ``` ## Features - ✅ **Automatic PK Key Management** - Fetches and caches PK keys automatically on initialization - ✅ **PK Key Encryption** - PK keys are encrypted (hash-based) before storing in cookies - ✅ **Automatic UUID Generation** - Generates and stores UUID automatically on initialization - ✅ **Automatic Auth Key Management** - Stores and retrieves auth keys from cookies/localStorage - ✅ **Domain-Scoped Configuration** - Supports multiple domains in the same session - ✅ **Email Authentication** - Login and sign up with email - ✅ **Phone Authentication** - Login and sign up with phone - ✅ **Social Authentication** - Google, Facebook, Apple login - ✅ **OTP Verification** - Verify and resend OTP codes - ✅ **User Profile Management** - Get, update user profile - ✅ **Auth Type Validation** - Check which auth methods are enabled - ✅ **Complete Logout** - Calls logout API and clears all stored data (auth_key, refresh_key, firebase_token, user_info, PK key cache) - ✅ **TypeScript Support** - Full TypeScript definitions - ✅ **Zero Configuration** - Works out of the box with automatic cookie/localStorage handling - ✅ **Server-Side Support** - Custom auth key source for SSR - ✅ **Built-in Caching** - PK keys and responses are cached automatically - ✅ **Secure Storage** - PK keys encrypted with domain-based hash algorithm for cookie storage ## Testing ```bash # Run all tests npm run test:all # Run integration tests (against real API) npm run test:integration # Run unit tests npm run test:unit # Run tests in watch mode npm run test:watch # Run tests with coverage npm run test:coverage # Run tests with UI npm run test:ui ``` ## TypeScript Full TypeScript support with comprehensive type definitions: ```typescript import type { ApiResponse, LoginResponse, SignUpResponse, UserProfile, PKKeyResponse, } from "@tradly/auth"; const response: ApiResponse<UserProfile> = await getUserProfile(); ``` ## Error Handling All API functions return a consistent response format: ```typescript interface ApiResponse<T> { status: boolean; data: T; error?: { code: number; message: string; }; } ``` Example: ```typescript const response = await emailLogin("user@example.com", "wrong-password"); if (!response.status) { console.error("Error:", response.error?.message); console.error("Code:", response.error?.code); } ``` ## Cookie Format The package uses domain-scoped cookie naming: - **Auth Key**: `${domain}_auth_key` (e.g., `beauty.tradly.co_auth_key`) - **UUID**: `${domain}_uuid` (e.g., `beauty.tradly.co_uuid`) - **Refresh Key**: `${domain}_refresh_key` (e.g., `beauty.tradly.co_refresh_key`) - **PK Key**: `${domain}_pk_key_${env}` (e.g., `beauty.tradly.co_pk_key_production`) - **Encrypted** **Security Note:** PK keys are encrypted using a domain-based hash algorithm before storing in cookies. The encryption ensures that even if cookies are accessed, the PK key cannot be easily extracted. This ensures no conflicts when multiple Tradly applications run in the same browser. ## Examples ### Complete Login Flow ```typescript import { initializeAuth, emailLogin, getUserProfile, logout, } from "@tradly/auth"; // Initialize initializeAuth("beauty.tradly.co", "production"); // Login const loginResponse = await emailLogin("user@example.com", "password123"); if (loginResponse.status) { // All keys and user info are automatically stored console.log("Login successful!"); // Get user profile const profileResponse = await getUserProfile(); if (profileResponse.status) { console.log("User:", profileResponse.data); } // Logout (calls API and clears all data) const logoutResponse = await logout(); if (logoutResponse.status) { console.log("Logout successful!"); } } else { console.error("Login failed:", loginResponse.error); } ``` ### Sign Up with Verification ```typescript import { initializeAuth, emailSignUp, verifyUser, resendOTP, } from "@tradly/auth"; initializeAuth("beauty.tradly.co", "production"); // Sign up const signUpResponse = await emailSignUp( "John", "Doe", "user@example.com", "password123" ); if (signUpResponse.status) { const { verify_id } = signUpResponse.data; // Verify OTP const verifyResponse = await verifyUser(verify_id, "123456"); if (verifyResponse.status) { console.log("Account verified!"); } else { // Resend OTP if needed await resendOTP({ verify_id }); } } ``` ## Next.js Integration For Next.js projects, see the [Next.js Integration Guide](./NEXTJS.md) for detailed setup instructions. The SDK supports both **server-only** usage and **hybrid (server + client)** usage: ### 1. Server-only usage (no client initialization) Use this when: - All auth-dependent logic runs on the server (server components, route handlers, server actions). - You read cookies on the server and pass data down to client components as props. In this case you **do not need any client-side initialization** component. ```typescript // app/layout.tsx (Server Component) import { initializeAuth, setAuthKeySource } from "@tradly/auth"; import { cookies } from "next/headers"; const DOMAIN = "beauty.tradly.co"; // Initialize on server side (for server components) initializeAuth(DOMAIN, "production"); // Set up cookie reading for server components setAuthKeySource({ getAuthKey: () => { const cookieStore = cookies(); return cookieStore.get(`${DOMAIN}_auth_key`)?.value || null; }, getUUID: () => { const cookieStore = cookies(); return cookieStore.get(`${DOMAIN}_uuid`)?.value || null; }, getDomain: () => DOMAIN, }); export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html> <body>{children}</body> </html> ); } ``` In this setup: - `initializeAuth` configures domain/env/base URL. - `setAuthKeySource` tells the SDK how to read `auth_key`/`uuid` from Next.js server cookies. - Server components can safely call `emailLogin`, `getUserProfile`, etc. without any client initializer. ### 2. Hybrid usage (server + client initialization) Use this when: - You have client components that need to call SDK methods directly in the browser (e.g. login forms, sign-up forms, profile pages). - You want the SDK to create and manage cookies in the browser (UUID, auth key, refresh key, PK key). In this case you should still initialize on the server **and** add the client-side `<AuthClientInit />` helper: ```typescript // app/layout.tsx (Server Component) import { initializeAuth, setAuthKeySource } from "@tradly/auth"; import { cookies } from "next/headers"; import { AuthClientInit } from "@tradly/auth/examples/nextjs-client-init"; const DOMAIN = "beauty.tradly.co"; // Initialize on server side (for server components) initializeAuth(DOMAIN, "production"); // Set up cookie reading for server components setAuthKeySource({ getAuthKey: () => { const cookieStore = cookies(); return cookieStore.get(`${DOMAIN}_auth_key`)?.value || null; }, getUUID: () => { const cookieStore = cookies(); return cookieStore.get(`${DOMAIN}_uuid`)?.value || null; }, getDomain: () => DOMAIN, }); export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html> <body> {/* Client-side initialization - ensures UUID & PK key are created and kept in sync in the browser */} <AuthClientInit domain={DOMAIN} env="production" /> {children} </body> </html> ); } ``` Here: - Server components can still use the SDK via `setAuthKeySource`. - Client components can also call SDK functions (like `emailLogin`) and rely on browser APIs (cookies, localStorage). ✅ **Server-side only** – just `initializeAuth` + `setAuthKeySource` ✅ **Server + client** – `initializeAuth` + `setAuthKeySource` + `AuthClientInit` ✅ **Works in Server Components** – via `setAuthKeySource` ✅ **Works in Client Components** – via browser-based initialization ## License ISC ## Repository https://github.com/TRADLY-PLATFORM