You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Clerk实现Google SSO认证时,获取已登录用户的Google Access Token以调用Calendar API创建Meet会议的方法

Clerk实现Google SSO认证时,获取已登录用户的Google Access Token以调用Calendar API创建Meet会议的方法

我之前在做Next.js + Clerk的项目时也碰到过一模一样的问题——明明已经配置了Google Calendar的额外权限,用户也授权了,但就是在Clerk返回的用户对象里找不到Google的Access Token。其实Clerk确实不会把第三方OAuth的令牌默认暴露在用户对象里,但有两种靠谱的方式可以拿到它:


方式一:前端直接通过Clerk客户端钩子获取(适合临时调用API)

Clerk的客户端SDK提供了专门的方法来获取第三方OAuth提供商的访问令牌,不需要绕后端。你可以在组件里用useUser钩子,然后调用user.getOAuthAccessToken('oauth_google')方法:

import { useUser } from '@clerk/nextjs';

export default function CreateMeetEventButton() {
  const { user } = useUser();

  const handleCreateMeet = async () => {
    if (!user) {
      alert('请先登录');
      return;
    }

    try {
      // 直接获取Google的Access Token
      const googleAccessToken = await user.getOAuthAccessToken('oauth_google');
      
      // 拿到Token后就可以调用Google Calendar API创建Meet会议了
      const response = await fetch('https://www.googleapis.com/calendar/v3/calendars/primary/events', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${googleAccessToken}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          summary: '团队同步会议',
          start: { dateTime: '2024-05-20T10:00:00+08:00' },
          end: { dateTime: '2024-05-20T11:00:00+08:00' },
          conferenceData: {
            createRequest: {
              requestId: 'random-unique-id-123',
              conferenceSolutionKey: { type: 'hangoutsMeet' }
            }
          }
        })
      });

      if (response.ok) {
        alert('Meet会议创建成功!');
      } else {
        console.error('创建会议失败:', await response.json());
      }
    } catch (error) {
      // 如果用户没授权Calendar权限,会抛出错误,这里可以引导用户重新授权
      console.error('获取Token失败:', error);
      alert('请先授权Google Calendar权限,可前往账户设置页面重新授权');
    }
  };

  return (
    <button onClick={handleCreateMeet} disabled={!user}>
      创建Google Meet会议
    </button>
  );
}

这个方法的好处是简单直接,适合前端临时调用API的场景,但要注意:Access Token有过期时间(Google一般是1小时),过期后调用这个方法会自动刷新(Clerk会帮你处理刷新逻辑),前提是用户已经授权了离线访问权限(如果需要长期使用的话)。


方式二:通过Clerk Webhooks持久化Token到用户元数据(适合后端长期使用)

如果你的业务需要在后端长期使用这个Token,或者要把Token存下来做后续处理,就可以用Clerk的Webhooks来捕获OAuth连接的事件,把Token存到用户的元数据里:

  1. 配置Clerk Webhook:
    登录Clerk Dashboard,找到「Webhooks」页面,添加一个新的Webhook,选择触发事件为oauth_connection.created和oauth_connection.updated,然后填写你的后端接收地址(比如/api/clerk-webhook),同时复制Webhook的密钥(后面验证签名要用)。

  2. 后端处理Webhook请求:
    后端接收到Clerk的Webhook后,先验证签名(防止伪造请求),然后提取Access Token,存到用户的私有元数据里(私有元数据只有后端能访问,更安全):

// pages/api/clerk-webhook.js
import { Clerk } from '@clerk/clerk-sdk-node';

const clerk = Clerk(process.env.CLERK_SECRET_KEY);

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).send('只接受POST请求');
  }

  // 验证Webhook签名,这一步必须做!
  try {
    const isValid = await clerk.verifyWebhookSignature({
      secret: process.env.CLERK_WEBHOOK_SECRET,
      signature: req.headers['clerk-webhook-signature'],
      body: JSON.stringify(req.body),
    });

    if (!isValid) {
      return res.status(401).send('无效的Webhook签名');
    }
  } catch (error) {
    console.error('签名验证失败:', error);
    return res.status(401).send('签名验证失败');
  }

  const payload = req.body;

  // 处理OAuth连接创建或更新的事件
  if (['oauth_connection.created', 'oauth_connection.updated'].includes(payload.type)) {
    const userId = payload.data.user_id;
    const googleAccessToken = payload.data.oauth_access_token;
    const googleRefreshToken = payload.data.oauth_refresh_token;

    // 把Token存到用户的私有元数据里
    await clerk.users.updateUser(userId, {
      privateMetadata: {
        google_access_token: googleAccessToken,
        google_refresh_token: googleRefreshToken,
      },
    });

    console.log('Google Token已成功保存到用户元数据');
  }

  res.status(200).send('Webhook处理成功');
}

之后在后端需要用到Token的时候,就可以通过Clerk的API获取用户的私有元数据:

// 示例:后端获取用户的Google Token
const user = await clerk.users.getUser(userId);
const googleAccessToken = user.privateMetadata.google_access_token;

一些关键注意事项

  • 权限验证:如果用户还没授权Calendar的权限,getOAuthAccessToken会抛出错误,这时候可以引导用户前往Clerk的账户设置页面,重新授权Google连接并勾选Calendar权限。
  • Token过期处理:Google的Access Token有效期是1小时,Refresh Token可以用来刷新Access Token,你可以在后端用Refresh Token调用Google的API来获取新的Access Token,然后更新用户元数据里的Token。
  • 安全性:不要把Access Token暴露给前端之外的不可信环境,私有元数据是后端专属的,比公共元数据更安全。

备注:内容来源于stack exchange,提问作者James Aldridge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 14:24:38