const pool = require('../config/database'); const crypto = require('crypto'); class OAuthToken { // 生成授权码 static generateAuthCode() { return crypto.randomBytes(32).toString('hex'); } // 生成访问令牌 static generateAccessToken() { return crypto.randomBytes(64).toString('hex'); } // 生成刷新令牌 static generateRefreshToken() { return crypto.randomBytes(64).toString('hex'); } // 创建授权码 static async createAuthCode(authCodeData) { const { code, clientId, userId, redirectUri, scopes } = authCodeData; const expiresAt = new Date(Date.now() + 10 * 60 * 1000); // 10分钟过期 const query = ` INSERT INTO oauth_auth_codes (code, client_id, user_id, redirect_uri, scopes, expires_at) VALUES ($1, $2, $3, $4, $5, $6) RETURNING * `; try { const result = await pool.query(query, [code, clientId, userId, redirectUri, scopes, expiresAt]); return result.rows[0]; } catch (error) { console.error('创建授权码失败:', error); throw error; } } // 验证授权码 static async validateAuthCode(code, clientId, redirectUri) { const query = ` SELECT * FROM oauth_auth_codes WHERE code = $1 AND client_id = $2 AND redirect_uri = $3 AND expires_at > NOW() `; try { const result = await pool.query(query, [code, clientId, redirectUri]); // console.log(result.rows[0]); // console.log(code, clientId, redirectUri); // // console.log(); return result.rows[0]; } catch (error) { console.error('验证授权码失败:', error); throw error; } } // 删除授权码 static async deleteAuthCode(code) { const query = 'DELETE FROM oauth_auth_codes WHERE code = $1'; try { await pool.query(query, [code]); } catch (error) { console.error('删除授权码失败:', error); throw error; } } // 创建访问令牌 static async createAccessToken(accessTokenData) { const { token, clientId, userId, scopes } = accessTokenData; const expiresAt = new Date(Date.now() + 60 * 60 * 1000); // 1小时过期 const query = ` INSERT INTO oauth_access_tokens (token, client_id, user_id, scopes, expires_at) VALUES ($1, $2, $3, $4, $5) RETURNING * `; try { const result = await pool.query(query, [token, clientId, userId, scopes, expiresAt]); return result.rows[0]; } catch (error) { console.error('创建访问令牌失败:', error); throw error; } } // 创建刷新令牌 static async createRefreshToken(refreshTokenData) { const { token, accessTokenId, clientId, userId } = refreshTokenData; const expiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000); // 30天过期 const query = ` INSERT INTO oauth_refresh_tokens (token, access_token_id, client_id, user_id, expires_at) VALUES ($1, $2, $3, $4, $5) RETURNING * `; try { const result = await pool.query(query, [token, accessTokenId, clientId, userId, expiresAt]); return result.rows[0]; } catch (error) { console.error('创建刷新令牌失败:', error); throw error; } } // 验证访问令牌 static async validateAccessToken(token) { const query = ` SELECT oat.*, u.username, u.email FROM oauth_access_tokens oat JOIN users u ON oat.user_id = u.id WHERE oat.token = $1 AND oat.expires_at > NOW() `; try { const result = await pool.query(query, [token]); return result.rows[0]; } catch (error) { console.error('验证访问令牌失败:', error); throw error; } } // 撤销刷新令牌 static async revokeRefreshToken(token) { const query = 'UPDATE oauth_refresh_tokens SET is_revoked = true WHERE token = $1'; try { await pool.query(query, [token]); } catch (error) { console.error('撤销刷新令牌失败:', error); throw error; } } // 验证刷新令牌 static async validateRefreshToken(token, clientId) { const query = ` SELECT rt.*, at.scopes FROM oauth_refresh_tokens rt JOIN oauth_access_tokens at ON rt.access_token_id = at.id WHERE rt.token = $1 AND rt.client_id = $2 AND rt.is_revoked = false AND rt.expires_at > NOW() `; try { const result = await pool.query(query, [token, clientId]); return result.rows[0]; } catch (error) { console.error('验证刷新令牌失败:', error); return null; } } // 撤销访问令牌 static async revokeAccessToken(token) { const query = 'DELETE FROM oauth_access_tokens WHERE token = $1'; try { const result = await pool.query(query, [token]); return result.rowCount > 0; } catch (error) { console.error('撤销访问令牌失败:', error); throw error; } } // 清理过期令牌(改进版) static async cleanupExpiredTokens() { try { // 清理过期的访问令牌 await pool.query('DELETE FROM oauth_access_tokens WHERE expires_at < NOW()'); // 清理过期的刷新令牌 await pool.query('DELETE FROM oauth_refresh_tokens WHERE expires_at < NOW()'); // 清理过期的授权码 await pool.query('DELETE FROM oauth_auth_codes WHERE expires_at < NOW()'); console.log('已清理过期令牌'); } catch (error) { console.error('清理过期令牌失败:', error); throw error; } } // 获取用户的活跃令牌 static async getActiveTokensByUserId(userId) { const query = ` SELECT oat.token, oat.client_id, oat.scopes, oat.expires_at, oc.name as client_name FROM oauth_access_tokens oat JOIN oauth_clients oc ON oat.client_id = oc.client_id WHERE oat.user_id = $1 AND oat.expires_at > NOW() `; try { const result = await pool.query(query, [userId]); return result.rows; } catch (error) { console.error('获取用户活跃令牌失败:', error); throw error; } } } module.exports = OAuthToken;