跳至主要內容

Google

@mastra/auth-google 套件使用 Google Workspace 為 Mastra 提供驗證與角色型存取控制。它支援採用加密 session cookie 的 OAuth 2.0 / OIDC 登入流程、驗證 Google ID token,並將 Google Workspace 群組對應至 Mastra 權限。

當 Studio 使用者透過 Google 登入,且存取權應限制於一或多個 Google Workspace domain 時,請使用此套件。

事前準備
「事前準備」的直接連結

本指南使用 Google Workspace 驗證。請務必完成下列事項:

  1. 建立或選取 Google Cloud 專案
  2. 為網頁應用程式設定 OAuth client
  3. 將 Mastra SSO callback URL 加入已授權的 redirect URI
  4. 如果計畫使用 RBAC,請設定 Google Workspace 群組

若要使用 Google Groups RBAC,還必須設定具備全網域委派的 Google Workspace service account,並授予 Directory API 唯讀群組 scope:

https://www.googleapis.com/auth/admin.directory.group.readonly

請確認環境變數已設定。

.env
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=http://localhost:4111/api/auth/sso/callback
GOOGLE_COOKIE_PASSWORD=a-random-string-at-least-32-characters-long
GOOGLE_ALLOWED_DOMAINS=example.com

GOOGLE_SERVICE_ACCOUNT_EMAIL=service-account@project.iam.gserviceaccount.com
GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
GOOGLE_WORKSPACE_ADMIN_EMAIL=admin@example.com
備註

GOOGLE_COOKIE_PASSWORD 用於加密 session cookie。若省略,系統會使用無法在伺服器重新啟動後沿用的自動產生值。請在正式環境中明確設定此值。

MastraAuthGoogle 會自動讀取 GOOGLE_* 驗證變數。上方顯示的 service account 變數則由你傳給 MastraRBACGoogle 的設定程式碼讀取。

安裝
「安裝」的直接連結

使用 MastraAuthGoogle 類別前,請先安裝 @mastra/auth-google 套件。

npm install @mastra/auth-google

使用範例
「使用範例」的直接連結

搭配環境變數的基本用法
「搭配環境變數的基本用法」的直接連結

設定上述環境變數後,所有 constructor 參數皆為選填:

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { MastraAuthGoogle } from '@mastra/auth-google'

export const mastra = new Mastra({
server: {
auth: new MastraAuthGoogle(),
},
})
警告

使用 allowedDomainsGOOGLE_ALLOWED_DOMAINS 強制執行 Workspace 存取限制。Mastra 會檢查 Google 已驗證的 hd claim,而非電子郵件地址的後綴。

自訂設定
「自訂設定」的直接連結

若不想依賴環境變數,請直接傳入 constructor 選項:

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { MastraAuthGoogle } from '@mastra/auth-google'

export const mastra = new Mastra({
server: {
auth: new MastraAuthGoogle({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
redirectUri: process.env.GOOGLE_REDIRECT_URI,
allowedDomains: ['example.com'],
}),
},
})

搭配 Google Groups RBAC 的驗證
「搭配 Google Groups RBAC 的驗證」的直接連結

加入 MastraRBACGoogle,將 Google Workspace 群組對應至 Mastra 權限:

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { MastraAuthGoogle, MastraRBACGoogle } from '@mastra/auth-google'

export const mastra = new Mastra({
server: {
auth: new MastraAuthGoogle(),
rbac: new MastraRBACGoogle({
serviceAccount: {
clientEmail: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL!,
privateKey: process.env.GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY!,
subject: process.env.GOOGLE_WORKSPACE_ADMIN_EMAIL!,
},
roleMapping: {
'admins@example.com': ['*'],
'engineering@example.com': ['agents:*', 'workflows:*', 'tools:*'],
'viewers@example.com': ['agents:read', 'workflows:read'],
_default: [], // users with unmapped groups get no permissions
},
}),
},
})

跨 Provider 使用
「跨 Provider 使用」的直接連結

使用不同的 auth Provider(Auth0、Clerk 等)登入,並以 Google Workspace 群組進行 RBAC。請傳入 getUserKey 函式,從其他 Provider 的使用者物件解析 Google Directory API 使用者 key:

src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { MastraAuthAuth0 } from '@mastra/auth-auth0'
import { MastraRBACGoogle } from '@mastra/auth-google'

export const mastra = new Mastra({
server: {
auth: new MastraAuthAuth0(),
rbac: new MastraRBACGoogle({
getUserKey: user => {
if (!user || typeof user !== 'object') return undefined

const { email } = user as { email?: unknown }
return typeof email === 'string' ? email : undefined
},
serviceAccount: {
clientEmail: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL!,
privateKey: process.env.GOOGLE_SERVICE_ACCOUNT_PRIVATE_KEY!,
subject: process.env.GOOGLE_WORKSPACE_ADMIN_EMAIL!,
},
roleMapping: {
'engineering@example.com': ['agents:*', 'workflows:*'],
'admins@example.com': ['*'],
_default: [],
},
}),
},
})

請參閱 MastraAuthGoogle,瞭解所有可用的設定選項。

角色對應
「角色對應」的直接連結

roleMapping 選項會將 Google Workspace 群組電子郵件地址對應至 Mastra 權限字串陣列。權限採用 resource:action 模式,並支援萬用字元:

const rbac = new MastraRBACGoogle({
roleMapping: {
// full access to everything
'admins@example.com': ['*'],

// full access to agents and workflows
'engineering@example.com': ['agents:*', 'workflows:*'],

// read-only access
'viewers@example.com': ['agents:read', 'workflows:read'],

// users whose groups don't match any key above
_default: [],
},
})

群組電子郵件地址預設用作角色 ID。如果想依群組名稱或其他屬性進行對應,請使用 mapGroupToRoles_default key 會將權限指派給 Google Workspace 群組與其他 key 皆不相符的使用者。

用戶端設定
「用戶端設定」的直接連結

啟用驗證後,對 Mastra route 的請求需要通過驗證。使用 GOOGLE_CLIENT_SECRET 啟用 SSO 時,MastraAuthGoogle 會使用 Google 登入,並在登入後設定加密的 session cookie。

針對跨 origin 請求(例如在 :3000 的前端呼叫 :4111 的 Mastra),請在 Mastra 伺服器上啟用 CORS credential:

src/mastra/index.ts
export const mastra = new Mastra({
server: {
auth: new MastraAuthGoogle(),
cors: {
origin: 'http://localhost:3000',
credentials: true,
},
},
})

設定用戶端,使其包含 credential:

lib/mastra-client.ts
import { MastraClient } from '@mastra/client-js'

export const mastraClient = new MastraClient({
baseUrl: 'http://localhost:4111',
credentials: 'include',
})

Bearer token
「Bearer token」的直接連結

你也可以將 Google ID token 當作 Bearer token 傳入。Mastra 會根據 Google 的 JSON Web Key Set(JWKS)endpoint 驗證該 token:

lib/mastra-client.ts
import { MastraClient } from '@mastra/client-js'

export const createMastraClient = (idToken: string) => {
return new MastraClient({
baseUrl: 'http://localhost:4111',
headers: {
Authorization: `Bearer ${idToken}`,
},
})
}

如需更多設定選項,請參閱 Mastra Client SDK

發出已驗證的請求
「發出已驗證的請求」的直接連結

src/api/agents.ts
import { mastraClient } from '../lib/mastra-client'

const agent = mastraClient.getAgent('weatherAgent')
const response = await agent.generate('Weather in London')
console.log(response)

疑難排解
「疑難排解」的直接連結

  • 登入後出現 401:檢查 GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRETGOOGLE_REDIRECT_URI 是否與 Google Cloud OAuth client 相符。
  • Workspace 使用者遭拒:確認 GOOGLE_ALLOWED_DOMAINS 與 Google ID token 的 hd claim 相符。
  • 一般 Gmail 帳號遭拒:設定 allowedDomains 時,這是預期行為,因為 Gmail 帳號沒有 Workspace hd claim。
  • RBAC 傳回預設權限:未解析出使用者的任何角色。請確認使用者電子郵件或自訂 getUserKey、Google 群組 membership 與 roleMapping。如果 Directory API 查詢失敗,Provider 會擲回錯誤,而非傳回 _default
  • Cookie 未跨 origin 傳送:在 MastraClient 中設定 credentials: "include",並以你的前端 origin 和 credentials: true 設定 server.cors
  • 重新啟動後 session 遺失:將 GOOGLE_COOKIE_PASSWORD 設為至少 32 個字元的穩定值。若未設定,開發環境會使用自動產生的 key,且每次重新啟動時都會變更。