@civic/auth

中文文档
0.15.5发布于 2026/06/25TypeScriptESM + CJS近 30 天下载 5788
原始使用文档
文档目录36 节
  1. Quick Start
  2. npm
  3. yarn
  4. pnpm
  5. bun
  6. Integration
  7. Usage
  8. The User Button
  9. Getting User Information on the Frontend
  10. Advanced Configuration
  11. Display Mode
  12. Browser-Specific Support
  13. API
  14. User Context
  15. User
  16. Quick Start
  17. 1. Add the Civic Auth Plugin
  18. 2. Create an API Route
  19. 3. Middleware
  20. 4. Frontend Integration
  21. Usage
  22. Getting User Information on the Frontend
  23. Getting User Information on the Backend
  24. Advanced Configuration
  25. Deep Linking
  26. Client Secret Support
  27. Using the CivicAuth Interface
  28. Quick Start
  29. Framework Examples
  30. Available Methods
  31. Deep Linking for Server Frameworks
  32. Server-Side Token Validation
  33. Authentication Storage and State
  34. Storage Entries
  35. Authentication Requirements
  36. Token Validation

Civic Auth Client SDK

Civic Auth offers a simple, flexible, and fast way to integrate authentication into your applications.

You can find the full, official documentation here, with a quick-start version in this README.

Note: This package is only published in ESM format. No CJS build is available.

Quick Start

Sign up for Civic Auth in less than a minute at auth.civic.com to get your Client ID.

Install the library in your app using your installer of choice:

npm

npm install @civic/auth

yarn

yarn add @civic/auth

pnpm

pnpm install @civic/auth

bun

bun add @civic/auth

Integration

Choose your framework for instructions on how to integrate Civic Auth into your application.

For integrating in other environments using any OIDC or OAuth 2.0-compliant client libraries, see here.

React

Integrate Civic Auth into your React application with ease, just wrap your app with the Civic Auth provider and add your Client ID (provided after you sign up). A working example is available in our github examples repo.

import { CivicAuthProvider, UserButton } from "@civic/auth/react";

function App({ children }) {
  return (
    <CivicAuthProvider clientId="YOUR CLIENT ID">
      <UserButton />
      {children}
    </CivicAuthProvider>
  )
}

Usage

The User Button

The Civic Auth SDK comes with a multi-purpose styled component called the 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>
  )
}

This component is context-dependent. If the user is logged in, it will show their profile picture and name. If the user is not logged in, it will show a Log In button.

Getting User Information on the Frontend

Use the Civic Auth SDK to retrieve user information on the frontend.

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>
}

We use name as an example here, but you can call any user object property from the user fields schema, as shown below.

Advanced Configuration

Civic Auth is a "low-code" solution, so all configuration takes place via the dashboard. Changes you make there will be updated automatically in your integration without any code changes. The only required parameter you need to provide is the client ID.

The integration provides additional run-time settings and hooks that you can use to customize the library's integration with your own app. If you need any of these, you can add them to the CivicAuthProvider as follows:

<CivicAuthProvider
  clientId="YOUR CLIENT ID"
  ...other configuration
>

See below for the list of all configuration options

FieldRequiredDefaultExampleDescription
clientIdYes-2cc5633d-2c92-48da-86aa-449634f274b9The key obtained on signup to auth.civic.com
nonceNo-1234A single-use ID used during login, binding a login token with a given client. Needed in advanced authentication processes only
onSignInNo-

(error?: Error) => {
  if (error) { 
    // handle error
  } else {
    // handle successful login
  }
}
A hook that executes after a sign-in attempt, whether successful or not.
onSignOutNo-
() => {
  // handle signout
}
A hook that executes after a user logs out.
redirectUrlNocurrentURL/authenticatingAn override for the page that OAuth will redirect to to perform token-exchange. By default Civic will redirect to the current URL and Authentication will be finished by the Civic provider automatically. Only use if you'd like to have some custom display or logic during OAuth token-exchange. The redirect page must have the CivicAuthProvider running in order to finish authentication.

modalIframe

NotruemodalIframe={true}Set to true if you want to embed the login iframe in your app rather than opening the iframe in a modal. See Embedded Login Iframe section below.
autoRedirectNotrueautoRedirect={false}When enabled, automatically uses the 'redirect' mode for authentication in browsers that don't support iframe-based authentication (e.g., Safari with passkeys). Instead of users performing authentication in an iframe, the current page will load the login page and they user will be redirected back upon succesfull login completion.

Display Mode

