如何基于access-token获取Facebook/Google用户信息并保存至MongoDB
基于Google/Facebook Access Token获取用户详情并存储到数据库的实现方案
处理Google认证流程
1. 先验证Token合法性
别直接信任前端传的token,先调用Google的token验证接口确认有效性:
async function verifyGoogleToken(accessToken) { try { const response = await fetch(`https://www.googleapis.com/oauth2/v3/tokeninfo?access_token=${accessToken}`); const data = await response.json(); // 校验token发行方是否为Google,防止伪造 if (data.iss !== 'https://accounts.google.com' && data.iss !== 'accounts.google.com') { throw new Error('无效的Token发行方'); } // 额外校验aud字段是否匹配你的Google应用客户端ID,确保token是给你家应用的 if (data.aud !== '你的Google客户端ID') { throw new Error('Token受众不匹配'); } return data; } catch (error) { throw new Error('Google Token验证失败: ' + error.message); } }
2. 获取用户详细信息
验证通过后,用这个token调用用户信息接口拿数据:
async function getGoogleUserInfo(accessToken) { const response = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', { headers: { 'Authorization': `Bearer ${accessToken}` } }); return await response.json(); }
处理Facebook认证流程
1. 验证Token合法性
调用Facebook的debug接口,需要带上你的应用ID和密钥:
async function verifyFacebookToken(accessToken, appId, appSecret) { try { const response = await fetch(`https://graph.facebook.com/debug_token?input_token=${accessToken}&access_token=${appId}|${appSecret}`); const data = await response.json(); if (!data.data || !data.data.is_valid) { throw new Error('无效的Facebook Access Token'); } // 校验应用ID是否匹配 if (data.data.app_id !== appId) { throw new Error('Token应用ID不匹配'); } return data; } catch (error) { throw new Error('Facebook Token验证失败: ' + error.message); } }
2. 获取用户详细信息
验证通过后,调用Graph API拿用户的姓名、邮箱、头像等信息:
async function getFacebookUserInfo(accessToken) { const fields = 'id,name,email,picture'; const response = await fetch(`https://graph.facebook.com/me?fields=${fields}&access_token=${accessToken}`); return await response.json(); }
存储用户信息到数据库
拿到用户数据后,先查数据库里有没有这个用户(用Google/Facebook的唯一ID做判断),有就更新,没有就新建。以Node.js + MongoDB为例:
async function saveUserToDB(userInfo, provider) { // provider传'google'或'facebook' const existingUser = await User.findOne({ [`${provider}_id`]: userInfo.id }); if (existingUser) { // 更新用户信息,比如头像、姓名这些可能变动的字段 existingUser.name = userInfo.name; existingUser.email = userInfo.email; existingUser.avatar = userInfo.picture?.data?.url || userInfo.avatar; // Facebook的picture是嵌套结构 await existingUser.save(); return existingUser; } else { // 创建新用户 const newUser = new User({ name: userInfo.name, email: userInfo.email, avatar: userInfo.picture?.data?.url || userInfo.avatar, [`${provider}_id`]: userInfo.id, provider: provider }); await newUser.save(); return newUser; } }
关键注意点
- 安全第一:绝对要先验证token合法性,不能跳过这一步,否则容易被伪造请求攻击。
- 别存敏感数据:Access Token本身别存到数据库,只用它拿用户信息,用完就丢。
- 错误处理要到位:每个步骤都加异常捕获,给前端返回清晰的错误提示,方便排查问题。
- Token过期问题:Access Token有有效期,前端要负责处理过期后的重新认证,后端不用存token,每次请求都重新验证就行。
内容的提问来源于stack exchange,提问作者John Oliver
相关产品推荐
相关产品推荐

