Token导航 LogoToken导航TokenDH.com
研究检索敏感数据github未标认证来源可访问clear审计通过

clerk-authentication职员认证

Agent Skill

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

总安装

5,784

周安装

241

GitHub Stars

87

下载量

1,928
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:clerk-authentication(职员认证)
来源仓库:https://github.com/mindrally/skills
仓库路径:skills/clerk-authentication
安装命令:
npx skills add https://github.com/mindrally/skills --skill clerk-authentication
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/mindrally/skills --skill clerk-authentication

简介

Next.js 应用中 Clerk 认证的专家级集成方案,强调多层防御与细粒度保护。

  • 覆盖安装配置、环境变量设置、服务器动作保护与内置安全特性启用。
  • 推荐使用 HttpOnly cookies 存储会话,并在每个数据访问点验证身份。
  • 必须设置 NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY 与 CLERK_SECRET_KEY 环境变量。
  • clerk-authentication 属于研究检索类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Clerk Authentication

You are an expert in Clerk authentication implementation for Next.js applications. Follow these guidelines when integrating Clerk.

Core Principles

  • Implement defense-in-depth with multiple authentication layers
  • Verify authentication at every data access point, not just middleware
  • Protect server actions individually
  • Use Clerk's built-in security features (HttpOnly cookies, CSRF protection)

Installation and Setup

npm install @clerk/nextjs

Environment Variables

# Required
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...

# Optional: Custom URLs
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/dashboard
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/dashboard

Provider Setup

App Router (app/layout.tsx)

import { ClerkProvider } from '@clerk/nextjs';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <ClerkProvider>
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  );
}

With Custom Appearance

import { ClerkProvider } from '@clerk/nextjs';
import { dark } from '@clerk/themes';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <ClerkProvider
      appearance={{
        baseTheme: dark,
        variables: {
          colorPrimary: '#3b82f6',
        },
        elements: {
          formButtonPrimary: 'bg-blue-500 hover:bg-blue-600',
        },
      }}
    >
      <html lang="en">
        <body>{children}</body>
      </html>
    </ClerkProvider>
  );
}

Middleware Configuration

Basic Middleware (middleware.ts)

import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

// Define protected routes
const isProtectedRoute = createRouteMatcher([
  '/dashboard(.*)',
  '/api/protected(.*)',
  '/settings(.*)',
]);

// Define public routes (optional, for clarity)
const isPublicRoute = createRouteMatcher([
  '/',
  '/sign-in(.*)',
  '/sign-up(.*)',
  '/api/public(.*)',
]);

export default clerkMiddleware(async (auth, req) => {
  if (isProtectedRoute(req)) {
    await auth.protect();
  }
});

export const config = {
  matcher: [
    // Skip Next.js internals and static files
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    // Always run for API routes
    '/(api|trpc)(.*)',
  ],
};

Advanced Middleware with Role-Based Access

import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';

const isAdminRoute = createRouteMatcher(['/admin(.*)']);
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)', '/api/protected(.*)']);

export default clerkMiddleware(async (auth, req) => {
  const { userId, sessionClaims } = await auth();

  // Admin routes require admin role
  if (isAdminRoute(req)) {
    if (!userId || sessionClaims?.metadata?.role !== 'admin') {
      return new Response('Forbidden', { status: 403 });
    }
  }

  // Protected routes require authentication
  if (isProtectedRoute(req)) {
    await auth.protect();
  }
});

Authentication in Server Components

Using auth()

import { auth } from '@clerk/nextjs/server';

export default async function DashboardPage() {
  const { userId } = await auth();

  if (!userId) {
    redirect('/sign-in');
  }

  // Fetch user-specific data
  const data = await fetchUserData(userId);

  return <Dashboard data={data} />;
}

Using currentUser()

import { currentUser } from '@clerk/nextjs/server';

export default async function ProfilePage() {
  const user = await currentUser();

  if (!user) {
    redirect('/sign-in');
  }

  return (
    <div>
      <h1>Welcome, {user.firstName}!</h1>
      <p>Email: {user.emailAddresses[0]?.emailAddress}</p>
    </div>
  );
}

Authentication in Client Components

useUser Hook

'use client';

import { useUser } from '@clerk/nextjs';

export function UserProfile() {
  const { isLoaded, isSignedIn, user } = useUser();

  if (!isLoaded) {
    return <Skeleton />;
  }

  if (!isSignedIn) {
    return <SignInPrompt />;
  }

  return (
    <div>
      <img src={user.imageUrl} alt={user.fullName ?? 'User'} />
      <p>{user.fullName}</p>
    </div>
  );
}

useAuth Hook

'use client';

import { useAuth } from '@clerk/nextjs';

export function ProtectedAction() {
  const { isLoaded, userId, getToken } = useAuth();

  async function handleAction() {
    if (!userId) return;

    // Get a fresh token for API calls
    const token = await getToken();

    const response = await fetch('/api/protected', {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });
  }

  if (!isLoaded || !userId) {
    return null;
  }

  return <button onClick={handleAction}>Perform Action</button>;
}

Server Actions Protection

Always protect server actions individually:

'use server';

import { auth } from '@clerk/nextjs/server';

export async function createPost(formData: FormData) {
  const { userId } = await auth();

  if (!userId) {
    throw new Error('Unauthorized');
  }

  const title = formData.get('title') as string;
  const content = formData.get('content') as string;

  // Create post with user ID
  const post = await db.post.create({
    data: {
      title,
      content,
      authorId: userId,
    },
  });

  revalidatePath('/posts');
  return post;
}

With Role Validation