The display mode indicates where the Civic login UI will be displayed. The following display modes are supported:

  • iframe (default): the UI loads in an iframe that shows in an overlay on top of the existing page content
  • redirect: the UI redirects the current URL to a Civic login screen, then redirects back to your site when login is complete
  • new_tab: the UI opens in a new tab or popup window (depending on browser preferences), and after login is complete, the tab or popup closes to return the user to your site

Browser-Specific Support

The Civic Auth SDK includes automatic browser detection to handle browser-specific limitations. Some browsers like Safari don't support creation of passkeys in 'iframe' mode. In cases like these we auto-initiate the 'redirect' flow so that your users have a seamless UX. The user sees a loader in place of the iframe, then the page redirects to show the login interface directly.

API

User Context

The full user context object (provided by useUser) looks like this:

{ 
  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&#x3C;void>;
  signOut: () => Promise&#x3C;void>;
}

User

The User object looks like this:

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;

Where you can pass extra user attributes to the object that you know will be present in user claims, e.g.

const UserWithNickName = User<{ nickname: string }>;

Field descriptions:

Base User Fields

Field
idThe user's unique ID with respect to your app. You can use this to look up the user in the dashboard.
emailThe user's email address
nameThe user's full name
given_nameThe user's given name
family_nameThe user's family name
updated_atThe time at which the user's profile was most recently updated.

Token Fields

Typically developers will not need to interact with the token fields, which are used only for advanced use cases.

Field
idTokenThe OIDC id token, used to request identity information about the user
accessTokenThe OAuth 2.0 access token, allowing a client to make API calls to Civic Auth on behalf of the user.
refreshTokenThe OAuth 2.0 refresh token, allowing a login session to be extended automatically without requiring user interaction.
The Civic Auth SDK handles refresh automatically, so you do not need to do this.
forwardedTokensIf the user authenticated using SSO (single-sign-on login) with a federated OAuth provider such as Google, this contains the OIDC and OAuth 2.0 tokens from that provider.

Forwarded Tokens

Use forwardedTokens if you need to make requests to the source provider, such as find out provider-specific information.


An example would be, if a user logged in via Google, using the Google forwarded token to query the Google Groups that the user is a member of.

For example:

const googleAccessToken = user.forwardedTokens?.google?.accessToken;

Embedded Login Iframe

If you want to have the Login screen open directly on a page without the user having to click on button, you can import the CivicAuthIframeContainer component and use it along with the AuthProvider option iframeMode={"embedded"}

You just need to ensure that the CivicAuthIframeContainer is a child under a 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>
  );
}

Next.JS

Quick Start

Integrate Civic Auth into your Next.js application using the following steps (a working example is available in our github examples repo):

1. Add the Civic Auth Plugin

This is where you give your app the Client ID provided when you sign up at auth.civic.com.

The defaults should work out of the box for most customers, but if you want to configure your app, see below for details.

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. Create an API Route

This is where your app will handle login and logout requests.

Create this file at the following path:

src/app/api/auth/[...civicauth]/route.ts

import { handler } from '@civic/auth/nextjs'

export const GET = handler()
export const POST = handler()

These steps apply to the App Router. If you are using the Pages Router, please contact us for integration steps.

3. Middleware

Middleware is used to protect your backend routes, server components and server actions from unauthenticated requests.

Using the Civic Auth middleware ensures that only logged-in users have access to secure parts of your service.

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).*)',
  ],
}

Note: If you have analytics proxy rewrites in your next.config.js (e.g., for Google Analytics, PostHog, or other tracking services), you should add those paths to the exclude configuration option. See Advanced Configuration for details.

Token Handling Behavior:

  • Valid tokens: User passes through to protected routes
  • Refresh token available: Automatically redirects to refresh endpoint to rehydrate session with targetUrl parameter
  • Expired tokens without refresh: Redirects to logout callback to clear bad tokens, then to login
  • No tokens: Redirects to login URL
  • Login URL access: Always allowed regardless of authentication state to prevent redirect loops

Middleware Chaining

If you are already using middleware in your Next.js app, then you can chain them with Civic Auth as follows:

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. Frontend Integration

Add the Civic Auth context to your app to give your frontend access to the logged-in user.

import { CivicAuthProvider } from "@civic/auth/nextjs";

function Layout({ children }) {
  return (
    // ... the rest of your app layout
    <CivicAuthProvider>
      {children}
    </CivicAuthProvider>
  )
}

Unlike the pure React integration, you do not have to add your client ID again here!

Usage

Getting User Information on the Frontend

Next.JS client components can use the Civic Auth React tools to obtain user information as well as display convenient login, and logout buttons. See the React Usage page for details.

Getting User Information on the Backend

Retrieve user information on backend code, such as in React Server Components, React Server Actions, or api routes using getUser:

import { getUser } from '@civic/auth/nextjs';

const user = await getUser();

For example, in a NextJS Server Component:

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>
}

The name property is used as an example here, check out the React Usage page to see the entire basic user object structure.

Advanced Configuration

Civic Auth is a "low-code" solution, so most of the configuration takes place via the dashboard. Changes you make there will be updated automatically in your integration without any code changes. The only required parameter you need to provide is the client ID.

The integration also offers the ability customize the library according to the needs of your Next.js app. For example, to restrict authentication checks to specific pages and routes in your app. You can do so inside next.config.js as follows:

const withCivicAuth = createCivicAuthPlugin({
  clientId: 'YOUR CLIENT ID',
  ...other config
});

export default withCivicAuth(nextConfig) // your next config here

Here are the available configuration options:

FieldRequiredDefaultExampleDescription
clientIdYes-2cc5633d-2c92-48da-86aa-449634f274b9The key obtained on signup to auth.civic.com
callbackUrlNo/api/auth/callback/api/myroute/callbackThe path to route the browser to after a succesful login. Set this value if you are hosting your civic auth API route somewhere other than the default recommended above.
loginUrlNo//adminThe path your user will be sent to if they access a resource that needs them to be logged in. If you have a dedicated login page, you can set it here.
logoutUrlNo//goodbyeThe path your user will be sent to after a successful log-out.
baseUrlNo-https://myapp.comThe public-facing base URL for apps deployed behind reverse proxies (e.g., Cloudfront + Vercel). When your app is behind a reverse proxy, the middleware may construct redirect URLs using internal origins instead of your public domain. Set this to ensure authentication redirects use the correct public URL.
autoRedirectNotrueautoRedirect: falseWhen enabled, automatically uses the 'redirect' mode for authentication in browsers that don't support iframe-based authentication (e.g., Safari with passkeys). Instead of users performing authentication in an iframe, the current page will load the login page and they user will be redirected back upon succesfull login completion.
deepLinkConfigNo"fullUrl""queryParamsOnly"Controls how deep links are preserved during authentication. See Deep Linking below.
includeNo['/*']

[

'/admin/*', '/api/admin/*'

]

An array of path globs that require a user to be logged-in to access. If not set, will include all paths matched by your Next.js middleware.
excludeNo-['/ga/**/*', '/gtm/**/*', '/ingest/**/*']An array of path globs that are excluded from the Civic Auth middleware. Important: If you have analytics proxy rewrites (e.g., for Google Analytics, GTM, or PostHog), add those paths here to prevent them from being captured as return URLs during authentication.

Deep Linking

Deep linking allows users to be redirected back to their original destination (including query parameters) after completing authentication. This is useful when users access deep links like /dashboard?tab=settings while unauthenticated.

Configuration Options:

ValueDescription
"fullUrl" (default)Preserves the full URL including path and query parameters
"queryParamsOnly"Preserves only query parameters, redirects to root path
"disabled"Disables deep linking entirely

Example:

const withCivicAuth = createCivicAuthPlugin({
  clientId: 'YOUR CLIENT ID',
  deepLinkConfig: 'fullUrl' // or 'queryParamsOnly' or 'disabled'
});

How it works:

  1. User visits /dashboard?tab=settings (unauthenticated)
  2. Middleware stores the URL in a cookie and redirects to login
  3. After successful authentication, user is redirected back to /dashboard?tab=settings

This is handled automatically by the Civic Auth middleware - no additional code required.

Server Integration

Client Secret Support

Civic Auth supports OAuth 2.0 client secrets for confidential clients (server-side applications). Client secrets are optional and provide enhanced security for backend services.

When to use client secrets:

  • Server-side applications where the secret can be stored securely
  • Backend services that need to authenticate without user interaction
  • Legacy systems that don't support PKCE

When NOT to use client secrets:

  • Browser-based SPAs (use PKCE instead)
  • Mobile applications (use PKCE instead)
  • Any environment where the secret could be exposed

To generate a client secret, visit the Civic Auth dashboard.

Using the CivicAuth Interface

For server-side integration, you can use the new unified CivicAuth interface which provides a full set of authentication methods with built-in token validation.

Quick Start

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);

Framework Examples

The Civic Auth SDK includes examples for popular server frameworks including Express, Fastify, and Hono.

Express Example

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('/');
});

Available Methods

The CivicAuth interface provides the following methods:

