Skip to main content

🔐 Authentication Guide

Prerequisites
  • API key configured (see API Key Setup)
  • BRDZ SDK installed and initialized

Overview

This guide covers complete user authentication including traditional login/register and Two-Factor Authentication (2FA) implementation.

Traditional Authentication

User Registration

import brdzSDK from 'anantla_sdk';

const auth = brdzSDK.auth;

// Register new user
const registerUser = async (userData) => {
try {
const result = await auth.registerUser({
email: 'newuser@example.com',
username: 'newuser',
client_alias: 'My App',
client_type: 'individual',
country_code: 'ID',
phone: '+628123456789'
});

console.log('Registration successful:', result);
return result;
} catch (error) {
console.error('Registration failed:', error);
throw error;
}
};

User Login

const loginUser = async (email, password) => {
try {
const result = await auth.loginUser(email, password);

// Check if 2FA is required
if (result.requires_2fa) {
console.log('2FA required for user:', result.user_id);
return {
success: false,
requires_2fa: true,
user_id: result.user_id,
message: '2FA verification required'
};
}

// Save JWT token for authenticated requests
localStorage.setItem('brdz_auth_token', result.token);
localStorage.setItem('user_id', result.user_id);

// Update SDK configuration
const config = brdzSDK.config;
config.setToken(result.token);

console.log('Login successful:', result);
return result;

} catch (error) {
console.error('Login failed:', error);
throw error;
}
};

Get User Profile

const getUserProfile = async (userId) => {
try {
const profile = await auth.getUserProfile(userId);
console.log('User profile:', profile);
return profile;
} catch (error) {
console.error('Failed to get profile:', error);
throw error;
}
};

Password Reset

const resetPassword = async (email) => {
try {
const result = await auth.forgotPassword(email);
console.log('Password reset email sent:', result);
return result;
} catch (error) {
console.error('Password reset failed:', error);
throw error;
}
};

Two-Factor Authentication (2FA)

Enable 2FA (User Settings)

const twofa = brdzSDK.twofa;

// Step 1: Generate QR Code for 2FA setup
const setup2FA = async () => {
try {
const setupResult = await twofa.setup();

console.log('2FA Setup Data:');
console.log('QR Code URL:', setupResult.qr_code_url);
console.log('Manual Entry Key:', setupResult.manual_entry_key);

// Display QR code to user for scanning with authenticator app
return setupResult;
} catch (error) {
console.error('2FA setup failed:', error);
throw error;
}
};

// Step 2: Enable 2FA after user scans QR code
const enable2FA = async (tokenFromApp) => {
try {
const result = await twofa.enable(tokenFromApp);
console.log('2FA enabled successfully:', result);

// 2FA is now active for this user
return result;
} catch (error) {
console.error('2FA enable failed:', error);
throw error;
}
};

// Check 2FA status
const check2FAStatus = async () => {
try {
const status = await twofa.getStatus();
console.log('2FA Status:', status);
return status.is_enabled;
} catch (error) {
console.error('Failed to check 2FA status:', error);
return false;
}
};

Login with 2FA

const loginWith2FA = async (email, password) => {
try {
// Step 1: Initial login
const loginResult = await auth.loginUser(email, password);

if (!loginResult.requires_2fa) {
// No 2FA required, login complete
localStorage.setItem('brdz_auth_token', loginResult.token);
localStorage.setItem('user_id', loginResult.user_id);

const config = brdzSDK.config;
config.setToken(loginResult.token);

return loginResult;
}

// Step 2: 2FA verification required
console.log('2FA verification required');
const userId = loginResult.user_id;

// Get 2FA token from user input (6-digit code from authenticator app)
const twoFactorCode = await getTwoFactorCodeFromUser(); // Your UI implementation

// Step 3: Complete login with 2FA
const completeResult = await auth.completeLoginWith2FA(userId, twoFactorCode);

// Save tokens
localStorage.setItem('brdz_auth_token', completeResult.token);
localStorage.setItem('user_id', userId);

// Update SDK configuration
const config = brdzSDK.config;
config.setToken(completeResult.token);

console.log('Login with 2FA successful:', completeResult);
return completeResult;

} catch (error) {
console.error('2FA login failed:', error);
throw error;
}
};

// Helper function - implement based on your UI
const getTwoFactorCodeFromUser = async () => {
// TODO: Implement your UI to get 6-digit code from user
// This could be a modal, prompt, or form input
return new Promise((resolve) => {
// Your implementation here
const code = prompt('Enter 6-digit code from authenticator app:');
resolve(code);
});
};

2FA Management

// Get backup codes (save these securely!)
const getBackupCodes = async (password) => {
try {
const codes = await twofa.getBackupCodes(password);
console.log('Backup codes:', codes);

// Display to user - they should save these securely
return codes;
} catch (error) {
console.error('Failed to get backup codes:', error);
throw error;
}
};

// Disable 2FA
const disable2FA = async (currentPassword, twoFactorCode) => {
try {
const result = await twofa.disable(twoFactorCode, currentPassword);
console.log('2FA disabled:', result);
return result;
} catch (error) {
console.error('Failed to disable 2FA:', error);
throw error;
}
};

// Verify 2FA code (for login)
const verify2FACode = async (userId, code) => {
try {
const result = await twofa.verifyLogin(userId, code);
return result;
} catch (error) {
console.error('2FA verification failed:', error);
throw error;
}
};

Complete Authentication Implementation

