Authentication Configuration
Lovrabet SDK supports multiple authentication methods to meet different security requirements. This document details the configuration and usage of various authentication methods.
Before starting, please ensure you have completed SDK Configuration. It is recommended to use CLI auto-generated configuration.
Authentication Methods Overview
The SDK supports the following authentication methods:
- User Token Authentication - Suitable for scenarios after user login
- OpenAPI Key Authentication - Suitable for server-to-server calls
- Cookie Authentication (Automatic) - Suitable for logged-in users in browser environments
- Runtime Dynamic Switching - Supports dynamic updates of authentication information
👤 User Token Authentication
Method 1: Specify via ClientConfig (Recommended)
import { registerModels, createClient } from "@lovrabet/sdk";
// Register base configuration first (recommended to use CLI auto-generation)
registerModels({
appCode: "my-app",
models: [
{ datasetCode: "8d2dcbae08b54bdd84c00be558ed48df", tableName: "users", alias: "users" },
{ datasetCode: "a1b2c3d4e5f6789012345678abcdef12", tableName: "orders", alias: "orders" },
],
});
// Create authenticated client
const client = createClient({
token: "your-user-token",
});
// Standard access method
const users = await client.models.dataset_8d2dcbae08b54bdd84c00be558ed48df.filter();
// Or use alias (syntactic sugar)
const users = await client.models.users.filter();
Method 2: Pass Configuration Directly
const client = createClient({
appCode: "my-app",
token: "your-user-token",
models: [
{ datasetCode: "8d2dcbae08b54bdd84c00be558ed48df", tableName: "users", alias: "users" },
{ datasetCode: "a1b2c3d4e5f6789012345678abcdef12", tableName: "orders", alias: "orders" },
],
});
// Standard access method
const users = await client.models.dataset_8d2dcbae08b54bdd84c00be558ed48df.filter();
Practical Application Example
// auth/client.ts
import { createClient } from "@lovrabet/sdk";
import "./api/api"; // Import CLI-generated configuration
import { getAuthToken } from "./auth-service";
// Create authenticated client factory
export const createAuthenticatedClient = () => {
const token = getAuthToken(); // Get token from storage
return createClient({
token,
options: {
onError: (error) => {
if (error.message.includes("unauthorized")) {
// Token expired, redirect to login page
window.location.href = "/login";
}
},
},
});
};
// Usage
const client = createAuthenticatedClient();
// Standard access method
const users = await client.models.dataset_8d2dcbae08b54bdd84c00be558ed48df.filter();
// Or use alias
const users = await client.models.users.filter();
🔑 OpenAPI Key Authentication
OpenAPI key authentication is suitable for server-to-server calls, providing higher security.
⚠️ accessKey can only be used on the server side!
Using accessKey in browser environments poses serious security risks:
- 🔓 Keys will be exposed in client-side code, visible to anyone
- 🚨 Attackers can obtain your keys and impersonate your application to make requests
- 💸 May lead to data breaches, malicious operations, and financial losses
Correct Approach:
- ✅ Use accessKey for authentication on the server side
- ✅ Use user Token or Cookie authentication on the browser side
- ✅ Generate and distribute Tokens for the frontend through server-side APIs
Authentication Flow Comparison:
Secure Server-Side Proxy Pattern
It is recommended to create an API proxy on the server side to provide secure data access for the frontend:
// Server side: Use accessKey
import { createClient } from '@lovrabet/sdk';
const serverClient = createClient({
accessKey: process.env.LOVRABET_ACCESS_KEY,
});
// API route: /api/users
export async function GET(request: Request) {
// Validate user identity (from session/cookie)
const user = await validateUser(request);
if (!user) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
// Use server-side client to get data
const users = await serverClient.models.dataset_8d2dcbae08b54bdd84c00be558ed48df.filter();
return Response.json(users);
}
// Browser side: Call server API
fetch('/api/users')
.then(res => res.json())
.then(data => console.log(data));
Method 1: Specify via ClientConfig (Recommended)
// Register base configuration first (recommended to use CLI auto-generation)
registerModels({
appCode: "my-app",
models: [
{ datasetCode: "8d2dcbae08b54bdd84c00be558ed48df", tableName: "users", alias: "users" },
{ datasetCode: "a1b2c3d4e5f6789012345678abcdef12", tableName: "analytics", alias: "analytics" },
],
});
// Create client with key authentication
const client = createClient({
accessKey: "your-access-key",
secretKey: "your-secret-key",
});
// Standard access method
const users = await client.models.dataset_8d2dcbae08b54bdd84c00be558ed48df.filter();
Method 2: Pass Configuration Directly
const client = createClient({
appCode: "my-app",
accessKey: "your-access-key",
secretKey: "your-secret-key",
models: [
{ datasetCode: "8d2dcbae08b54bdd84c00be558ed48df", tableName: "users", alias: "users" },
{ datasetCode: "a1b2c3d4e5f6789012345678abcdef12", tableName: "analytics", alias: "analytics" },
],
});
// Standard access method
const analytics = await client.models.dataset_a1b2c3d4e5f6789012345678abcdef12.filter();
Server-Side Application Example
// server/lovrabet-client.ts
import { registerModels, createClient } from "@lovrabet/sdk";
registerModels({
appCode: process.env.LOVRABET_APP_CODE,
models: [
{
datasetCode: process.env.USERS_DATASET_CODE,
tableName: "users",
alias: "users",
},
{
datasetCode: process.env.ORDERS_DATASET_CODE,
tableName: "orders",
alias: "orders",
},
],
});
// Use keys from environment variables
export const serverClient = createClient({
accessKey: process.env.LOVRABET_ACCESS_KEY,
secretKey: process.env.LOVRABET_SECRET_KEY,
});
// Use in API routes
export async function GET() {
try {
// Use datasetCode from environment variables
const users = await serverClient.models[`dataset_${process.env.USERS_DATASET_CODE}`].filter({
currentPage: 1,
pageSize: 100,
});
return Response.json(users);
} catch (error) {
console.error("Failed to fetch user data:", error);
return Response.json({ error: "Internal Server Error" }, { status: 500 });
}
}
🍪 Cookie Authentication (Automatic)
If no token or key is provided, the SDK will automatically use browser cookies for authentication. This is suitable for logged-in users in browser scenarios.
import { createClient } from "@lovrabet/sdk";
import "./api/api"; // Import CLI-generated configuration
// Do not provide any authentication info, automatically use Cookie
const client = createClient();
// If user is logged in, will automatically use login cookie from browser
// Standard access method
const users = await client.models.dataset_8d2dcbae08b54bdd84c00be558ed48df.filter();
// Or use alias
const users = await client.models.users.filter();
Hybrid Authentication Strategy
// Prefer Token, fallback to Cookie
const createSmartClient = (token?: string) => {
const config = token ? { token } : {}; // Use token if available, otherwise rely on Cookie
return createClient(config);
};
// Usage
const tokenFromStorage = localStorage.getItem("auth_token");
const client = createSmartClient(tokenFromStorage);
🔄 Runtime Authentication Switching
The SDK supports dynamically updating authentication information at runtime without recreating the client.
Dynamic Token Setting
const client = createClient(); // Initially no authentication
// After user login, dynamically set token
client.setToken("new-user-token");
// Now can access authenticated APIs
const users = await client.models.users.filter();
// When user logs out, clear token
client.setToken(null);
Real Login Flow Example
// auth/auth-manager.ts
import { createClient } from "@lovrabet/sdk";
import "./api"; // Import pre-registered configuration
class AuthManager {
private client = createClient(); // Initialize client
async login(username: string, password: string) {
try {
// Call login API
const response = await fetch("/api/auth/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
});
if (response.ok) {
const { token } = await response.json();
// Set token to SDK
this.client.setToken(token);
// Store locally
localStorage.setItem("auth_token", token);
return { success: true };
} else {
return { success: false, error: "Login failed" };
}
} catch (error) {
return { success: false, error: "Network error" };
}
}
logout() {
// Clear token in SDK
this.client.setToken(null);
// Clear local storage
localStorage.removeItem("auth_token");
// Redirect to login page
window.location.href = "/login";
}
getClient() {
return this.client;
}
// Restore token from local storage on initialization
init() {
const token = localStorage.getItem("auth_token");
if (token) {
this.client.setToken(token);
}
}
}
export const authManager = new AuthManager();
// Initialize on app startup
authManager.init();
// Export client for business code use
export const lovrabetClient = authManager.getClient();
React Hook Example
// hooks/useAuth.ts
import { useState, useEffect } from "react";
import { authManager, lovrabetClient } from "../auth/auth-manager";
export function useAuth() {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Check authentication status
const checkAuth = async () => {
try {
// Try to get user info to verify authentication status
await lovrabetClient.models.users.getOne("me");
setIsAuthenticated(true);
} catch (error) {
setIsAuthenticated(false);
} finally {
setLoading(false);
}
};
checkAuth();
}, []);
const login = async (username: string, password: string) => {
const result = await authManager.login(username, password);
if (result.success) {
setIsAuthenticated(true);
}
return result;
};
const logout = () => {
authManager.logout();
setIsAuthenticated(false);
};
return {
isAuthenticated,
loading,
login,
logout,
client: lovrabetClient,
};
}
🛡️ Security Best Practices
1. Token Storage Security
// Secure Token storage management
class SecureTokenStorage {
private readonly TOKEN_KEY = "lovrabet_auth_token";
setToken(token: string) {
// Production environment recommends using httpOnly cookie or other secure storage solutions
if (process.env.NODE_ENV === "production") {
// Set secure cookie
document.cookie = `${this.TOKEN_KEY}=${token}; secure; httpOnly; samesite=strict`;
} else {
// Development environment uses localStorage
localStorage.setItem(this.TOKEN_KEY, token);
}
}
getToken(): string | null {
if (process.env.NODE_ENV === "production") {
// Read from cookie
const cookies = document.cookie.split(";");
const tokenCookie = cookies.find(c => c.trim().startsWith(this.TOKEN_KEY));
return tokenCookie ? tokenCookie.split("=")[1] : null;
} else {
return localStorage.getItem(this.TOKEN_KEY);
}
}
removeToken() {
if (process.env.NODE_ENV === "production") {
document.cookie = `${this.TOKEN_KEY}=; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
} else {
localStorage.removeItem(this.TOKEN_KEY);
}
}
}
2. Environment Variable Management
// .env.example
LOVRABET_APP_CODE=your-app-code
LOVRABET_ACCESS_KEY=your-access-key
LOVRABET_SECRET_KEY=your-secret-key
// config/lovrabet.ts
export const lovrabetConfig = {
appCode: process.env.LOVRABET_APP_CODE!,
accessKey: process.env.LOVRABET_ACCESS_KEY,
secretKey: process.env.LOVRABET_SECRET_KEY,
};
// Validate required environment variables
if (!lovrabetConfig.appCode) {
throw new Error("LOVRABET_APP_CODE is required");
}
3. Error Handling and Retry
const client = createClient({
token: "user-token",
options: {
timeout: 30000,
onError: (error) => {
console.error("Lovrabet SDK Error:", {
message: error.message,
status: error.status,
url: error.url,
});
// Handle different error types differently
if (error.status === 401) {
// Authentication failed
console.log("Authentication failed, redirecting to login...");
authManager.logout();
} else if (error.status >= 500) {
// Server error, may consider retry
console.log("Server error, may retry later");
}
},
},
});
🔍 Debugging Authentication Issues
Get Current Configuration Information
const client = createClient({ token: "your-token" });
// Get current configuration (does not include sensitive information)
const config = client.getConfig();
console.log("Current configuration:", {
appCode: config.appCode,
env: config.env,
hasToken: !!config.token,
hasAccessKey: !!config.accessKey,
serverUrl: config.serverUrl,
});
Authentication Status Detection
// Check if authentication is valid
const checkAuthStatus = async (client) => {
try {
// Try calling an API that requires authentication
await client.models.users.filter({ pageSize: 1 });
console.log("✅ Authentication valid");
return true;
} catch (error) {
if (error.status === 401) {
console.log("❌ Authentication invalid or expired");
} else {
console.log("❓ Other error:", error.message);
}
return false;
}
};
📖 Next Steps
After understanding authentication configuration, you can continue learning:
- 📊 API Usage Guide - Deep dive into API operations
- 🎯 TypeScript Support - Type-safe development experience
- 🛠️ Practical Examples - React/Vue integration examples
❓ Frequently Asked Questions
Q: What's the difference between Token and OpenAPI keys?
- Token: User-level authentication, suitable for frontend applications and user-related operations
- OpenAPI Keys: Application-level authentication, suitable for server-to-server calls with higher permissions
Q: How to handle Token expiration?
const client = createClient({
token: "initial-token",
options: {
onError: async (error) => {
if (error.status === 401) {
// Token may be expired, try refreshing
try {
const newToken = await refreshToken();
client.setToken(newToken);
// Can optionally retry the original request
} catch (refreshError) {
// Refresh failed, redirect to login page
window.location.href = "/login";
}
}
},
},
});
Q: How to use in Node.js environment?
Node.js environment recommends using OpenAPI key authentication:
// server/lovrabet.js
const { registerModels, createClient } = require("@lovrabet/sdk");
registerModels({
appCode: process.env.LOVRABET_APP_CODE,
models: [
{ datasetCode: process.env.USERS_DATASET_CODE, tableName: "users", alias: "users" },
],
});
const client = createClient({
accessKey: process.env.LOVRABET_ACCESS_KEY,
secretKey: process.env.LOVRABET_SECRET_KEY,
});
module.exports = { client };
Next Steps
- 📋 Configuration Details - Learn about various configuration methods
- 📊 API Usage Guide - Deep dive into API operations
- 🛠️ Practical Examples - React/Vue integration examples