公民认证客户SDK
Civil Auth提供了一个简单,灵活,快捷的方法,将认证纳入您的应用程序.
您可以找到完整的官方文件 这里,在此 README 中有一个快速启动版本.
说明: 这一包仅以无害环境管理格式发布。 没有可用的 CJS 构建 .
快速启动
在不到一分钟的时间为公民奥思报名 auth.civic.com (英语) 获取客户身份.
使用您选择的安装器在您的应用程序中安装库 :
无
npm install @civic/auth
线条
yarn add @civic/auth
小时
pnpm install @civic/auth
包头
bun add @civic/auth
一体化
选择您如何将 Civil Auth 纳入应用程序的指令框架 .
使用 OIDC 或 OAuth 符合 2.0 的客户端库整合到其他环境中,请参见 这里。 。 。 .
反应
轻松地将 Civil Auth 整合到您的 React 应用程序中, 只要将您的应用程序包入 Civil Auth 提供者, 并添加您的客户端ID( 在您之后提供) 注册) (中文(简体) ). 我们有一个实例: github 实例重播。 。 。 .
import { CivicAuthProvider, UserButton } from "@civic/auth/react";
function App({ children }) {
return (
<CivicAuthProvider clientId="YOUR CLIENT ID">
<UserButton />
{children}
</CivicAuthProvider>
)
}
使用量
用户按钮
Citizen Auth SDK 带有多功能样式组件,称为 UserButton
import { UserButton, CivicAuthProvider } from '@civic/auth/react';
export function TitleBar() {
return (
<div className="flex justify-between items-center">
<h1>My App</h1>
<UserButton />
</div>
);
};
function App({ children }) {
return (
<CivicAuthProvider clientId="YOUR CLIENT ID">
<TitleBar />
</CivicAuthProvider>
)
}
这一构成部分取决于具体情况。 如果用户登录,它将显示他们的配置图和名称。 如果用户未登录, 则会显示日志输入按钮 .
在前端获取用户信息
使用 Civil Auth SDK 获取前端的用户信息 .
import { useUser } from '@civic/auth/react';
export function MyComponent() {
const { user } = useUser();
if (!user) return <div>User not logged in</div>
return <div>Hello { user.name }!</div>
}
我们用 name 作为这里的示例,但您可以调用用户字段中的任意对象属性, 如所示 下级。 。 。 .
高级配置
Civil Auth是一个"低码"解决方案,所以所有配置都通过 仪表板。您所做的更改将在您的整合中自动更新,而无需修改代码。 您需要提供的唯一参数是客户端ID .
集成提供了额外的运行时间设置和钩子,您可以用来自定义库与自己应用程序的集成. 如果您需要这些,您可以在公民认证中添加如下内容:
<CivicAuthProvider
clientId="YOUR CLIENT ID"
...other configuration
>
所有配置选项列表见下文
| 外地 | 需求 | 默认 | 示例 | 说明 |
|---|---|---|---|---|
| 客户端ID | 对 | - 说吧 | 2cc5633d-2c92-48da-86aa-449634f274b9 | 注册到 auth.civic.com (英语) |
| 无 | 没有 | - 说吧 | 第1234条 | 登录时使用的单用ID,将登录符与给定客户端绑定. 仅需高级认证程序 |
| 签名时 | 没有 | - 说吧 | | 签入尝试后执行的钩子, 不管成功与否. |
| 签名时 | 没有 | - 说吧 | | 用户日志出后执行的钩子 . |
| 重定向 Url | 没有 | 当前URL | 认证 | OAuth 将重定向到执行符号交换的页面的覆盖 。 默认情况下, Civil 将重定向到当前 URL, 认证由 Civil 提供者自动完成 。 只有在 OAuth 证书交换时需要自定义显示或逻辑时才使用. 重定向页面必须让 CivilAuth Provider 运行才能完成认证 . |
模式框架 | 没有 | 真实 | 模式Iframe真 | 设定为 true 如果您想要将登录的 Iframe 嵌入到您的应用程序中, 而不是以模式打开 。 见 嵌入式登录 Iframe 部分 见下文. |
| 自动方向 | 没有 | 真实 | 自动重定向QFalse} | 当启用时,在不支持以iframe为基础的认证(例如有密码的Safari)的浏览器中自动使用"redict"模式进行认证. 而不是用户在一个iframe中进行认证,当前页面会加载登录页面,用户在Succesful 登录完成后会被重定向回. |
显示模式
显示模式将显示公民登录 UI 的位置 。 支持下列显示模式:
iframe(默认) : UI 装入一个在已存在的页面内容上方的覆盖中显示的 iframeredirect: UI 将当前 URL 重定向到 Civil 登录屏幕, 然后在登录完成后重定向回您的站点new_tab: UI 在一个新的标签或弹出窗口中打开(取决于浏览器的偏好),登录完成后,标签或弹出关闭将用户返回您的站点
浏览器- 特定支持
Citizen Auth SDK包括自动浏览器检测处理浏览器特定限制. Safari等一些浏览器不支持在"iframe"模式下创建密码. 在这种情况下,我们自动启动“方向”流动,以便用户有一个无缝的UX。 用户看到一个装入器代替了iframe,然后页面重定向直接显示登录界面.
API 密码
用户背景
完整用户上下文对象(由 useUser看起来是这样的:
{
user: User | null;
// these are the OAuth tokens created during authentication
idToken?: string;
accessToken?: string;
refreshToken?: string;
forwardedTokens?: ForwardedTokens;
// functions and flags for UI and signIn/signOut
isLoading: boolean;
authStatus: AuthStatus;
error: Error | null;
signIn: (displayMode?: DisplayMode) => Promise<void>;
signOut: () => Promise<void>;
}
用户
这个 User 对象看起来像 :
type BaseUser = {
id: string;
email?: string;
name?: string;
picture?: string;
given_name?: string;
family_name?: string;
updated_at?: Date;
};
type UnknownObject = Record<string, unknown>;
type EmptyObject = Record<string, never>;
type User<T extends UnknownObject | EmptyObject = EmptyObject> =
T extends EmptyObject ? BaseUser : BaseUser & T;
在您可以将额外的用户属性传递给您知道将会出现在用户请求中的对象的地方,例如.
const UserWithNickName = User<{ nickname: string }>;
实地说明:
基础用户字段
| 外地 | |
|---|---|
| 编号 | 用户在您的应用程序方面独有的ID. 您可以使用此选项查找用户 仪表板。 。 。 . |
| 电子邮件 | 用户的电子邮件地址 |
| 名称 | 用户的全名 |
| 给定名称( n) | 用户的名字 |
| 家族名称 | 用户的姓 |
| 已更新 at | 用户的配置最近更新的时间. |
托肯字段
通常开发者不需要与符号字段交互,这些字段只用于高级用例.
| 外地 | |
|---|---|
| 图标 | OIDC 代号,用于请求用户身份信息 |
| 访问脚本 | OAuth 2.0访问令牌,允许客户端代表用户向Civil Auth发出API呼叫. |
| 刷新脚本 | OAuth 2.0 刷新令牌,允许登录会话自动被扩展而不需要用户交互. Civil Auth SDK 手柄自动刷新,所以你不需要这样做. |
| 已转发 键 | 如果用户使用单一签名登录的SSO(单签名登录)与Google等联合OAuth提供商进行认证,则包含来自该提供商的OIDC和OAuth 2.0签名. |
转发托肯斯
已转发的使用 如果需要向源提供者提出请求,例如查找提供者特有的信息,则按键.
例如,如果用户通过Google登录,使用Google转发的令牌查询用户所属的Google团体.
例如:
const googleAccessToken = user.forwardedTokens?.google?.accessToken;
嵌入式登录框架
如果您想让登录屏幕在页面上直接打开, 而用户无需点击按钮, 您可以导入 CivicAuthIframeContainer 组件并连同 Auth 提供选项一起使用 iframeMode={"embedded"}
你只需要确保 CivicAuthIframeContainer 是一个孩子 CivicAuthProvider
import { CivicAuthIframeContainer } from "@civic/auth/react";
const Login = () => {
return (
<div class="login-container">
<CivicAuthIframeContainer />
</div>
);
};
const App = () => {
return (
<CivicAuthProvider
clientId={"YOUR CLIENT ID"}
iframeMode={"embedded"}
>
<Login />
</CivicAuthProvider>
);
}
下一个 联合来文
快速启动
使用下列步骤将 Civil Auth 纳入您的 Next.js 应用程序(我们可在 github 实例重播:
1. 添加公民认证插件
这里是您在注册时提供客户端身份的应用程序 auth.civic.com (英语)。 。 。 .
对于大多数客户来说,默认值应该通过框处理,但是如果您想要配置您的应用程序,请查看 下级 详细情况.
import { createCivicAuthPlugin } from "@civic/auth/nextjs"
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
};
const withCivicAuth = createCivicAuthPlugin({
clientId: 'YOUR CLIENT ID'
});
export default withCivicAuth(nextConfig)
2. 创建 API 路由
您的应用程序将在这里处理登录和登录请求 .
在以下路径创建此文件 :
src/app/api/auth/[...civicauth]/route.ts
import { handler } from '@civic/auth/nextjs'
export const GET = handler()
export const POST = handler()
这些步骤适用于: 应用路由器如果您正在使用 Pages 路由器, 请 联系我们 用于整合步骤.
3. 中间软件
Middleware用于保护您的后端路径,服务器组件和服务器动作不受未经认证的请求.
使用 Citizen Auth 中间软件可确保只有登录用户才能获取您服务的安全部分.
import { authMiddleware } from '@civic/auth/nextjs/middleware'
export default authMiddleware();
export const config = {
// include the paths you wish to secure here
matcher: [
/*
* Match all request paths except:
* - _next directory (Next.js static files)
* - favicon.ico, sitemap.xml, robots.txt
* - image files
*/
'/((?!_next|favicon.ico|sitemap.xml|robots.txt|.*\\.jpg|.*\\.png|.*\\.svg|.*\\.gif).*)',
],
}
说明: 如果您有分析代理重写
next.config.js(例如,对于Google Analytics、PostHog或其他跟踪服务,您应当将这些路径添加到exclude配置选项。 见 高级配置 详细情况.
处理行为:
- 有效符号: 用户通过保护路线
- 刷新可用的令牌: 自动重定向以刷新端点以将会话与
targetUrl参数 - 不刷新已过期的令牌: 重定向到登录调用以清除不良符号, 然后登录
- 无符号: 重定向到登录 URL
- 登录 URL 访问: 总是允许不管认证状态如何防止重定向循环
中间软件链
如果您已经在您的 Next.js 应用程序中使用了中间软件, 那么您可以将其与 Civil Auth 链接如下 :
import { auth } from '@civic/auth/nextjs'
import { NextRequest, NextResponse } from "next/server";
const withCivicAuth = auth()
const otherMiddleware = (request: NextRequest) => {
console.log('my middleware')
return NextResponse.next()
}
export default withCivicAuth(otherMiddleware)
4. 前端一体化
将 Civil Auth 上下文添加到您的应用程序中, 让您的前端访问登录用户 .
import { CivicAuthProvider } from "@civic/auth/nextjs";
function Layout({ children }) {
return (
// ... the rest of your app layout
<CivicAuthProvider>
{children}
</CivicAuthProvider>
)
}
不像纯洁 反应 综合,你做 没有 还要再加一个客户身份!
使用量
在前端获取用户信息
下一个 JS客户部分 可以使用 Civil Auth React 工具获取用户信息并显示方便的登录,以及登录按钮. 见 反应使用页面 详细情况.
在后端获取用户信息
获取后端代码上的用户信息, 如 React 服务器组件、 React 服务器动作或使用 api 路由 getUser数字 :
import { getUser } from '@civic/auth/nextjs';
const user = await getUser();
例如,在下一个JS服务器组件中:
import { getUser } from '@civic/auth/nextjs';
export async function MyServerComponent() {
const user = await getUser();
if (!user) return <div>User not logged in</div>
return <div>Hello { user.name }!</div>
}
这个 name 属性在此用作示例,请检查 反应使用页面 以查看整个基本用户对象结构.
高级配置
Civil Auth是一个"低码"的解决方案,所以大多数配置是通过: 仪表板。您所做的更改将在您的整合中自动更新,而无需修改代码。 您需要提供的唯一参数是客户端ID .
该集成还提供了根据您 Next.js app的需求定制库的能力. 例如,将认证检查限制在您的应用程序中的特定页面和路径. 你可以进去 next.config.js 内容如下:
const withCivicAuth = createCivicAuthPlugin({
clientId: 'YOUR CLIENT ID',
...other config
});
export default withCivicAuth(nextConfig) // your next config here
以下是可用的配置选项:
| 外地 | 需求 | 默认 | 示例 | 说明 |
|---|---|---|---|---|
| 客户端ID | 对 | - 说吧 | 2cc5633d-2c92-48da-86aa-449634f274b9 | 注册到 auth.civic.com (英语) |
| 调用 | 没有 | /api/auth/召回 | /api/myroute/召回 | 浏览器在 successful 登录之后的路径 。 设置此值, 如果您在推荐的默认值之外的其他地方托管您的公民 assent API 路由 上文。 。 。 . |
| 登录Url | 没有 | 编号 : | /管理 | 您的用户如果访问需要登录的资源, 将会被发送到该路径 。 如果您有专门的登录页面, 您可以在此设置 . |
| 登录Url | 没有 | 编号 : | 再见 | 您的用户在登录成功后将会被发送到的路径 . |
| 基数Url | 没有 | - 说吧 | https://myapp.com (中文(简体) ) | 应用软件在逆向代理(如Cloudfront + Vercel)后所部署的公交基址. 当您的应用程序在反向代理后方时, 中间软件可能使用内部来源而不是您的公有领域来构建重定向 URL 。 设定此选项可确保认证重定向使用正确的公共 URL . |
| 自动方向 | 没有 | 真实 | 自动方向: 假 | 当启用时,在不支持以iframe为基础的认证(例如有密码的Safari)的浏览器中自动使用"redict"模式进行认证. 而不是用户在一个iframe中进行认证,当前页面会加载登录页面,用户在Succesful 登录完成后会被重定向回. |
| 深链接配置 | 没有 | "满" | "只有凯里·帕拉姆斯" | 控制认证过程中如何保存深层链接. 见 深度链接 见下文. |
| 包含 | 没有 | [`*'] | [ “/admin/*”、“/api/admin/*” [ . ] | 一系列路径 缩写 需要登录用户才能访问。 如果没有设定, 将包含与您的 Next.js 匹配的所有路径 中间软件。 。 。 . |
| 排除 | 没有 | - 说吧 | ['/ga/**/*'、'/gtm/**/*'、'/摄入/**/*'] | 一系列路径 缩写 被排斥在公民认证书之外的 中间软件。 。 。 . 重要内容: 如果您有分析代理重写(例如对于Google Analytics,GTM,或PostHog),请在此添加这些路径来防止它们在认证时被捕获为返回URL. |
深度链接
深度链接可以让用户在完成认证后被重新定向回原目的地(包括查询参数). 当用户访问深层链接时( 如 : /dashboard?tab=settings 而不真实的.
配置选项 :
| 数值 | 说明 |
|---|---|
"fullUrl" (默认) | 保存包括路径和查询参数在内的完整 URL |
"queryParamsOnly" | 只保留查询参数, 重定向到根路径 |
"disabled" | 完全禁用深层链接 |
示例
const withCivicAuth = createCivicAuthPlugin({
clientId: 'YOUR CLIENT ID',
deepLinkConfig: 'fullUrl' // or 'queryParamsOnly' or 'disabled'
});
如何运作:
- 用户访问
/dashboard?tab=settings(未经认证) - 将 URL 存储在 cookie 中并重定向到登录
- 认证成功后,用户会被重定向到
/dashboard?tab=settings
由 Civil Auth 中间软件自动处理 - 不需要额外的代码 .
服务器集成
客户端秘密支持
Civil Auth支持OAuth 2.0客户端机密为机密客户端(服务器侧应用). 客户端秘密是可选的,为后端服务提供强化的安全.
何时使用客户机密 :
- 服务器侧应用程序, 其中可以安全存储该秘密
- 后端服务,不需要用户交互即可认证
- 不支持PKCE的遗留系统
当不使用客户机密时:
- 基于浏览器的 SPA( 使用 PKCE 代替)
- 移动应用程序(代之以PKCE)
- 任何可能暴露秘密的环境
要生成客户端的秘密,请访问 公民认证仪表板。 。 。 .
使用 CivilAuth 接口
对于服务器端集成, 您可以使用新的统一 CivicAuth 接口,它提供一整套带有内置符号验证的认证方法.
快速启动
import { CivicAuth, CookieStorage } from '@civic/auth/server';
// Define your authentication configuration
const config = {
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET', // Optional - for confidential clients only
redirectUrl: 'http://yoursite.com/auth/callback',
oauthServer: 'https://auth.civic.com/oauth',
postLogoutRedirectUrl: 'http://yoursite.com/auth/logoutcallback',
disableRefresh: false, // Optional - set to true to disable automatic token refresh
};
// Create a storage adapter that implements AuthStorage interface
class YourStorageAdapter extends CookieStorage {
// Implement the storage methods (get, set, delete)
// to work with your server framework's cookie system
}
// Create the Civic Auth instance
const storage = new YourStorageAdapter();
const civicAuth = new CivicAuth(storage, config);
框架实例
Citizen Auth SDK包括了包括Express,Fastify,和Hono在内的流行服务器框架的例子.
快捷示例
import express from 'express';
import cookieParser from 'cookie-parser';
import { CookieStorage, CivicAuth } from '@civic/auth/server';
// Extend Express Request to include civicAuth instance
declare global {
namespace Express {
interface Request {
storage: ExpressCookieStorage;
civicAuth: CivicAuth;
}
}
}
const config: AuthConfig = {
clientId: process.env.CLIENT_ID!,
clientSecret: process.env.CLIENT_SECRET, // Optional - for confidential clients only
redirectUrl: `https://<your server>/auth/callback`,
postLogoutRedirectUrl: `https://<your server>/auth/logoutcallback`,
};
const app = express();
app.use(cookieParser());
// Create middleware to attach CivicAuth to each request
app.use((req, res, next) => {
const storage = new ExpressCookieStorage(req, res);
req.storage = storage;
req.civicAuth = new CivicAuth(storage, config);
next();
});
// Protected route example
app.get('/admin/profile', async (req, res) => {
if (!(await req.civicAuth.isLoggedIn())) {
return res.status(401).send('Unauthorized');
}
const user = await req.civicAuth.getUser();
res.send(`Hello, ${user?.name || user?.email || 'User'}`);
});
// Authentication route
app.get('/auth/login', async (req, res) => {
const url = await req.civicAuth.buildLoginUrl();
res.redirect(url.toString());
});
// Handle post-logout callback and clear session
app.get('/auth/logoutcallback', async (req: Request, res: Response) => {
const { state } = req.query as { state: string };
console.log(`Logout-callback: state=${state}`);
await req.civicAuth.clearTokens();
res.redirect('/');
});
可用方法
CivilAuth 接口提供了以下方法:
| 方法 | 说明 |
|---|---|
getUser() | 获得经认证的用户的符号验证 |
getTokens() | 获得带有符号验证的认证符 |
resolveOAuthAccessCode(code, state) | 解析 OAuth 访问代码到一组 OIDC 令牌 |
isLoggedIn() | 检查用户是否正在登录 |
buildLoginUrl(options?) | 建立登录 URL 以引导用户 |
buildLogoutRedirectUrl(options?) | 构建一个登录 URL 以引导用户 |
handleDeepLinking(requestUrl, originUrl, method) | 存储当前用于登录后重定向的 URL( 仅限 GET 请求) |
handleCallback() | 处理 OAuth 回调并重定向到存储的深链接 |
refreshTokens() | 刷新当前 IDC 令牌集 |
clearTokens() | 从存储中清除所有认证符 |
每种方法均被设计在服务器侧上下文中使用,包括适当验证令牌以确保安全.
服务器框架的深度链接
深层链接可以让用户在完成认证后被重定向回原目的地. 对于服务器框架(Express, Fastify, Hono等),您可以使用 handleDeepLinking 方法,以保留整个认证流的深层联系.
说明: 深度链接只为 GET 请求激活 。 POST,PUT,DELETE等HTTP方法被忽略了,因为它们代表的是程序动作而不是用户导航意图.
配置 :
在创建您的 CivilAuth 实例时, 您可以配置深链接的行为 :
const config = {
clientId: 'YOUR_CLIENT_ID',
redirectUrl: 'http://yoursite.com/auth/callback',
// ... other config
deepLinkConfig: 'fullUrl' // or 'queryParamsOnly' or 'disabled'
};
| 数值 | 说明 |
|---|---|
"fullUrl" (默认) | 保存包括路径和查询参数在内的完整 URL |
"queryParamsOnly" | 只保留查询参数, 重定向到根路径 |
"disabled" | 完全禁用深层链接 |
受保护路线的使用:
打电话 handleDeepLinking 在重定向未认证用户登录前 :
// Express example
app.use(async (req, res, next) => {
if (!(await req.civicAuth.isLoggedIn())) {
// Set up deep linking before redirecting to login
const requestUrl = `${req.protocol}://${req.get("host")}${req.originalUrl}`;
const originUrl = `${req.protocol}://${req.get("host")}`;
await req.civicAuth.handleDeepLinking(requestUrl, originUrl, req.method);
const loginUrl = await req.civicAuth.buildLoginUrl();
return res.redirect(loginUrl.toString());
}
next();
});
// Fastify example
fastify.addHook('preHandler', async (request, reply) => {
if (!(await request.civicAuth.isLoggedIn())) {
const protocol = request.headers["x-forwarded-proto"] || request.protocol || "http";
const host = request.headers.host || "localhost";
const requestUrl = `${protocol}://${host}${request.url}`;
const originUrl = `${protocol}://${host}`;
await request.civicAuth.handleDeepLinking(requestUrl, originUrl, request.method);
const loginUrl = await request.civicAuth.buildLoginUrl();
return reply.redirect(loginUrl.toString());
}
});
如何运作:
- 用户访问
/dashboard?tab=settings(未经认证) handleDeepLinking()在饼干中存储 URLbuildLoginUrl()将返回的 URL 编码为 OAuth 状态- 认证后,
handleCallback()重定向到原始 URL
服务器- Side 托肯验证
CivilAuth 界面在您使用时自动验证符号 getUser() 或者说 getTokens() 方法,为您的服务器侧认证逻辑提供多一层安全.
认证 存储和状态
Citizen Auth SDK维持了数个存储项来跟踪认证状态. 了解这些条目有助于调试和了解认证流. 这些令牌可以存储在cookie(服务器-侧使牌交换)或本地存储(客户-侧使牌交换)中,取决于您的配置.
存储条目
| 条目 | 目的 | 认证需要 | 页:1 |
|---|---|---|---|
id_token | 包含验证用户身份的ID 令牌 | 对 | 用于认证的主令牌 |
access_token | 包含 OAuth2 访问符 | 没有 | 可选自0.6.0版本 - 用于API访问 |
refresh_token | 过期时用来刷新符号 | 没有 | 存储为仅作为会话的条目,没有到期 |
oidc_session_expires_at | Oidc 会话过期时的音轨( 匹配 ID 令牌过期) | 没有 | 用于客户端符号刷新调度 |
认证要求
用户需要认证,SDK要求:
- 一个有效的
id_token将存在存储中 - ID 符号不能过期
托肯验证
SDK使用以下检查来验证符号 :
- 对照 OAuth 提供者的公用钥匙进行签名验证
- 过期时间验证
- 发行人验证
- 观众验证
- 根据您的申请要求追加的任择索赔审定
如果符号验证失败, 用户会被自动重定向为再认证 .