class AuthenticationManager {
constructor() {
this.isAuthenticated = false;
this.currentUser = null;
this.init();
}

async init() {
// Check if user is already logged in
const token = localStorage.getItem('brdz_auth_token');
const userId = localStorage.getItem('user_id');

if (token && userId) {
// Set token in SDK
const config = brdzSDK.config;
config.setToken(token);

try {
// Verify token is still valid
const profile = await brdzSDK.auth.getUserProfile(userId);
this.currentUser = profile;
this.isAuthenticated = true;
console.log('User already authenticated:', profile.username);
} catch (error) {
// Token expired or invalid
this.logout();
}
}
}

async register(userData) {
try {
const result = await brdzSDK.auth.registerUser(userData);
console.log('Registration successful');
return result;
} catch (error) {
throw this.handleAuthError(error);
}
}

async login(email, password) {
try {
const result = await brdzSDK.auth.loginUser(email, password);

if (result.requires_2fa) {
return {
success: false,
requires_2fa: true,
user_id: result.user_id
};
}

return this.completeLogin(result);
} catch (error) {
throw this.handleAuthError(error);
}
}

async loginWith2FA(userId, twoFactorCode) {
try {
const result = await brdzSDK.auth.completeLoginWith2FA(userId, twoFactorCode);
return this.completeLogin(result);
} catch (error) {
throw this.handleAuthError(error);
}
}

completeLogin(result) {
// Save authentication data
localStorage.setItem('brdz_auth_token', result.token);
localStorage.setItem('user_id', result.user_id);

// Update SDK configuration
const config = brdzSDK.config;
config.setToken(result.token);

// Update state
this.isAuthenticated = true;
this.currentUser = result.user;

console.log('Login completed successfully');
return result;
}

async setup2FA() {
if (!this.isAuthenticated) {
throw new Error('User must be logged in to setup 2FA');
}

try {
const setupResult = await brdzSDK.twofa.setup();
return setupResult;
} catch (error) {
throw this.handleAuthError(error);
}
}

async enable2FA(code) {
try {
const result = await brdzSDK.twofa.enable(code);
console.log('2FA enabled for user');
return result;
} catch (error) {
throw this.handleAuthError(error);
}
}

async check2FAStatus() {
try {
const status = await brdzSDK.twofa.getStatus();
return status.is_enabled;
} catch (error) {
console.error('Failed to check 2FA status');
return false;
}
}

logout() {
// Clear stored data
localStorage.removeItem('brdz_auth_token');
localStorage.removeItem('user_id');

// Clear SDK token
const config = brdzSDK.config;
config.setToken('');

// Update state
this.isAuthenticated = false;
this.currentUser = null;

console.log('User logged out');
}

handleAuthError(error) {
if (error.message.includes('Invalid credentials')) {
return new Error('Invalid email or password');
}
if (error.message.includes('User not found')) {
return new Error('Account not found');
}
if (error.message.includes('2FA required')) {
return new Error('Two-factor authentication required');
}
if (error.message.includes('Invalid 2FA')) {
return new Error('Invalid authenticator code');
}

return error;
}

getCurrentUser() {
return this.currentUser;
}

isLoggedIn() {
return this.isAuthenticated;
}
}

// Usage
const authManager = new AuthenticationManager();

Usage Examples

Basic Login Flow

// Initialize authentication manager
const authManager = new AuthenticationManager();

// Login attempt
try {
const result = await authManager.login('user@example.com', 'password123');

if (result.requires_2fa) {
// Show 2FA input form
const code = await getUserInput2FA(); // Your UI implementation
const finalResult = await authManager.loginWith2FA(result.user_id, code);
console.log('Login successful with 2FA');
} else {
console.log('Login successful');
}
} catch (error) {
console.error('Login failed:', error.message);
}

2FA Setup Flow

// User wants to enable 2FA in settings
const enable2FAForUser = async () => {
try {
// Step 1: Generate QR code
const setup = await authManager.setup2FA();

// Step 2: Show QR code to user
displayQRCode(setup.qr_code_url); // Your UI implementation

// Step 3: Wait for user to scan and enter code
const code = await getUserInput2FA(); // Your UI implementation

// Step 4: Enable 2FA
await authManager.enable2FA(code);

alert('2FA enabled successfully!');
} catch (error) {
alert('2FA setup failed: ' + error.message);
}
};

Security Best Practices

Security Guidelines
  1. Store JWT tokens securely in localStorage (or httpOnly cookies for SSR)
  2. Implement token refresh logic for long-lived applications
  3. Clear tokens on logout completely
  4. Validate tokens on app initialization
  5. Handle token expiration gracefully
  6. Use HTTPS only for all authentication flows
  7. Encourage 2FA usage for enhanced security

Error Handling

const handleAuthErrors = (error) => {
switch (error.message) {
case 'Invalid credentials':
return 'Email or password is incorrect';
case 'User not found':
return 'No account found with this email';
case '2FA required':
return 'Please enter your 2FA code';
case 'Invalid 2FA code':
return 'Invalid authenticator code. Please try again';
case 'Token expired':
return 'Session expired. Please login again';
default:
return 'Authentication failed. Please try again';
}
};

Next Steps

Continue with the remaining guides:

  1. API Key Setup - Complete
  2. Authentication - Complete
  3. Quickstart Tutorial - Build your first app
  4. React Integration - Frontend components

Need Help?

If you encounter issues: