Documentation Index
Fetch the complete documentation index at: https://docs.aihubmix.com/llms.txt
Use this file to discover all available pages before exploring further.
Déclaration de sécurité importante
Principe « la sécurité d’abord » : lors du développement et du déploiement d’applications tierces, la sécurité est la considération la plus importante. Vous devez suivre strictement les principes de sécurité ci-dessous pour garantir la sécurité des données utilisateurs et du processus d’autorisation.
- N’exposez jamais le
client_secret dans du code JavaScript frontend
- L’échange entre code d’autorisation OAuth et token doit être géré côté serveur
- Tout accès aux ressources utilisateurs protégées doit passer par un proxy d’API backend
- Toutes les communications OAuth doivent être protégées par HTTPS
Toute violation des principes de sécurité ci-dessus peut entraîner de graves vulnérabilités de sécurité !
📋 Table des matières
- Vue d’ensemble
- Démarrage
- Flux d’autorisation OAuth2
- Référence de l’API
- SDK et exemples de code
- Bonnes pratiques de sécurité
- FAQ
- Support technique
Vue d’ensemble
Nous fournissons une API ouverte basée sur le standard OAuth2, permettant aux applications tierces d’accéder en toute sécurité aux informations de base et au solde du compte des utilisateurs. Grâce à notre service OAuth2, votre application peut :
- 🚀 Connexion en un clic : les utilisateurs n’ont pas besoin de s’inscrire à nouveau, la connexion accorde automatiquement l’autorisation pour une expérience véritablement fluide
- 👤 Obtenir des informations utilisateur : accéder au profil de base de l’utilisateur (nom d’utilisateur, e-mail, etc.)
- 💰 Consulter le solde du compte : obtenir en temps réel le solde du compte de l’utilisateur
- 🔄 Redirection vers le rechargement : guider les utilisateurs vers notre page de rechargement pour réapprovisionner le compte
- 🔐 Rafraîchissement automatique des tokens : mécanisme intégré de refresh token pour un renouvellement de token transparent, améliorant l’expérience utilisateur
Démarrage
1. Enregistrer un compte développeur
Vous devez d’abord enregistrer un compte développeur dans notre système.
2. Créer une application OAuth
Créez votre application OAuth dans la console développeur :
curl -X POST https://api.aihubmix.com/api/oauth_apps \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_DEVELOPER_TOKEN" \
-d '{
"name": "My Third-party App",
"description": "App description",
"redirect_uri": "https://yourapp.com/oauth/callback"
}'
Exemple de réponse :
{
"success": true,
"message": "Application created successfully",
"data": {
"id": 1,
"name": "My Third-party App",
"client_id": "client_abc123def456...",
"client_secret": "secret_xyz789uvw012...",
"redirect_uri": "https://yourapp.com/oauth/callback",
"created_time": 1640995200
}
}
Rappel de sécurité important :
- Le
client_id peut être utilisé côté frontend (information publique)
- Le
client_secret ne peut être utilisé que côté serveur et ne doit jamais être exposé au navigateur
- Stockez le
client_secret dans des variables d’environnement ; ne le codez pas en dur dans votre code
Assurez-vous que votre URI de redirection répond aux exigences suivantes :
- Utilise le protocole HTTPS (en production)
- Pointe vers un endpoint de votre serveur (et non vers une page frontend)
- Le domaine est enregistré et accessible
- Le chemin est spécifique à l’endpoint API qui traite le callback
Flux d’autorisation OAuth2
Diagramme du flux sécurisé
Instructions pas à pas
Étape 1 : Guider l’utilisateur vers l’autorisation
Ajoutez un bouton de connexion sur votre page frontend. Lorsqu’il est cliqué, redirigez vers votre endpoint d’autorisation côté serveur :
Frontend code - only responsible for redirecting
function startLogin() {
// Redirect to your server-side authorization handler
window.location.href = '/auth/oauth/start';
}
Étape 2 : Gestionnaire d’autorisation côté serveur
Implémentez le gestionnaire d’autorisation sur votre serveur :
app.get('/auth/oauth/start', (req, res) => {
// Generate and store state parameter
const state = generateSecureRandomString();
req.session.oauth_state = state;
// Build authorization URL
const authUrl = new URL('https://your-domain.com/api/oauth2/authorize');
authUrl.searchParams.append('client_id', process.env.OAUTH_CLIENT_ID);
authUrl.searchParams.append('redirect_uri', process.env.OAUTH_REDIRECT_URI);
authUrl.searchParams.append('response_type', 'code');
authUrl.searchParams.append('scope', 'profile balance');
authUrl.searchParams.append('state', state);
authUrl.searchParams.append('auto_authorize', 'true'); // One-click login
// Redirect to authorization server
res.redirect(authUrl.toString());
});
Étape 3 : Gérer le callback d’autorisation (côté serveur)
Server-side authorization callback handler
app.get('/oauth/callback', async (req, res) => {
const { code, state, error } = req.query;
// Error handling
if (error) {
return res.redirect(`/?error=${encodeURIComponent(error)}`);
}
// Parameter validation
if (!code || !state) {
return res.redirect('/?error=missing_parameters');
}
// Validate state parameter (prevent CSRF attacks)
if (state !== req.session.oauth_state) {
return res.redirect('/?error=invalid_state');
}
try {
// Exchange authorization code for access token (server-side)
const tokenResponse = await fetch('https://your-domain.com/api/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
redirect_uri: process.env.OAUTH_REDIRECT_URI,
client_id: process.env.OAUTH_CLIENT_ID,
client_secret: process.env.OAUTH_CLIENT_SECRET // Server-side only
})
});
const tokenData = await tokenResponse.json();
if (!tokenResponse.ok) {
throw new Error(tokenData.error || 'Token exchange failed');
}
// Securely store token (server session or database)
req.session.access_token = tokenData.access_token;
req.session.refresh_token = tokenData.refresh_token;
req.session.token_expires_at = Date.now() + (tokenData.expires_in * 1000);
// Clean up temporary state
delete req.session.oauth_state;
// Redirect to frontend page
res.redirect('/?login=success');
} catch (error) {
console.error('OAuth callback error:', error);
res.redirect(`/?error=server_error`);
}
});
Frontend fetches user info via API proxy
async function loadUserInfo() {
try {
const response = await fetch('/api/user/info');
if (!response.ok) {
throw new Error('Failed to fetch user info');
}
const userInfo = await response.json();
displayUserInfo(userInfo);
} catch (error) {
console.error('Failed to load user info:', error);
showLoginButton();
}
}
app.get('/api/user/info', async (req, res) => {
const accessToken = req.session.access_token;
if (!accessToken) {
return res.status(401).json({ error: 'Not authenticated' });
}
try {
// Proxy request to OAuth server
const response = await fetch('https://your-domain.com/api/oauth2/userinfo', {
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
if (!response.ok) {
throw new Error('User info request failed');
}
const userInfo = await response.json();
res.json(userInfo);
} catch (error) {
console.error('User info proxy error:', error);
res.status(500).json({ error: 'Server error' });
}
});
Référence de l’API
1. Endpoint d’autorisation
GET /api/oauth2/authorize
Guide l’utilisateur à travers l’autorisation OAuth2.
Paramètres :
| Paramètre | Type | Requis | Description |
|---|
client_id | string | Oui | ID client de l’application (utilisable côté frontend) |
redirect_uri | string | Oui | URI de callback après autorisation (doit pointer vers un endpoint serveur) |
response_type | string | Oui | Fixe : code |
scope | string | Non | Portée, séparée par des espaces |
state | string | Oui | Chaîne aléatoire pour prévenir les attaques CSRF (générée côté serveur) |
auto_authorize | string | Non | Définir à true pour activer l’auto-autorisation |
Exigences de sécurité :
redirect_uri doit correspondre exactement à l’adresse enregistrée
state doit être une chaîne aléatoire générée côté serveur
- HTTPS doit être utilisé (en production)
Explication des scopes :
profile : accéder aux informations de base de l’utilisateur (nom d’utilisateur, e-mail)
balance : accéder au solde du compte de l’utilisateur
2. Endpoint Token
POST /api/oauth2/token
Avertissement de sécurité : cet endpoint ne doit être appelé que depuis le côté serveur, jamais depuis le frontend !
Utilisé dans deux scénarios :
- Échanger un code d’autorisation contre un access token
- Utiliser un refresh token pour obtenir un nouvel access token
Paramètres pour la concession « authorization code » :
| Paramètre | Type | Requis | Description |
|---|
grant_type | string | Oui | Fixe : authorization_code |
code | string | Oui | Code d’autorisation |
redirect_uri | string | Oui | Doit correspondre à l’URI utilisée pour l’autorisation |
client_id | string | Oui | ID client de l’application |
client_secret | string | Oui | Secret client de l’application (côté serveur uniquement) |
Paramètres pour la concession « refresh token » :
| Paramètre | Type | Requis | Description |
|---|
grant_type | string | Oui | Fixe : refresh_token |
refresh_token | string | Oui | Refresh token |
client_id | string | Oui | ID client de l’application |
client_secret | string | Oui | Secret client de l’application (côté serveur uniquement) |
Exemple de réponse :
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "refresh_abc123def456...",
"scope": "profile balance"
}
GET /api/oauth2/userinfo
Obtenir les informations de base de l’utilisateur et le solde du compte.
En-tête de requête :
Authorization: Bearer {access_token}
Exemple de réponse :
{
"id": 12345,
"username": "user123",
"email": "user@example.com",
"quota": 1000000,
"used_quota": 250000,
"balance_formatted": "750.00",
"created_time": 1640995200,
"status": 1
}
SDK et exemples de code
SDK JavaScript
Nous fournissons un SDK JavaScript complet que vous pouvez utiliser directement :
<!DOCTYPE html>
<html>
<head>
<title>Third-party App Example</title>
<style>
.container { max-width: 800px; margin: 0 auto; padding: 20px; }
.user-info { background: #f5f5f5; padding: 20px; border-radius: 8px; margin: 20px 0; }
.login-section { text-align: center; padding: 40px; }
.btn { padding: 12px 24px; border: none; border-radius: 6px; cursor: pointer; font-size: 16px; }
.btn-primary { background: #007bff; color: white; }
.btn-success { background: #28a745; color: white; }
.btn-secondary { background: #6c757d; color: white; }
.hidden { display: none; }
</style>
</head>
<body>
<div class="container">
<h1>我的第三方应用</h1>
<!-- Loading status -->
<div id="loading">
<p>Checking login status...</p>
</div>
<!-- Logged-in user info -->
<div id="user-info" class="user-info hidden">
<h2>Welcome back!</h2>
<p><strong>Username:</strong> <span id="username"></span></p>
<p><strong>Email:</strong> <span id="email"></span></p>
<p><strong>Account Balance:</strong> <span id="balance"></span></p>
<div style="margin-top: 20px;">
<button class="btn btn-success" onclick="refreshBalance()">Refresh Balance</button>
<button class="btn btn-primary" onclick="goToTopup()">Top Up Account</button>
<button class="btn btn-secondary" onclick="logout()">Log Out</button>
</div>
</div>
<!-- Not logged in status -->
<div id="login-section" class="login-section hidden">
<h2>Please log in to view account info</h2>
<p>Use one-click login for quick access to your account</p>
<button class="btn btn-primary" onclick="oneClickLogin()">
🚀 One-click Login
</button>
</div>
</div>
<script>
// OAuth configuration
const OAUTH_CONFIG = {
authServer: 'https://your-domain.com',
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET', // 生产环境应该在后端处理
redirectUri: window.location.origin + '/oauth/callback.html',
scope: 'profile balance'
};
class OAuthManager {
constructor() {
this.accessToken = localStorage.getItem('oauth_access_token');
this.refreshToken = localStorage.getItem('oauth_refresh_token');
this.tokenExpiresAt = localStorage.getItem('oauth_token_expires_at');
this.isRefreshing = false; // 防止并发刷新
this.init();
}
async init() {
// 检查URL中是否有授权码
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
if (code) {
await this.handleAuthCallback(code, state);
// 清理URL
window.history.replaceState({}, document.title, window.location.pathname);
} else if (this.accessToken) {
try {
// 检查token是否过期,如果过期尝试刷新
if (this.isTokenExpired()) {
await this.refreshTokenIfNeeded();
}
await this.fetchUserInfo();
this.showUserInfo();
} catch (error) {
console.log('Token可能已过期或无效,需要重新登录');
this.clearTokens();
this.showLoginSection();
}
} else {
this.showLoginSection();
}
document.getElementById('loading').classList.add('hidden');
}
// Check if access token is expired
isTokenExpired() {
if (!this.tokenExpiresAt) return false;
const expiryTime = parseInt(this.tokenExpiresAt);
const bufferTime = 5 * 60 * 1000; // 5 minutes buffer
return Date.now() > (expiryTime - bufferTime);
}
// Automatically refresh token
async refreshTokenIfNeeded() {
if (!this.refreshToken || this.isRefreshing) {
return false;
}
this.isRefreshing = true;
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: this.refreshToken,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
})
});
if (response.ok) {
const tokenData = await response.json();
this.updateTokens(tokenData);
return true;
} else {
throw new Error('Token refresh failed');
}
} catch (error) {
console.error('Failed to refresh token:', error);
this.clearTokens();
return false;
} finally {
this.isRefreshing = false;
}
}
// Update token info
updateTokens(tokenData) {
this.accessToken = tokenData.access_token;
this.refreshToken = tokenData.refresh_token;
this.tokenExpiresAt = Date.now() + (tokenData.expires_in * 1000);
localStorage.setItem('oauth_access_token', this.accessToken);
localStorage.setItem('oauth_refresh_token', this.refreshToken);
localStorage.setItem('oauth_token_expires_at', this.tokenExpiresAt.toString());
}
oneClickLogin() {
const state = this.generateState();
localStorage.setItem('oauth_state', state);
const authUrl = `${OAUTH_CONFIG.authServer}/api/oauth2/authorize?` +
`client_id=${OAUTH_CONFIG.clientId}&` +
`redirect_uri=${encodeURIComponent(OAUTH_CONFIG.redirectUri)}&` +
`response_type=code&` +
`scope=${encodeURIComponent(OAUTH_CONFIG.scope)}&` +
`state=${state}&` +
`auto_authorize=true`; // Enable auto-authorization for true one-click login
// Open authorization page in popup
const popup = window.open(authUrl, 'oauth_login', 'width=500,height=600,scrollbars=yes');
// Listen for popup close
const checkClosed = setInterval(() => {
if (popup.closed) {
clearInterval(checkClosed);
// 检查是否获得了授权
setTimeout(() => this.init(), 1000);
}
}, 1000);
}
async handleAuthCallback(code, state) {
const savedState = localStorage.getItem('oauth_state');
if (state !== savedState) {
console.error('State parameter mismatch');
return;
}
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
redirect_uri: OAUTH_CONFIG.redirectUri
})
});
const tokenData = await response.json();
if (tokenData.access_token) {
this.updateTokens(tokenData);
localStorage.removeItem('oauth_state');
await this.fetchUserInfo();
this.showUserInfo();
}
} catch (error) {
console.error('获取访问令牌失败:', error);
}
}
// API request method with auto-refresh
async apiRequest(url, options = {}) {
// Check and refresh token if needed
if (this.isTokenExpired()) {
const refreshed = await this.refreshTokenIfNeeded();
if (!refreshed) {
throw new Error('Unable to refresh token');
}
}
const headers = {
'Authorization': `Bearer ${this.accessToken}`,
...options.headers
};
const response = await fetch(url, {
...options,
headers
});
// If a 401 error is received, try to refresh token and retry once
if (response.status === 401 && !options._retry) {
const refreshed = await this.refreshTokenIfNeeded();
if (refreshed) {
return this.apiRequest(url, { ...options, _retry: true });
}
}
return response;
}
async fetchUserInfo() {
const response = await this.apiRequest(`${OAUTH_CONFIG.authServer}/api/oauth2/userinfo`);
if (!response.ok) {
throw new Error('Failed to get user info');
}
this.userInfo = await response.json();
}
showUserInfo() {
document.getElementById('username').textContent = this.userInfo.username;
document.getElementById('email').textContent = this.userInfo.email;
document.getElementById('balance').textContent = this.userInfo.balance_formatted;
document.getElementById('user-info').classList.remove('hidden');
document.getElementById('login-section').classList.add('hidden');
}
showLoginSection() {
document.getElementById('user-info').classList.add('hidden');
document.getElementById('login-section').classList.remove('hidden');
}
async refreshBalance() {
try {
await this.fetchUserInfo();
document.getElementById('balance').textContent = this.userInfo.balance_formatted;
alert('Balance updated');
} catch (error) {
alert('Refresh failed, please log in again');
this.clearTokens();
this.showLoginSection();
}
}
async goToTopup() {
try {
const response = await this.apiRequest(`${OAUTH_CONFIG.authServer}/api/oauth2/topup`);
const data = await response.json();
if (data.topup_url) {
window.open(data.topup_url, '_blank');
}
} catch (error) {
console.error('Failed to get top-up link:', error);
}
}
logout() {
this.clearTokens();
this.showLoginSection();
}
clearTokens() {
this.accessToken = null;
this.refreshToken = null;
this.tokenExpiresAt = null;
this.userInfo = null;
localStorage.removeItem('oauth_access_token');
localStorage.removeItem('oauth_refresh_token');
localStorage.removeItem('oauth_token_expires_at');
}
generateState() {
return Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
}
}
// 全局函数
let oauthManager;
function oneClickLogin() {
oauthManager.oneClickLogin();
}
function refreshBalance() {
oauthManager.refreshBalance();
}
function goToTopup() {
oauthManager.goToTopup();
}
function logout() {
oauthManager.logout();
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
oauthManager = new OAuthManager();
});
</script>
</body>
</html>
Page de callback OAuth
Créez un fichier /oauth/callback.html :
<!DOCTYPE html>
<html>
<head>
<title>Logging in...</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; padding: 50px; }
.loading { color: #666; }
.error { color: #dc3545; }
</style>
</head>
<body>
<h2>Logging in, please wait...</h2>
<div id="status" class="loading">Verifying authorization information...</div>
<script>
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
const error = urlParams.get('error');
if (error) {
document.getElementById('status').innerHTML =
`<div class="error">Authorization failed: ${error}</div>`;
setTimeout(() => {
if (window.opener) {
window.close();
} else {
window.location.href = '/';
}
}, 3000);
} else if (code) {
if (window.opener) {
// 如果是弹窗,关闭并让父窗口处理
window.opener.location.href =
window.opener.location.pathname + `?code=${code}&state=${state}`;
window.close();
} else {
// 如果不是弹窗,重定向到主页面
window.location.href = `/?code=${code}&state=${state}`;
}
} else {
document.getElementById('status').innerHTML =
'<div class="error">No valid authorization information received</div>';
setTimeout(() => {
window.location.href = '/';
}, 3000);
}
</script>
</body>
</html>
Exemple backend Node.js
Pour une meilleure sécurité, il est recommandé de gérer le client_secret côté backend :
const express = require('express');
const cors = require('cors');
const fetch = require('node-fetch');
const app = express();
app.use(cors());
app.use(express.json());
const OAUTH_CONFIG = {
authServer: 'https://your-domain.com',
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET'
};
// Backend handles token exchange
app.post('/api/oauth/exchange-token', async (req, res) => {
const { code, redirectUri, state } = req.body;
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
redirect_uri: redirectUri
})
});
const tokenData = await response.json();
if (response.ok) {
res.json(tokenData);
} else {
res.status(400).json(tokenData);
}
} catch (error) {
res.status(500).json({ error: 'Token exchange failed' });
}
});
// Refresh token endpoint
app.post('/api/oauth/refresh-token', async (req, res) => {
const { refreshToken } = req.body;
if (!refreshToken) {
return res.status(400).json({ error: 'Missing refresh token' });
}
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: OAUTH_CONFIG.clientId,
client_secret: OAUTH_CONFIG.clientSecret,
})
});
const tokenData = await response.json();
if (response.ok) {
res.json(tokenData);
} else {
res.status(400).json(tokenData);
}
} catch (error) {
res.status(500).json({ error: 'Token refresh failed' });
}
});
// Proxy user info request (with auto-refresh)
app.get('/api/oauth/userinfo', async (req, res) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).json({ error: 'Missing authorization header' });
}
try {
const response = await fetch(`${OAUTH_CONFIG.authServer}/api/oauth2/userinfo`, {
headers: {
'Authorization': authHeader
}
});
const userData = await response.json();
if (response.ok) {
res.json(userData);
} else {
res.status(response.status).json(userData);
}
} catch (error) {
res.status(500).json({ error: 'Failed to fetch user info' });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Bonnes pratiques de sécurité
1. Protection du Client Secret
- ✅ Recommandé : stocker le
client_secret sur le serveur backend
- ❌ À éviter : exposer le
client_secret dans du JavaScript frontend
2. Validation du paramètre State
// Generate random state
const state = crypto.randomBytes(16).toString('hex');
localStorage.setItem('oauth_state', state);
// Validate state
const savedState = localStorage.getItem('oauth_state');
if (receivedState !== savedState) {
throw new Error('CSRF attack detected');
}
3. Utilisation de HTTPS
- Doit utiliser
HTTPS en production
- L’URI de callback doit utiliser
HTTPS
- Toutes les requêtes API utilisent
HTTPS
4. Stockage sécurisé des tokens
// Set token expiry time
const expiryTime = Date.now() + (tokenData.expires_in * 1000);
localStorage.setItem('oauth_token_expiry', expiryTime);
// Check if token is expired
function isTokenExpired() {
const expiry = localStorage.getItem('oauth_token_expiry');
return !expiry || Date.now() > parseInt(expiry);
}
5. Gestion des erreurs
try {
const response = await fetch('/api/oauth2/userinfo', {
headers: { 'Authorization': `Bearer ${token}` }
});
if (!response.ok) {
if (response.status === 401) {
// Token expired, need to re-login
clearToken();
showLoginSection();
} else {
throw new Error(`HTTP ${response.status}`);
}
}
const userInfo = await response.json();
return userInfo;
} catch (error) {
console.error('API request failed:', error);
// Handle network errors etc.
}
FAQ
R : Il suffit d’ajouter le paramètre auto_authorize=true à l’URL d’autorisation. Après la connexion de l’utilisateur, l’autorisation sera accordée automatiquement, sans étape de confirmation supplémentaire :
const authUrl = 'https://your-domain.com/api/oauth2/authorize?' +
'client_id=YOUR_CLIENT_ID&' +
'auto_authorize=true&' + // Key parameter
'...other parameters';
Q2 : Les tokens se rafraîchissent-ils automatiquement ?
R : Oui, notre SDK intègre le rafraîchissement automatique des tokens :
- Access token : valide 2 heures, rafraîchissement automatique 5 minutes avant expiration
- Refresh token : valide 30 jours, utilisé pour obtenir de nouveaux access tokens
- Rafraîchissement transparent : tous les appels API vérifient et rafraîchissent automatiquement les tokens expirés
- Nouvelle tentative en cas d’échec : si l’API renvoie une erreur 401, le SDK tentera automatiquement de rafraîchir le token et de réessayer
// The SDK will handle token refresh automatically, no manual handling needed
const userInfo = await oauthManager.fetchUserInfo(); // token auto-refresh
Ce n’est que si le refresh token expire également que l’utilisateur devra se reconnecter.
R : Selon le scope autorisé, vous pouvez obtenir :
- Scope
profile : nom d’utilisateur, e-mail
- Scope
balance : informations sur le solde du compte
R :
- Utilisez
HTTP localhost en développement pour les tests
- Utilisez nos outils de test fournis pour vérifier le flux d’autorisation
- Vérifiez les requêtes réseau dans les outils de développement du navigateur
Q5 : Quels langages de programmation sont pris en charge ?
R : Notre API OAuth2 est standard et prend en charge tous les principaux langages de programmation :
- JavaScript/Node.js
- Python
- PHP
- Java
- C#/.NET
- Go
- Ruby
R : Les utilisateurs peuvent révoquer l’autorisation d’une application tierce dans la page Centre utilisateur > Gestion des autorisations.
Dernière mise à jour : 2026-06-01