MethodDescription
getUser()Gets the authenticated user with token validation
getTokens()Gets the authentication tokens with token validation
resolveOAuthAccessCode(code, state)Resolves an OAuth access code to a set of OIDC tokens
isLoggedIn()Checks if the user is currently logged in
buildLoginUrl(options?)Builds a login URL to redirect the user to
buildLogoutRedirectUrl(options?)Builds a logout URL to redirect the user to
handleDeepLinking(requestUrl, originUrl, method)Stores the current URL for post-login redirect (GET requests only)
handleCallback()Handles OAuth callback and redirects to stored deep link
refreshTokens()Refreshes the current set of OIDC tokens
clearTokens()Clears all authentication tokens from storage

Each method is designed to be used in a server-side context and includes proper validation of tokens to ensure security.

Deep Linking for Server Frameworks

Deep linking allows users to be redirected back to their original destination after completing authentication. For server frameworks (Express, Fastify, Hono, etc.), you can use the handleDeepLinking method to preserve deep links across the authentication flow.

Note: Deep linking only activates for GET requests. POST, PUT, DELETE, and other HTTP methods are ignored because they represent programmatic actions rather than user navigation intent.

Configuration:

When creating your CivicAuth instance, you can configure deep linking behavior:

const config = {
  clientId: 'YOUR_CLIENT_ID',
  redirectUrl: 'http://yoursite.com/auth/callback',
  // ... other config
  deepLinkConfig: 'fullUrl' // or 'queryParamsOnly' or 'disabled'
};
ValueDescription
"fullUrl" (default)Preserves the full URL including path and query parameters
"queryParamsOnly"Preserves only query parameters, redirects to root path
"disabled"Disables deep linking entirely

Usage in Protected Routes:

Call handleDeepLinking before redirecting unauthenticated users to login:

// 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());
  }
});

How it works:

  1. User visits /dashboard?tab=settings (unauthenticated)
  2. handleDeepLinking() stores the URL in a cookie
  3. buildLoginUrl() encodes the return URL into OAuth state
  4. After authentication, handleCallback() redirects to the original URL

Server-Side Token Validation

The CivicAuth interface automatically validates tokens for you when using getUser() or getTokens() methods, providing an extra layer of security for your server-side authentication logic.

Authentication Storage and State

Civic Auth SDK maintains several storage entries to track authentication state. Understanding these entries is helpful for debugging and understanding the authentication flow. These tokens can be stored either in cookies (server-side token exchange) or in local storage (client-side token exchange) depending on your configuration.

Storage Entries

EntryPurposeRequired for AuthenticationNotes
id_tokenContains the ID token that verifies the user's identityYesPrimary token used for authentication
access_tokenContains the OAuth2 access tokenNoOptional as of version 0.6.0 - used for API access
refresh_tokenUsed to refresh tokens when they expireNoStored as a session-only entry with no expiry
oidc_session_expires_atTracks when the oidc session expires (matches ID token expiry)NoUsed for client-side token refresh scheduling

Authentication Requirements

For a user to be considered authenticated, the SDK requires:

  1. A valid id_token to be present in storage
  2. The ID token must not be expired

Token Validation

The SDK validates tokens using the following checks:

  • Signature verification against the OAuth provider's public keys
  • Expiration time validation
  • Issuer validation
  • Audience validation
  • Additional optional claim validations based on your application's requirements

If token validation fails, the user will be automatically redirected to re-authenticate.

版本与发布记录

@civic/auth 共发布 281 个版本,首次发布于 2024/10/22;过去 12 个月发布了 44 个版本。

版本发布日期距今
0.15.5latest2026/06/254 个月前
0.15.42026/06/194 个月前
0.15.32026/04/246 个月前
0.15.3-beta.0beta2026/04/236 个月前
0.15.22026/04/017 个月前
0.15.12026/03/048 个月前

其他发布通道:test → 0.5.1-beta.1,alpha → 0.11.3-alpha.1,beta → 0.15.3-beta.0。

关于 @civic/auth 的常见问题

@civic/auth 是什么?

Civic Auth Client SDK - Quick Start - npm - yarn - pnpm - bun - Integration - React - Usage - [The User Button](#th

如何安装 @civic/auth?

在项目目录运行 npm install @civic/auth,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=18)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@civic/auth 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@civic/auth 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@civic/auth 可以商用吗?

@civic/auth 使用 未声明 许可。package.json 没有声明许可证。没有许可证的代码默认保留全部权利,商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括,不构成法律意见,请以许可原文为准。

@civic/auth 的下载量有多少?

根据 npm 官方下载统计,@civic/auth 在 2026/10/10 – 2026/11/08 这 30 天内被下载 5,788 次,日均约 193 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@civic/auth 还在维护吗?

最新版本 0.15.5 发布于 2026/06/25(4 个月前);至今共发布 281 个版本,其中过去 12 个月发布了 44 个;首次发布于 2024/10/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。