'use server';

import { auth } from '@clerk/nextjs/server';

export async function deleteUser(userId: string) {
  const { userId: currentUserId, sessionClaims } = await auth();

  if (!currentUserId) {
    throw new Error('Unauthorized');
  }

  if (sessionClaims?.metadata?.role !== 'admin') {
    throw new Error('Forbidden: Admin access required');
  }

  await db.user.delete({ where: { id: userId } });
  revalidatePath('/admin/users');
}

API Route Protection

Route Handlers (App Router)

import { auth } from '@clerk/nextjs/server';
import { NextResponse } from 'next/server';

export async function GET() {
  const { userId } = await auth();

  if (!userId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const data = await fetchUserData(userId);
  return NextResponse.json(data);
}

export async function POST(request: Request) {
  const { userId } = await auth();

  if (!userId) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const body = await request.json();
  // Process request...

  return NextResponse.json({ success: true });
}

JWT Verification for External APIs

import { auth } from '@clerk/nextjs/server';

export async function GET() {
  const { getToken } = await auth();

  // Get JWT for external API
  const token = await getToken({ template: 'external-api' });

  const response = await fetch('https://external-api.com/data', {
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  return Response.json(await response.json());
}

Organization Support

import { auth } from '@clerk/nextjs/server';

export async function getOrganizationData() {
  const { userId, orgId, orgRole } = await auth();

  if (!userId || !orgId) {
    throw new Error('Must be in an organization');
  }

  // Check organization role
  if (orgRole !== 'org:admin') {
    throw new Error('Admin access required');
  }

  return await db.organization.findUnique({
    where: { clerkOrgId: orgId },
  });
}

Custom Session Claims

Configure in Clerk Dashboard

Add custom claims via JWT Templates, then access them:

import { auth } from '@clerk/nextjs/server';

export async function checkSubscription() {
  const { sessionClaims } = await auth();

  const plan = sessionClaims?.metadata?.subscriptionPlan;

  if (plan !== 'pro') {
    throw new Error('Pro subscription required');
  }
}

UI Components

Pre-built Components

import {
  SignIn,
  SignUp,
  SignOutButton,
  UserButton,
  SignedIn,
  SignedOut,
} from '@clerk/nextjs';

export function Header() {
  return (
    <header>
      <SignedIn>
        <UserButton afterSignOutUrl="/" />
      </SignedIn>
      <SignedOut>
        <SignInButton mode="modal" />
      </SignedOut>
    </header>
  );
}

// Dedicated sign-in page
export default function SignInPage() {
  return (
    <div className="flex justify-center items-center min-h-screen">
      <SignIn />
    </div>
  );
}

Security Best Practices

1. Defense in Depth

// Layer 1: Middleware
export default clerkMiddleware(async (auth, req) => {
  if (isProtectedRoute(req)) {
    await auth.protect();
  }
});

// Layer 2: Server Component
export default async function Page() {
  const { userId } = await auth();
  if (!userId) redirect('/sign-in');
  // ...
}

// Layer 3: Data Access
async function fetchUserData(userId: string) {
  const { userId: currentUserId } = await auth();
  if (currentUserId !== userId) throw new Error('Forbidden');
  // ...
}

2. Protect All Server Actions

// Every server action should verify auth independently
'use server';

export async function sensitiveAction() {
  const { userId } = await auth();
  if (!userId) throw new Error('Unauthorized');
  // ...
}

3. Avoid Client-Side Only Protection

// BAD: Client-side only check
'use client';
export function SecretComponent() {
  const { isSignedIn } = useAuth();
  if (!isSignedIn) return null;
  return <div>Secret Data</div>; // Data still sent to client!
}

// GOOD: Server-side protection
export default async function SecretPage() {
  const { userId } = await auth();
  if (!userId) redirect('/sign-in');
  const data = await fetchSecretData(userId);
  return <SecretComponent data={data} />;
}

Error Handling

import { auth } from '@clerk/nextjs/server';
import { redirect } from 'next/navigation';

export default async function ProtectedPage() {
  try {
    const { userId } = await auth();

    if (!userId) {
      redirect('/sign-in');
    }

    const data = await fetchUserData(userId);
    return <Dashboard data={data} />;
  } catch (error) {
    if (error instanceof AuthenticationError) {
      redirect('/sign-in');
    }
    throw error;
  }
}

Testing

// Mock Clerk for testing
import { auth } from '@clerk/nextjs/server';

jest.mock('@clerk/nextjs/server', () => ({
  auth: jest.fn(),
}));

describe('Protected API', () => {
  it('returns 401 for unauthenticated requests', async () => {
    (auth as jest.Mock).mockResolvedValue({ userId: null });

    const response = await GET();
    expect(response.status).toBe(401);
  });

  it('returns data for authenticated requests', async () => {
    (auth as jest.Mock).mockResolvedValue({ userId: 'user_123' });

    const response = await GET();
    expect(response.status).toBe(200);
  });
});

Common Anti-Patterns to Avoid

  1. Relying solely on middleware for protection
  2. Not protecting server actions individually
  3. Using client-side auth checks for sensitive data
  4. Exposing user data without ownership verification
  5. Not validating organization membership for org-scoped resources
  6. Hardcoding role checks instead of using Clerk's RBAC
  7. Not handling loading states in client components

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

26.62%
按下载量换算513

OpenCode

24.38%
按下载量换算470

Antigravity

16.86%
按下载量换算325

Codex

12.83%
按下载量换算247

Gemini CLI

8.56%
按下载量换算165

github-copilot

3.86%
按下载量换算74

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills