Auth SDK 设计方案
Microcosm Auth SDK 设计方案
版本: v2.5 (2026-02-02 更新)
目标: 让任何项目通过几行代码就能安全、高效地接入 Microcosm 认证系统和业务 API
参考标准: OAuth 2.0 / OpenID Connect / JSON:API / Auth0 SDK / Firebase Auth SDK / NextAuth.js
v2.5 更新 (2026-02-02):
- ✅ 用户来源追踪 (
source_project_id) 已实施,OAuth 登录自动记录- ✅ 开发者伴生矿已上线,项目可获得用户铸造伴生矿的 10% MCD
- ✅ DHC (Double Helix) 项目配置完成,MCD ATA 已创建
v2.4 更新 (2026-01-25): ✅ 项目注册与 MCD 白名单管理功能已实施完成 (Section 13)
0. 重大更新 (v2.0)
新增 Microcosm Open API 服务,统一对外暴露认证和业务数据 API:
| 服务 | 域名 | 用途 |
|---|---|---|
| Open API | https://api.microcosm.money | 统一 API 入口 (MCC/MCD/用户) |
| Portal | https://microcosm.money | 用户门户 + OAuth 认证 |
| Auth | https://auth.microcosm.money | OAuth 服务 (计划) |
关键变化:
- 外部项目不再需要 K8s 内部代理
- 所有业务数据通过 Open API 获取
- 统一使用 OAuth 2.0 Bearer Token 认证
1. 设计原则
| 原则 | 说明 |
|---|---|
| 零配置启动 | 只需 clientId 和 redirectUri 即可运行 |
| 类型安全 | 完整的 TypeScript 类型定义 |
| 框架无关 | 核心 SDK 不依赖任何框架,提供框架适配层 |
| 自动处理复杂性 | Token 刷新、错误重试、状态同步全自动 |
| 安全第一 | PKCE、state 验证、secure cookie 等开箱即用 |
2. SDK 架构
2.1 整体架构
外部项目 (任意云平台)
| 项目 | 云平台 |
|---|---|
| Double Helix | GCP |
| Event Horizon | GCP |
| 第三方项目 A | AWS |
| 第三方项目 B | 阿里云 |
所有外部项目统一通过以下两个入口接入:
Microcosm Open API (https://api.microcosm.money)
| 路由 | 说明 |
|---|---|
/v1/mcc/* | MCC Token API |
/v1/mcd/* | MCD 积分 API |
/v1/users/* | 用户 API |
/v1/orgs/* | 组织 API |
Microcosm OAuth (https://microcosm.money)
| 路由 | 说明 |
|---|---|
/oauth/authorize | 授权 |
/oauth/token | Token 交换 |
/oauth/introspect | 验证 |
2.2 SDK 分层架构
SDK 分为四层,自上而下依次为:
第 1 层:应用层 (项目代码)
import { useAuth, useMCD } from '@microcosm/auth-react'
const { user, login } = useAuth()
const { balance } = useMCD()
第 2 层:框架适配层 (Framework Adapters)
| 框架 | 包名 |
|---|---|
| React / Next.js | @microcosm/auth-react |
| Vue.js | @microcosm/auth-vue |
| Angular | @microcosm/auth-angular |
第 3 层:核心层 (Core SDK) — @microcosm/auth-core
| 模块 | 职责 |
|---|---|
| AuthClient | 认证客户端 |
| TokenManager | Token 管理 |
| APIClient | API 调用 |
| StateManager | 状态管理 |
第 4 层:后端 SDK (Server SDKs)
| 语言 | 包名 |
|---|---|
| Python | microcosm-auth-python |
| Node.js | @microcosm/auth-node |
| Go | microcosm-auth-go |
3. 前端 SDK 使用示例
3.1 基础用法 (React/Next.js)
npm install @microcosm/auth-react
// app/providers.tsx
import { MicrocosmAuthProvider } from '@microcosm/auth-react'
export function Providers({ children }) {
return (
<MicrocosmAuthProvider
clientId="doublehelix"
redirectUri="/auth/callback"
>
{children}
</MicrocosmAuthProvider>
)
}
// app/page.tsx
import { useAuth } from '@microcosm/auth-react'
export default function HomePage() {
const { user, isLoading, login, logout } = useAuth()
if (isLoading) return <div>Loading...</div>
if (!user) {
return <button onClick={login}>登录</button>
}
return (
<div>
<p>欢迎, {user.email}</p>
<button onClick={logout}>登出</button>
</div>
)
}
// app/auth/callback/page.tsx
import { AuthCallback } from '@microcosm/auth-react'
export default function CallbackPage() {
return <AuthCallback redirectTo="/dashboard" />
}
就这么简单! 3 个文件,不到 30 行代码,完成整个认证接入。
3.2 保护路由
import { withAuth } from '@microcosm/auth-react'
function DashboardPage() {
const { user } = useAuth()
return <div>Dashboard for {user.email}</div>
}
// 自动重定向未登录用户到登录页
export default withAuth(DashboardPage)
3.3 获取 Access Token (调用 API)
import { useAuth } from '@microcosm/auth-react'
function MyComponent() {
const { getAccessToken } = useAuth()
const fetchData = async () => {
const token = await getAccessToken() // 自动处理刷新
const res = await fetch('/api/data', {
headers: { Authorization: `Bearer ${token}` }
})
return res.json()
}
}
3.4 调用 Open API (MCC/MCD 数据)
import { useAuth, useMCD, useMCC } from '@microcosm/auth-react'
function AssetPage() {
// 方式一: 使用封装好的 Hooks
const { balance: mcdBalance, loading: mcdLoading } = useMCD()
const { balance: mccBalance, loading: mccLoading } = useMCC()
// 方式二: 直接调用 Open API
const { getAccessToken } = useAuth()
const fetchMCDBalance = async () => {
const token = await getAccessToken()
const res = await fetch('https://api.microcosm.money/v1/mcd/balance', {
headers: { Authorization: `Bearer ${token}` }
})
return res.json()
}
return (
<div>
<p>MCC 余额: {mccBalance?.total_balance}</p>
<p>MCD 积分: {mcdBalance?.total_balance}</p>
</div>
)
}
3.5 更新用户资料 (共享用户架构)
重要: Microcosm 是统一用户平台,用户在任意项目更新 display_name 或 avatar 后,所有项目立即生效。
import { useAuth, useProfile } from '@microcosm/auth-react'
function ProfilePage() {
// 方式一: 使用封装好的 Hook
const { profile, updateProfile, uploadAvatar, loading } = useProfile()
const handleUpdateName = async (newName: string) => {
await updateProfile({ display_name: newName })
// 更新后所有项目(Double Helix、Event Horizon)立即生效
}
const handleUploadAvatar = async (file: File) => {
await uploadAvatar(file)
}
// 方式二: 直接调用 Open API
const { getAccessToken } = useAuth()
const updateDisplayName = async (displayName: string) => {
const token = await getAccessToken()
const res = await fetch('https://api.microcosm.money/v1/users/me/profile', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ display_name: displayName })
})
return res.json()
}
const uploadAvatarFile = async (file: File) => {
const token = await getAccessToken()
const formData = new FormData()
formData.append('avatar', file)
const res = await fetch('https://api.microcosm.money/v1/users/me/avatar', {
method: 'POST',
headers: { Authorization: `Bearer ${token}` },
body: formData
})
return res.json()
}
return (
<div>
<p>当前昵称: {profile?.display_name}</p>
<input
type="text"
placeholder="新昵称 (1-50字符)"
onChange={(e) => handleUpdateName(e.target.value)}
/>
<input
type="file"
accept="image/jpeg,image/png,image/gif,image/webp"
onChange={(e) => e.target.files?.[0] && handleUploadAvatar(e.target.files[0])}
/>
</div>
)
}
3.6 Open API 速率限制处理
import { useAuth } from '@microcosm/auth-react'
function MyComponent() {
const { getAccessToken } = useAuth()
const fetchWithRetry = async (url: string) => {
const token = await getAccessToken()
const res = await fetch(url, {
headers: { Authorization: `Bearer ${token}` }
})
// 检查速率限制
const remaining = res.headers.get('X-RateLimit-Remaining')
const reset = res.headers.get('X-RateLimit-Reset')
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get('Retry-After') || '60')
console.log(`Rate limited. Retry after ${retryAfter}s`)
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000))
return fetchWithRetry(url) // 重试
}
return res.json()
}
}
3.7 角色权限控制
import { useAuth, RequireRole } from '@microcosm/auth-react'
function AdminPage() {
return (
<RequireRole roles={['admin']} fallback={<div>无权限</div>}>
<AdminDashboard />
</RequireRole>
)
}
4. 后端 SDK 使用示例
4.1 Python (Flask)
pip install microcosm-auth
from flask import Flask
from microcosm_auth import MicrocosmAuth, require_auth
app = Flask(__name__)
# 一行配置
auth = MicrocosmAuth(
client_id="doublehelix",
client_secret="sk_xxx" # 从环境变量读取
)
# 保护路由 - 装饰器方式
@app.route('/api/protected')
@auth.require_auth
def protected_route():
user = auth.current_user # 自动注入
return {"message": f"Hello {user.email}"}
# 保护路由 - 角色限制
@app.route('/api/admin')
@auth.require_role('admin')
def admin_route():
return {"message": "Admin only"}
# 手动验证 token
@app.route('/api/manual')
def manual_route():
token = request.headers.get('Authorization', '').replace('Bearer ', '')
user = auth.verify_token(token)
if not user:
return {"error": "Unauthorized"}, 401
return {"user": user.to_dict()}
4.2 Python (FastAPI)
from fastapi import FastAPI, Depends
from microcosm_auth.fastapi import MicrocosmAuth, get_current_user, User
app = FastAPI()
auth = MicrocosmAuth(client_id="doublehelix", client_secret="sk_xxx")
@app.get('/api/protected')
async def protected_route(user: User = Depends(get_current_user)):
return {"message": f"Hello {user.email}"}
4.3 Node.js (Express)
const express = require('express')
const { MicrocosmAuth } = require('@microcosm/auth-node')
const app = express()
const auth = new MicrocosmAuth({
clientId: 'doublehelix',
clientSecret: process.env.MICROCOSM_CLIENT_SECRET
})
// 中间件方式
app.get('/api/protected', auth.requireAuth(), (req, res) => {
res.json({ message: `Hello ${req.user.email}` })
})
// 角色限制
app.get('/api/admin', auth.requireRole('admin'), (req, res) => {
res.json({ message: 'Admin only' })
})
4.4 Go
package main
import (
"github.com/microcosm/auth-go"
"net/http"
)
func main() {
auth := microcosm.NewAuth(microcosm.Config{
ClientID: "doublehelix",
ClientSecret: os.Getenv("MICROCOSM_CLIENT_SECRET"),
})
http.Handle("/api/protected", auth.RequireAuth(protectedHandler))
http.ListenAndServe(":8080", nil)
}
func protectedHandler(w http.ResponseWriter, r *http.Request) {
user := microcosm.GetUser(r.Context())
json.NewEncoder(w).Encode(map[string]string{
"message": "Hello " + user.Email,
})
}
5. 核心 API 设计
5.1 统一响应格式
所有 Microcosm API 采用统一响应格式,且必须保证 100% JSON 返还率。严禁返回 HTML 格式的 500 错误页面。
interface ApiResponse<T> {
success: boolean
data: T | null
error: string | null // 简要错误描述
message?: string | null // 详细错误信息 (可选)
}
加固准则:
- 全局拦截: 所有服务必须配置全局异常处理器(Global Exception Handler),捕获一切未处理异常并映射为 500 JSON。
- 契约意识: 禁止通过中间件(如 Nginx)直接返回默认 HTML 错误页,必须包装为 JSON。
成功响应:
{
"success": true,
"data": {
"uid": "abc123",
"email": "user@example.com",
"role": "user"
},
"error": null
}
错误响应:
{
"success": false,
"data": null,
"error": {
"code": "invalid_token",
"message": "The access token has expired"
}
}
5.2 标准错误码
| 错误码 | HTTP 状态 | 说明 |
|---|---|---|
invalid_request | 400 | 请求参数错误 |
invalid_client | 401 | client_id 或 secret 错误 |
invalid_token | 401 | Token 无效 |
token_expired | 401 | Token 已过期 |
insufficient_scope | 403 | 权限不足 (见下方 Scope 映射说明) |
user_not_found | 404 | 用户不存在 |
rate_limit_exceeded | 429 | 请求过于频繁 |
server_error | 500 | 服务器内部错误 |
OIDC Scope 映射 (2026-01-18):
为兼容 OpenID Connect 标准,Open API 自动将 OIDC scope 映射到 Microcosm scope:
| OIDC Scope | 映射到 Microcosm Scope | 说明 |
|---|---|---|
profile | user:read | 可访问用户资料 API |
openid | - | 仅用于 OIDC 身份验证 |
email | - | 仅用于获取邮箱声明 |
示例: 使用 scope: "openid profile email" 的 Token 可以调用 /v1/users/me/profile。
5.3 OAuth 端点 (microcosm.money)
| 端点 | 方法 | 说明 |
|---|---|---|
/oauth/authorize | GET | 授权页面 |
/oauth/token | POST | Token 交换/刷新 |
/oauth/introspect | POST | Token 验证 |
/oauth/revoke | POST | 撤销 Token |
/oauth/userinfo | GET | 获取用户信息 (OIDC) |
/.well-known/openid-configuration | GET | OIDC 发现文档 |
/.well-known/jwks.json | GET | JWT 公钥 |
5.4 Open API 端点 (api.microcosm.money)
MCD (Microcosm Dollar) API:
| 端点 | 方法 | 权限 | 说明 |
|---|---|---|---|
/v1/mcd/balance | GET | mcd:read | 获取 MCD 余额 |
/v1/mcd/transactions | GET | mcd:read | 获取交易记录 |
/v1/mcd/rewards | GET | mcd:read | 获取每日奖励 |
/v1/mcd/stats | GET | 公开 | 获取全局统计 |
MCC (Microcosm Coin) API:
| 端点 | 方法 | 权限 | 说明 |
|---|---|---|---|
/v1/mcc/balance | GET | mcc:read | 获取 MCC 余额 |
/v1/mcc/balance/{address} | GET | 公开 | 获取指定地址余额 |
/v1/mcc/transactions | GET | mcc:read | 获取交易记录 |
/v1/mcc/price | GET | 公开 | 获取当前价格 |
/v1/mcc/stats | GET | 公开 | 获取全局统计 |
用户 API:
| 端点 | 方法 | 权限 | 说明 |
|---|---|---|---|
/v1/users/me | GET | user:read | 获取当前用户信息 |
/v1/users/me/profile | GET | user:read | 获取用户详细资料 |
/v1/users/me/profile | PATCH | user:write | 更新用户资料 (display_name) |
/v1/users/me/avatar | POST | user:write | 上传用户头像 |
/v1/users/{uid} | GET | user:read:public | 获取指定用户公开信息 |
⚠️ OIDC Scope 兼容 (2026-01-18 修复): OpenID Connect 标准
profilescope 自动映射到user:read。 这意味着使用scope: "openid profile email"的 OAuth Token 可以访问用户 API。
Solana 合约 API (v1.1.0 新增):
| 模块 | 端点 | 方法 | 权限 | 说明 |
|---|---|---|---|---|
| Territory NFT | /v1/territory/collection | GET | 项目认证 | Collection 配置 |
/v1/territory/nft/{mint} | GET | 项目认证 | NFT 元数据 | |
/v1/territory/nfts/{wallet} | GET | 项目认证 | 用户 NFT 列表 | |
/v1/territory/unit/{unit_id}/nft | GET | 项目认证 | 单位关联 NFT | |
| Auction Solana | /v1/auction-solana/config | GET | 项目认证 | 拍卖配置 |
/v1/auction-solana/active | GET | 项目认证 | 活跃拍卖列表 | |
/v1/auction-solana/auction/{id} | GET | 项目认证 | 拍卖详情 | |
/v1/auction-solana/auction/{id}/bids | GET | 项目认证 | 竞价历史 | |
/v1/auction-solana/bids/{wallet} | GET | 项目认证 | 用户竞价记录 | |
/v1/auction-solana/auctions/{wallet} | GET | 项目认证 | 用户创建的拍卖 | |
| Fragment | /v1/fragment/config | GET | 项目认证 | 碎片化配置 |
/v1/fragment/vaults | GET | 项目认证 | 所有 Vault 列表 | |
/v1/fragment/vault/{id} | GET | 项目认证 | Vault 详情 | |
/v1/fragment/vault/{id}/holders | GET | 项目认证 | 持仓分布 | |
/v1/fragment/holdings/{wallet} | GET | 项目认证 | 用户持仓 | |
| Lending | /v1/lending/pool | GET | 项目认证 | 借贷池配置 |
/v1/lending/stats | GET | 项目认证 | 借贷池统计 | |
/v1/lending/position/{wallet} | GET | 项目认证 | 用户仓位 | |
/v1/lending/loans/{wallet} | GET | 项目认证 | 用户贷款列表 | |
/v1/lending/loan/{wallet}/{loan_id} | GET | 项目认证 | 贷款详情 | |
/v1/lending/lp-balance/{wallet} | GET | 项目认证 | LP Token 余额 | |
/v1/lending/calculate-interest | POST | 项目认证 | 计算利息 | |
/v1/lending/estimate-borrow-cost | POST | 项目认证 | 估算借款成本 |
API 文档:
| 端点 | 说明 |
|---|---|
https://api.microcosm.money/docs | Swagger UI 交互式文档 |
https://api.microcosm.money/redoc | ReDoc 文档 |
https://api.microcosm.money/openapi.json | OpenAPI 3.1 规范 |
6. SDK 内部实现
6.1 @microcosm/auth-core
// 核心配置
interface MicrocosmAuthConfig {
clientId: string
redirectUri: string
scope?: string[] // 默认 ['openid', 'profile', 'email']
authEndpoint?: string // 默认 'https://microcosm.money'
usePKCE?: boolean // 默认 true
storage?: 'localStorage' | 'sessionStorage' | 'cookie'
autoRefresh?: boolean // 默认 true
refreshBuffer?: number // Token 过期前多少秒刷新,默认 300
}
// 用户对象
interface User {
uid: string
email: string
displayName?: string
role: 'admin' | 'user' | 'agent' // 系统角色
level: 'recruit' | 'prospect' | 'miner' // 用户级别
title?: 'commander' | 'pioneer' | 'warden' | 'admiral' | null // 职级头衔(基于 NFT)
stationId?: number // 所属 Station ID(Miner 才有)
avatarUrl?: string
emailVerified?: boolean
}
// 核心类
class MicrocosmAuthClient {
constructor(config: MicrocosmAuthConfig)
// 认证方法
login(options?: { prompt?: 'login' | 'consent' }): void
logout(): Promise<void>
handleCallback(): Promise<User>
// 状态方法
getUser(): User | null
isAuthenticated(): boolean
getAccessToken(): Promise<string | null> // 自动刷新
// 事件监听
onAuthStateChange(callback: (user: User | null) => void): () => void
}
6.2 自动 Token 刷新
class TokenManager {
private refreshTimer: NodeJS.Timeout | null = null
async getAccessToken(): Promise<string | null> {
const token = this.getStoredToken()
if (!token) return null
// 检查是否需要刷新(提前 5 分钟)
if (this.shouldRefresh(token)) {
return this.refreshToken()
}
return token.accessToken
}
private shouldRefresh(token: TokenData): boolean {
const bufferMs = this.config.refreshBuffer * 1000
return token.expiresAt - Date.now() < bufferMs
}
private async refreshToken(): Promise<string> {
// 防止并发刷新
if (this.refreshPromise) {
return this.refreshPromise
}
this.refreshPromise = this.doRefresh()
try {
return await this.refreshPromise
} finally {
this.refreshPromise = null
}
}
}
6.3 PKCE 实现 (安全增强)
class PKCEManager {
static async generateChallenge(): Promise<{
codeVerifier: string
codeChallenge: string
}> {
// 生成随机 code_verifier
const codeVerifier = this.generateRandomString(64)
// 计算 code_challenge = BASE64URL(SHA256(code_verifier))
const encoder = new TextEncoder()
const data = encoder.encode(codeVerifier)
const digest = await crypto.subtle.digest('SHA-256', data)
const codeChallenge = this.base64UrlEncode(digest)
return { codeVerifier, codeChallenge }
}
}
6.4 API 调用健壮性 (Safe Parsing)
客户端 SDK 在发起 API 请求时,必须采用“防御式解析”模式,防止因突发情况(如 Nginx 级错误)导致的 JS 崩溃。
// 推荐的 fetchApi 内部逻辑
const safeJson = async (res: Response) => {
const contentType = res.headers.get('content-type')
if (contentType?.includes('application/json')) {
return res.json()
}
// 如果非 JSON 响应,捕获为文本错误描述
const text = await res.text()
return {
success: false,
error: 'Non-JSON Response',
message: text.substring(0, 200)
}
}
7. 项目接入流程
步骤 1: 注册项目
在 Microcosm 开发者控制台注册项目:
https://microcosm.money/developer/apps/new
获取:
client_id: 项目唯一标识client_secret: 项目密钥(仅后端使用)
步骤 2: 安装 SDK
前端 (React/Next.js):
npm install @microcosm/auth-react
后端 (Python):
pip install microcosm-auth
步骤 3: 配置
前端:
// app/providers.tsx
<MicrocosmAuthProvider clientId="your-client-id" redirectUri="/auth/callback">
{children}
</MicrocosmAuthProvider>
后端:
# 从环境变量读取
auth = MicrocosmAuth(
client_id=os.environ['MICROCOSM_CLIENT_ID'],
client_secret=os.environ['MICROCOSM_CLIENT_SECRET']
)
步骤 4: 使用
前端使用 useAuth() hook,后端使用 @auth.require_auth 装饰器。
完成! 整个接入过程不超过 10 分钟。
8. 与现有方案对比
| 方面 | 当前方案 (Double Helix) | SDK 方案 |
|---|---|---|
| 代码量 | 5+ 文件,200+ 行 | 3 文件,< 30 行 |
| 接入时间 | 1-2 天 | 10 分钟 |
| 错误处理 | 手动处理各种边界情况 | SDK 自动处理 |
| Token 刷新 | 手动实现 | 自动刷新 |
| 响应格式 | 需要兼容多种格式 | 统一格式 |
| 类型安全 | 手动定义类型 | SDK 内置类型 |
| 调试 | 手动添加日志 | SDK 内置调试模式 |
| 升级维护 | 每个项目单独维护 | 统一升级 SDK |
9. 安全特性
| 特性 | 说明 |
|---|---|
| PKCE | 防止授权码劫持攻击 |
| State 验证 | 防止 CSRF 攻击 |
| Token 轮换 | 每次刷新返回新的 refresh_token |
| Secure Cookie | 可选的 cookie 存储方式 |
| HTTPS 强制 | 生产环境强制 HTTPS |
| 速率限制 | 防止暴力破解 |
| Token 撤销 | 支持主动撤销 Token |
10. 开发者控制台
为项目管理者提供 Web 控制台:
https://microcosm.money/developer
功能:
- 项目注册与管理
- 查看 client_id / 轮换 client_secret
- 配置回调 URL 白名单
- 查看 API 调用统计
- 查看活跃用户数
- 查看错误日志
11. 实施路线图
Phase 1: 核心 SDK (2 周)
- @microcosm/auth-core - 核心库
- @microcosm/auth-react - React 适配
- 统一 API 响应格式
- 基础文档
Phase 2: 后端 SDK (2 周)
- microcosm-auth-python (Flask/FastAPI)
- @microcosm/auth-node (Express)
- 后端验证中间件
Phase 3: 高级特性 (2 周)
- PKCE 支持
- OIDC 发现文档
- JWT 验证(减少 introspect 调用)
- 开发者控制台
Phase 4: 生态扩展 (持续)
- Vue.js 适配
- Go SDK
- 更多框架适配
- SDK 测试套件
12. ⚠️ OAuth Callback 用户资料处理 (重要)
12.1 问题背景 (2026-01-16)
在 Double Helix 集成中发现的问题:用户登录成功后,侧边栏无法显示头像和昵称。
根因: OAuth callback 页面在保存用户信息时遗漏了 displayName 和 avatarUrl 字段。
12.2 正确的 Callback 处理
// OAuth callback 中正确设置用户信息
const handleCallback = async () => {
// 1. Token exchange
const tokenData = await fetch("/api/auth/exchange", {
method: "POST",
body: JSON.stringify({ code }),
}).then(res => res.json())
// 2. 获取用户详细资料
const profileRes = await fetch("/api/users/profile", {
headers: { Authorization: `Bearer ${tokenData.access_token}` }
})
const profileData = await profileRes.json()
// 3. 兼容解包 (API 可能返回 {user: {...}} 或 {...})
const userData = profileData.user || profileData
// 4. ⚠️ 必须传递 displayName 和 avatarUrl!
authManager.setUser({
uid: userData.uid,
email: userData.email || "",
role: userData.role || "user",
displayName: userData.display_name || null, // ← 必须
avatarUrl: userData.avatar_url || null, // ← 必须
apiKeysConfigured: userData.api_keys_configured || false,
})
router.push("/dashboard")
}
12.3 字段名映射规则
| API 响应 (snake_case) | 前端 User 类型 (camelCase) |
|---|---|
display_name | displayName |
avatar_url | avatarUrl |
api_keys_configured | apiKeysConfigured |
12.3.1 头像存储架构 (2026-02-02 更新)
重要变更: 头像现在存储在 GCS Bucket 而非数据库。
| 配置 | 值 |
|---|---|
| GCS Bucket | double-helix-avatars |
| 文件路径 | avatars/{uid}/avatar.jpg |
| 存储策略 | 固定文件名,覆盖式更新 |
| 图片处理 | 最大 512×512,JPEG 85% 质量 |
| 上传限制 | 最大 2MB,支持 jpg/png/gif/webp |
avatar_url 格式:
https://storage.googleapis.com/double-helix-avatars/avatars/{uid}/avatar.jpg
12.4 检查清单
- OAuth callback 中调用
/api/users/profile获取完整用户信息 - 兼容处理响应格式 (
data.user || data) - setUser 时传递
displayName和avatarUrl - 字段名正确从 snake_case 映射到 camelCase
13. 项目注册与 MCD 白名单 ✅ 已实施
2026-01-25 实施完成
组件 版本 状态 open-api-service v1.1.8 ✅ API 已部署 blockchain-service v1.2.28 ✅ 链上操作已集成 portal-service v1.7.23 ✅ 管理页面已上线
13.1 概述
开发者在接入 Microcosm Open API 之前,需要先完成项目注册并获得 API Key。注册流程中必须提交 MCD 钱包地址,用于后续的 MCD 积分消费场景。
13.2 注册流程
项目注册流程
- 开发者登录 Microcosm Portal
- 进入"开发者中心" -> "申请项目接入"
- 填写表单:
- 项目名称
- 项目描述
- 公司名称
- 网站 URL
- MCC 钱包地址 (选填)
- MCD 钱包地址 (必填,用于接收用户 MCD 消费)
- 提交申请 (状态: pending)
- 管理员审核
- 审核通过:
- 生成 Project ID
- 生成 API Key / API Secret
- 创建链上白名单 PDA
- 开发者获取凭证,开始集成
13.3 MCD 白名单机制
为什么需要白名单:
MCD 是系统控制的积分(1 MCD = 1 USDC),用户无法自由转账。用户消费 MCD 时,只能转账到已注册的项目钱包(白名单地址)。
链上验证流程:
- 用户调用
consume_mcd消费 MCD - 合约验证目标地址是否在白名单
- 在白名单且 active -> 允许转账
- 不在白名单或 suspended -> 拒绝交易
相关合约指令:
| 指令 | 用途 |
|---|---|
add_to_whitelist | 添加项目钱包到白名单 |
remove_from_whitelist | 从白名单移除 |
update_whitelist_status | 更新状态 (active/suspended) |
13.4 SDK 集成要点
开发者获取凭证后:
// 1. 配置 SDK
const config = {
clientId: "your-project-id",
apiKey: "mc_live_xxxxx",
apiSecret: "mc_secret_yyyyy",
redirectUri: "/auth/callback"
}
// 2. 初始化 SDK
<MicrocosmAuthProvider {...config} />
// 3. MCD 消费场景 - 用户消费 MCD 会转到你注册的钱包
const { consumeMcd } = useMcd()
await consumeMcd({
amount: 100, // 消费 100 MCD
memo: "购买商品"
})
13.5 管理员审核 ✅ 已上线
管理员可在 Portal 后台管理项目申请和白名单:
| 页面 | 路径 | 功能 | 状态 |
|---|---|---|---|
| 项目申请列表 | /admin/project-applications | 审核开发者申请 | ✅ 已上线 |
| MCD 白名单 | /admin/mcd-whitelist | 管理白名单状态 | ✅ 已上线 |
访问方式: 以管理员身份登录 https://microcosm.money,在侧边栏找到"项目审核"和"MCD 白名单"菜单。
14. 总结
通过 SDK 模块化,未来任何项目接入 Microcosm 认证只需要:
// 1. 安装
npm install @microcosm/auth-react
// 2. 配置 (1 行)
<MicrocosmAuthProvider clientId="xxx" redirectUri="/auth/callback" />
// 3. 使用 (1 行)
const { user, login, logout } = useAuth()
不需要:
- 手动处理 OAuth 流程
- 手动刷新 Token
- 手动处理响应格式
- 手动添加调试日志
- 重复实现认证逻辑
从"一天一夜调试"到"10 分钟接入"。