better-auth-mastodon
v1.0.0
Published
Better Auth 的 Mastodon OAuth 登录插件
Maintainers
Readme
Better Auth Mastodon Plugin
一个用于 Better Auth 的 Mastodon OAuth 登录插件,支持多实例动态域名和应用自动注册。
特性
- 🔐 OAuth 2.0 授权码流程:完整的 OAuth 2.0 实现,支持 PKCE 扩展
- 🌐 多实例支持:支持任意 Mastodon 实例登录(mastodon.social、pawoo.net 等)
- 🤖 应用自动注册:自动在目标实例上注册 OAuth 应用,无需手动配置
- 💾 数据库持久化:自动保存应用配置到数据库,避免重复注册
- 📦 开箱即用:简单的 API 设计,易于集成
安装
npm install better-auth-mastodon
# 或
yarn add better-auth-mastodon
# 或
pnpm add better-auth-mastodon快速开始
服务器端配置
import { betterAuth } from "better-auth";
import { mastodonPlugin } from "better-auth-mastodon";
export const auth = betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
mastodonPlugin({
// 应用名称(注册时使用)
appName: "My Awesome App",
// 应用网站(可选)
appWebsite: "https://myapp.com",
// 回调 URL
redirectUri: "http://localhost:3000/api/auth/mastodon/callback",
// 权限范围(默认 "read")
scope: "read write follow",
}),
],
});客户端配置
import { createAuthClient } from "better-auth/client";
import { mastodonClientPlugin } from "better-auth-mastodon/client";
export const authClient = createAuthClient({
baseURL: "http://localhost:3000",
plugins: [mastodonClientPlugin()],
});登录使用
// 用户选择或输入 Mastodon 实例域名
const domain = "mastodon.social";
// 一键登录(应用会自动在实例上注册)
const userInfo = await authClient.mastodon.signIn(domain);
console.log("登录成功:", userInfo);API 文档
服务器端
mastodonPlugin(options)
创建 Mastodon 服务器插件。
参数:
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| appName | string | ✅ | 应用名称,注册时显示给用户的名称 |
| appWebsite | string | ❌ | 应用网站 URL |
| redirectUri | string | ✅ | OAuth 回调 URL |
| scope | string | ❌ | 权限范围,默认 "read" |
| useDatabase | boolean | ❌ | 是否使用数据库保存应用信息,默认 true |
示例:
mastodonPlugin({
appName: "My App",
appWebsite: "https://example.com",
redirectUri: "https://example.com/api/auth/mastodon/callback",
scope: "read write follow",
});客户端
authClient.mastodon.signIn(domain)
完整的登录流程,打开授权窗口并返回用户信息。
const userInfo = await authClient.mastodon.signIn("mastodon.social");
// 返回:{ mastodonId, username, displayName, avatar, url, accessToken, scope, domain }authClient.mastodon.getAuthorizationUrl(domain)
获取授权 URL,用于自定义登录流程。
const authData = await authClient.mastodon.getAuthorizationUrl("mastodon.social");
// 返回:{ url, state, codeVerifier, domain }authClient.mastodon.handleCallback(code, state, codeVerifier, domain)
处理 OAuth 回调,获取用户信息。
const userInfo = await authClient.mastodon.handleCallback(
code,
state,
codeVerifier,
"mastodon.social"
);authClient.mastodon.refreshToken(refreshToken, domain)
刷新访问令牌。
const newToken = await authClient.mastodon.refreshToken(refreshToken, "mastodon.social");
// 返回:{ accessToken, tokenType, scope, createdAt }authClient.mastodon.revokeToken(token, domain)
撤销访问令牌。
await authClient.mastodon.revokeToken(token, "mastodon.social");
// 返回:{ success: true }数据库 Schema
插件会自动创建以下数据表:
mastodonApp
存储注册的 OAuth 应用信息。
| 字段 | 类型 | 说明 |
|------|------|------|
| id | string | 主键 |
| domain | string | Mastodon 实例域名 |
| appName | string | 应用名称 |
| website | string? | 应用网站 |
| redirectUri | string | 回调 URL |
| clientId | string | OAuth 客户端 ID |
| clientSecret | string | OAuth 客户端密钥 |
| vapidKey | string? | VAPID 密钥(用于推送) |
| createdAt | date | 创建时间 |
| updatedAt | date | 更新时间 |
user(扩展字段)
| 字段 | 类型 | 说明 |
|------|------|------|
| mastodonId | string? | Mastodon 用户 ID |
| mastodonUsername | string? | 用户名 |
| mastodonDisplayName | string? | 显示名称 |
| mastodonAvatar | string? | 头像 URL |
| mastodonUrl | string? | 个人主页 URL |
| mastodonAccessToken | string? | 访问令牌 |
| mastodonDomain | string? | 实例域名 |
高级用法
分步登录流程
// 步骤 1: 获取授权 URL
const authData = await authClient.mastodon.getAuthorizationUrl("mastodon.social");
// 步骤 2: 打开授权窗口(或使用 signInWithPopup)
window.location.href = authData.url;
// 步骤 3: 处理回调(在回调页面执行)
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code");
const state = urlParams.get("state");
if (code && state) {
const userInfo = await authClient.mastodon.handleCallback(
code,
state,
authData.codeVerifier,
"mastodon.social"
);
console.log("用户信息:", userInfo);
}多实例登录
const instances = [
{ domain: "mastodon.social", name: "Mastodon Social" },
{ domain: "pawoo.net", name: "Pawoo" },
{ domain: "mstdn.jp", name: "Mstdn.jp" },
];
// 用户选择实例
const selected = instances[0];
// 应用会自动在选中的实例上注册
const userInfo = await authClient.mastodon.signIn(selected.domain);自定义回调处理
// 服务器端处理回调
export async function handleMastodonCallback(
code: string,
state: string,
codeVerifier: string,
domain: string
) {
// 调用 Better Auth API 获取用户信息
const response = await fetch(
`${process.env.BETTER_AUTH_URL}/api/auth/mastodon/callback`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ code, state, codeVerifier, domain }),
}
);
const mastodonUser = await response.json();
// 创建或关联用户账户
// ...
}工作原理
- 应用注册:当用户首次登录某个 Mastodon 实例时,插件会自动调用
POST /api/v1/apps向该实例注册 OAuth 应用 - 配置保存:注册成功后,将
client_id和client_secret保存到数据库 - OAuth 流程:使用标准 OAuth 2.0 授权码流程,支持 PKCE 扩展
- 配置复用:下次同一实例的登录直接使用已保存的配置
技术参考
许可证
MIT
