API Authentication Guide
Learn how to authenticate with the LeafMove API and manage access tokens securely.
🔐 Authentication Methods
Bearer Token Authentication
The LeafMove API uses Bearer Token authentication. You need to include a valid token in the Authorization header of each request.
Authorization: Bearer YOUR_API_TOKEN
Getting API Tokens
Method 1: Login Endpoint
async function login(email, password) {
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: email,
password: password
})
});
const data = await response.json();
if (data.code === 200) {
// Save token
localStorage.setItem('api_token', data.data.token);
return data.data.token;
} else {
throw new Error(data.message);
}
}
Method 2: Admin Dashboard
- Log in to the admin dashboard
- Navigate to "API Management" page
- Click "Generate New Token"
- Copy the generated token
🔑 Token Management
Secure Token Storage
// Token management utility
class TokenManager {
static setToken(token) {
// Use secure storage in production
localStorage.setItem('api_token', token);
}
static getToken() {
return localStorage.getItem('api_token');
}
static removeToken() {
localStorage.removeItem('api_token');
}
static isTokenValid() {
const token = this.getToken();
if (!token) return false;
try {
// Parse JWT token (if using JWT)
const payload = JSON.parse(atob(token.split('.')[1]));
const now = Date.now() / 1000;
return payload.exp > now;
} catch (error) {
return false;
}
}
}
Token Refresh
async function refreshToken() {
const refreshToken = localStorage.getItem('refresh_token');
if (!refreshToken) {
throw new Error('No refresh token available');
}
const response = await fetch('/api/auth/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
refresh_token: refreshToken
})
});
const data = await response.json();
if (data.code === 200) {
TokenManager.setToken(data.data.access_token);
localStorage.setItem('refresh_token', data.data.refresh_token);
return data.data.access_token;
} else {
// Refresh failed, need to re-login
TokenManager.removeToken();
localStorage.removeItem('refresh_token');
throw new Error('Token refresh failed');
}
}
🛡️ Permission Control
Permission Levels
Permission Level | Description | Accessible Endpoints |
---|---|---|
admin | Administrator | All endpoints |
user | Regular user | User-related endpoints |
readonly | Read-only user | Query endpoints only |
Permission Checking
class APIClient {
constructor(token) {
this.token = token;
this.userInfo = null;
}
async getUserInfo() {
if (!this.userInfo) {
const response = await this.request('/api/user/profile');
this.userInfo = response.data;
}
return this.userInfo;
}
async hasPermission(permission) {
const userInfo = await this.getUserInfo();
return userInfo.permissions.includes(permission);
}
async request(endpoint, options = {}) {
const headers = {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json',
...options.headers
};
const response = await fetch(endpoint, {
...options,
headers
});
if (response.status === 401) {
// Token expired or invalid
throw new AuthError('Authentication failed');
}
if (response.status === 403) {
// Insufficient permissions
throw new PermissionError('Permission denied');
}
return response.json();
}
}
🔒 Security Best Practices
1. Token Security
// ✅ Recommended: Use HTTPS
const API_BASE_URL = 'https://api.leafmove.com';
// ❌ Avoid: Passing token in URL
// https://api.leafmove.com/users?token=xxx
// ✅ Recommended: Pass in header
headers: {
'Authorization': 'Bearer ' + token
}
2. Token Expiration Handling
class AuthenticatedAPIClient {
async request(endpoint, options = {}) {
try {
return await this.makeRequest(endpoint, options);
} catch (error) {
if (error.status === 401) {
// Try to refresh token
try {
await this.refreshToken();
return await this.makeRequest(endpoint, options);
} catch (refreshError) {
// Refresh failed, redirect to login
this.redirectToLogin();
throw refreshError;
}
}
throw error;
}
}
redirectToLogin() {
window.location.href = '/login';
}
}
3. Request Interceptors
// Using Axios interceptors example
import axios from 'axios';
const apiClient = axios.create({
baseURL: 'https://api.leafmove.com'
});
// Request interceptor
apiClient.interceptors.request.use(
config => {
const token = TokenManager.getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => {
return Promise.reject(error);
}
);
// Response interceptor
apiClient.interceptors.response.use(
response => {
return response;
},
async error => {
const originalRequest = error.config;
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
await refreshToken();
return apiClient(originalRequest);
} catch (refreshError) {
TokenManager.removeToken();
window.location.href = '/login';
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
🧪 Testing Authentication
Test Token Validity
async function testAuthentication() {
const token = TokenManager.getToken();
if (!token) {
console.log('❌ No token found');
return false;
}
try {
const response = await fetch('/api/auth/verify', {
headers: {
'Authorization': `Bearer ${token}`
}
});
if (response.ok) {
console.log('✅ Token is valid');
return true;
} else {
console.log('❌ Token is invalid');
return false;
}
} catch (error) {
console.log('❌ Verification failed:', error.message);
return false;
}
}
Complete Authentication Flow
// Complete authentication flow example
async function authenticationFlow() {
try {
// 1. Check existing token
if (TokenManager.isTokenValid()) {
console.log('✅ Using existing token');
return TokenManager.getToken();
}
// 2. Try to refresh token
try {
const newToken = await refreshToken();
console.log('✅ Token refreshed successfully');
return newToken;
} catch (refreshError) {
console.log('⚠️ Token refresh failed, need to re-login');
}
// 3. Re-login
const email = prompt('Enter email:');
const password = prompt('Enter password:');
const token = await login(email, password);
console.log('✅ Login successful');
return token;
} catch (error) {
console.error('❌ Authentication failed:', error.message);
throw error;
}
}
📋 FAQ
Q: What to do when token expires?
A: The system will automatically try to refresh the token. If refresh fails, you need to re-login.
Q: How to check if token is valid?
A: You can call the /api/auth/verify
endpoint to verify token validity.
Q: What to do if token is lost?
A: You need to re-login to get a new token, or regenerate one in the admin dashboard.
Q: Can I use multiple tokens simultaneously?
A: Yes, but it's recommended to use different tokens for different applications or environments.