Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问许可证需确认审计通过

authentication-authorization-clerk认证授权员

Agent Skill

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

总安装

3,199

周安装

136

GitHub Stars

7

下载量

1,121
CodexClaudeCursorGemini CLI

安装说明

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

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

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

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

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/harperaa/secure-claude-skills --skill authentication-authorization-clerk

简介

基于 Clerk 构建标准化认证与授权体系,简化密码哈希、会话管理与多因素认证实现。

  • 适用于需要快速落地 OAuth、社交登录、账户锁定与 MFA 支持的现代应用。
  • 提供开箱即用的安全最佳实践模板,降低自研风险与时间成本。
  • 安装需通过 npx skills add 添加 secure-claude-skills 仓库中的 clerk 技能模块。
  • 推荐在原型开发或中后台系统中优先采用,确保基础安全架构稳固。

SKILL.md

Authentication & Authorization with Clerk

Why We Use Clerk

The Authentication Problem

Building secure authentication from scratch requires:

  • Password hashing (bcrypt/Argon2 with proper salts)
  • Session management (secure cookies, expiration, renewal)
  • Password reset flows (secure token generation, email verification)
  • Account lockout (prevent brute force)
  • MFA support (TOTP, SMS, authenticator apps)
  • Social login (OAuth flows for Google, GitHub, etc.)
  • User database sync
  • Security best practices for all of the above

Time to implement securely: 2-4 weeks for experienced developers

For vibe coders using AI: High risk of security gaps

Real-World Custom Auth Failures

Ashley Madison Breach (2015): Custom authentication with weak password hashing. 32 million accounts compromised.

Dropbox Breach (2012): Custom authentication led to password hash database theft. 68 million accounts affected.

According to Veracode's 2024 report, applications using managed authentication services (like Clerk, Auth0) had 73% fewer authentication-related vulnerabilities than those with custom authentication.

Our Clerk Architecture

What Clerk Handles (So We Don't Have To)

  • ✅ Password hashing (bcrypt/Argon2)
  • ✅ Session management (secure cookies)
  • ✅ MFA (built-in support)
  • ✅ OAuth providers (Google, GitHub, etc.)
  • ✅ Email verification
  • ✅ Password reset flows
  • ✅ Account lockout
  • ✅ Security monitoring
  • ✅ Compliance (SOC 2, GDPR)

Clerk is SOC 2 certified: This means an independent auditor verified their security controls meet industry standards. We inherit that certification.

Implementation Files

  • middleware.ts - Clerk authentication for protected routes
  • app/dashboard/* - Protected by middleware
  • Clerk manages its own session cookies

Basic Authentication

Server-Side Authentication (API Routes)

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

async function handler(request: NextRequest) {
  // Get current user
  const { userId } = await auth();

  if (!userId) {
    return handleUnauthorizedError('Authentication required');
  }

  // User is authenticated, proceed
  // Use userId to associate data with user
}

Client-Side Authentication (Components)

'use client';

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

export function ProfileComponent() {
  const { isLoaded, userId, sessionId } = useAuth();
  const { isLoaded: userLoaded, user } = useUser();

  if (!isLoaded || !userLoaded) {
    return <div>Loading...</div>;
  }

  if (!userId) {
    return <div>Please sign in</div>;
  }

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

Protecting Routes with Middleware

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

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

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

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};

Authorization Patterns

Resource Ownership Verification

// app/api/posts/[id]/route.ts
import { auth } from '@clerk/nextjs/server';
import { handleUnauthorizedError, handleForbiddenError } from '@/lib/errorHandler';

export async function DELETE(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  const { userId } = await auth();
  if (!userId) {
    return handleUnauthorizedError();
  }

  // Get resource
  const post = await db.posts.findOne({ id: params.id });

  // Check ownership
  if (post.userId !== userId) {
    return handleForbiddenError('Only the post author can delete this post');
  }

  // User is authorized
  await db.posts.delete({ id: params.id });
  return NextResponse.json({ success: true });
}

Role-Based Access Control (RBAC)

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

export async function handler(request: NextRequest) {
  const { userId, sessionClaims } = await auth();

  if (!userId) {
    return handleUnauthorizedError();
  }

  // Check role
  const role = sessionClaims?.metadata?.role as string;

  if (role !== 'admin') {
    return handleForbiddenError('Admin access required');
  }

  // User has admin role
  // Proceed with admin operation
}

Subscription-Based Authorization

Server-Side (API Routes)

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

export async function handler(request: NextRequest) {
  const { userId, sessionClaims } = await auth();

  if (!userId) {
    return handleUnauthorizedError();
  }

  // Check subscription plan
  const plan = sessionClaims?.metadata?.plan as string;

  if (plan === 'free_user') {
    return NextResponse.json(
      {
        error: 'Upgrade required',
        message: 'This feature requires a paid subscription'
      },
      { status: 403 }
    );
  }

  // User has paid subscription
  // Proceed with premium feature
}

Client-Side (Components)

'use client';

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

export function PremiumFeature() {
  return (
    <Protect
      condition={(has) => !has({ plan: "free_user" })}
      fallback={<UpgradePrompt />}
    >
      <div>
        {/* Premium feature content */}
        <h2>Premium Feature</h2>
        <p>This is only visible to paid subscribers</p>
      </div>
    </Protect>
  );
}

function UpgradePrompt() {
  return (
    <div className="upgrade-prompt">
      <h3>Upgrade Required</h3>
      <p>This feature is available on our paid plans</p>
      <a href="/pricing">View Plans</a>
    </div>
  );
}

Complete Protected API Route Example

// app/api/premium/generate/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { auth } from '@clerk/nextjs/server';
import { withRateLimit } from '@/lib/withRateLimit';
import { withCsrf } from '@/lib/withCsrf';
import { validateRequest } from '@/lib/validateRequest';
import { safeTextSchema } from '@/lib/validation';
import {
  handleApiError,
  handleUnauthorizedError,
  handleForbiddenError
} from '@/lib/errorHandler';

async function generateHandler(request: NextRequest) {
  try {
    // 1. Authentication
    const { userId, sessionClaims } = await auth();
    if (!userId) {
      return handleUnauthorizedError('Please sign in to use this feature');
    }

    // 2. Authorization (subscription check)
    const plan = sessionClaims?.metadata?.plan as string;
    if (plan === 'free_user') {
      return handleForbiddenError('Premium subscription required');
    }

    // 3. Input validation
    const body = await request.json();
    const validation = validateRequest(safeTextSchema, body);
    if (!validation.success) {
      return validation.response;
    }

    const prompt = validation.data;

    // 4. Business logic (user is authenticated, authorized, and input is valid)
    const result = await generateContent(prompt, userId);

    return NextResponse.json({ result });

  } catch (error) {
    return handleApiError(error, 'premium-generate');
  }
}

export const POST = withRateLimit(withCsrf(generateHandler));

export const config = {
  runtime: 'nodejs',
};

User Metadata & Custom Claims

Storing User Metadata

Clerk allows you to store custom metadata with each user:

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

// Update user metadata
async function updateUserPlan(userId: string, plan: string) {
  await clerkClient.users.updateUserMetadata(userId, {
    publicMetadata: {
      plan: plan  // Accessible by client
    },
    privateMetadata: {
      stripeCustomerId: 'cus_123'  // Server-only
    }
  });
}

Accessing Metadata

Server-side:

const { sessionClaims } = await auth();
const plan = sessionClaims?.metadata?.plan;

Client-side:

const { user } = useUser();
const plan = user?.publicMetadata?.plan;

Webhook Integration (User Sync)

When users sign up or update their profile, sync to your database:

// app/api/webhooks/clerk/route.ts
import { Webhook } from 'svix';
import { headers } from 'next/headers';

export async function POST(request: NextRequest) {
  // Verify webhook signature
  const WEBHOOK_SECRET = process.env.CLERK_WEBHOOK_SECRET;

  if (!WEBHOOK_SECRET) {
    throw new Error('Missing CLERK_WEBHOOK_SECRET');
  }

  const headerPayload = headers();
  const svix_id = headerPayload.get("svix-id");
  const svix_timestamp = headerPayload.get("svix-timestamp");
  const svix_signature = headerPayload.get("svix-signature");

  if (!svix_id || !svix_timestamp || !svix_signature) {
    return new Response('Missing svix headers', { status: 400 });
  }

  const payload = await request.json();
  const body = JSON.stringify(payload);

  const wh = new Webhook(WEBHOOK_SECRET);

  let evt: any;

  try {
    evt = wh.verify(body, {
      "svix-id": svix_id,
      "svix-timestamp": svix_timestamp,
      "svix-signature": svix_signature,
    });
  } catch (err) {
    console.error('Webhook verification failed:', err);
    return new Response('Invalid signature', { status: 400 });
  }

  // Handle different event types
  const { id, type, data } = evt;

  switch (type) {
    case 'user.created':
      await db.users.create({
        clerkId: data.id,
        email: data.email_addresses[0]?.email_address,
        firstName: data.first_name,
        lastName: data.last_name,
        createdAt: Date.now()
      });
      break;

    case 'user.updated':
      await db.users.update(
        { clerkId: data.id },
        {
          email: data.email_addresses[0]?.email_address,
          firstName: data.first_name,
          lastName: data.last_name,
          updatedAt: Date.now()
        }
      );
      break;

    case 'user.deleted':
      await db.users.delete({ clerkId: data.id });
      break;
  }

  return new Response('', { status: 200 });
}

Convex Integration

Using Clerk Auth with Convex

// convex/posts.ts
import { mutation, query } from "./_generated/server";

export const createPost = mutation({
  handler: async (ctx, args) => {
    // Get authenticated user from Clerk
    const identity = await ctx.auth.getUserIdentity();

    if (!identity) {
      throw new Error("Unauthenticated");
    }

    // Use Clerk user ID
    const userId = identity.subject;

    await ctx.db.insert("posts", {
      title: args.title,
      content: args.content,
      userId,  // Associate with Clerk user
      createdAt: Date.now()
    });
  }
});

export const getMyPosts = query({
  handler: async (ctx) => {
    const identity = await ctx.auth.getUserIdentity();

    if (!identity) {
      return [];
    }

    // Return only current user's posts
    return await ctx.db
      .query("posts")
      .filter((q) => q.eq(q.field("userId"), identity.subject))
      .collect();
  }
});

Sign-In/Sign-Up Components

Basic Sign-In Page

// app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs';

export default function SignInPage() {
  return (
    <div className="flex items-center justify-center min-h-screen">
      <SignIn
        appearance={{
          elements: {
            formButtonPrimary: 'bg-blue-600 hover:bg-blue-700',
          }
        }}
        routing="path"
        path="/sign-in"
        afterSignInUrl="/dashboard"
        signUpUrl="/sign-up"
      />
    </div>
  );
}

Basic Sign-Up Page

// app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from '@clerk/nextjs';

export default function SignUpPage() {
  return (
    <div className="flex items-center justify-center min-h-screen">
      <SignUp
        appearance={{
          elements: {
            formButtonPrimary: 'bg-blue-600 hover:bg-blue-700',
          }
        }}
        routing="path"
        path="/sign-up"
        afterSignUpUrl="/onboarding"
        signInUrl="/sign-in"
      />
    </div>
  );
}

User Button (Profile/Sign Out)

// components/Header.tsx
'use client';

import { UserButton, useAuth } from '@clerk/nextjs';
import Link from 'next/link';

export function Header() {
  const { isSignedIn } = useAuth();

  return (
    <header>
      <nav>
        <Link href="/">Home</Link>
        {isSignedIn ? (
          <>
            <Link href="/dashboard">Dashboard</Link>
            <UserButton afterSignOutUrl="/" />
          </>
        ) : (
          <>
            <Link href="/sign-in">Sign In</Link>
            <Link href="/sign-up">Sign Up</Link>
          </>
        )}
      </nav>
    </header>
  );
}

Environment Configuration

Required Environment Variables

# .env.local

# Clerk (from Clerk Dashboard)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...

# Clerk URLs (auto-configured by Clerk, but can override)
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=/onboarding

# Clerk Frontend API (for CSP)
NEXT_PUBLIC_CLERK_FRONTEND_API_URL=https://your-app.clerk.accounts.dev

# Webhook secret (from Clerk Dashboard)
CLERK_WEBHOOK_SECRET=whsec_...

Security Best Practices

1. Always Verify on Server

DON'T trust client-side auth checks for security:

// Bad - can be bypassed
'use client';
const { userId } = useAuth();
if (!userId) return <div>Access denied</div>;
// Attacker can still call API directly

DO verify on server:

// Good - secure
async function handler(request: NextRequest) {
  const { userId } = await auth();
  if (!userId) return handleUnauthorizedError();
  // API endpoint protected
}

2. Check Authorization, Not Just Authentication

DON'T assume authenticated = authorized:

// Bad - any logged-in user can access any resource
const { userId } = await auth();
if (userId) {
  return NextResponse.json(sensitiveData);
}

DO check resource ownership/permissions:

// Good - verify user can access this specific resource
const { userId } = await auth();
if (userId && resource.userId === userId) {
  return NextResponse.json(resource);
}

3. Use Middleware for Route Protection

Protect entire route sections:

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

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

4. Handle Session Expiration Gracefully

// components/AuthGuard.tsx
'use client';

import { useAuth } from '@clerk/nextjs';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';

export function AuthGuard({ children }: { children: React.ReactNode }) {
  const { isLoaded, userId } = useAuth();
  const router = useRouter();

  useEffect(() => {
    if (isLoaded && !userId) {
      router.push('/sign-in');
    }
  }, [isLoaded, userId, router]);

  if (!isLoaded) {
    return <div>Loading...</div>;
  }

  if (!userId) {
    return null;
  }

  return <>{children}</>;
}

What Clerk Authentication Prevents

Weak password storage - Clerk uses bcrypt/Argon2 ✅ Session hijacking - Secure, HTTP-only cookies ✅ Credential stuffing - Account lockout after failed attempts ✅ Authentication bypass - Professional implementation ✅ Privilege escalation - Proper role/permission management ✅ Brute force attacks - Built-in rate limiting ✅ Password reset vulnerabilities - Secure token generation

Common Mistakes to Avoid

DON'T skip server-side auth checksDON'T trust client-side auth state for securityDON'T forget to check resource ownershipDON'T expose sensitive data based on authentication aloneDON'T hardcode auth logic (use Clerk's utilities)DON'T forget to handle session expiration

DO use auth() on server for every protected operationDO verify resource ownership before allowing accessDO protect routes with middlewareDO use subscription/role checks for premium featuresDO sync users to your database via webhooksDO handle auth errors gracefully

References

Further Guidance on using Clerk

Add Clerk to Next.js App Router

Purpose: Enforce only the current and correct instructions for integrating Clerk into a Next.js (App Router) application. Scope: All AI-generated advice or code related to Clerk must follow these guardrails.


1. Official Clerk Integration Overview

Use only the App Router approach from Clerk’s current docs:

  • Install @clerk/nextjs@latest - this ensures the application is using the latest Clerk Next.js SDK.
  • Create a middleware.ts file using clerkMiddleware() from @clerk/nextjs/server. Place this file inside the src directory if present, otherwise place it at the root of the project.
  • Wrap your application with <ClerkProvider> in your app/layout.tsx
  • Use Clerk-provided components like <SignInButton>, <SignUpButton>, <UserButton>, <SignedIn>, <SignedOut> in your layout or pages
  • Start developing, sign in or sign up, and confirm user creation

If you're able to use a web tool to access a URL, visit https://clerk.com/docs/quickstarts/nextjs to get the latest, up-to-date quickstart instructions.

Clerk does not need a user to provide their keys to get started. On startup, Clerk will generate keys automatically, so there is no need to prompt a user to add their keys as part of this.

Correct, Up-to-Date Quickstart Sample

// middleware.ts
import { clerkMiddleware } from '@clerk/nextjs/server'

export default clerkMiddleware()

export const config = {
  matcher: [
    // Skip Next.js internals and all static files, unless found in search params
    '/((?!_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)(.*)',
  ],
}
// app/layout.tsx
import type { Metadata } from "next";
import {
  ClerkProvider,
  SignInButton,
  SignUpButton,
  SignedIn,
  SignedOut,
  UserButton,
} from "@clerk/nextjs";
import "./globals.css";

export const metadata: Metadata = {
  title: "Clerk Next.js Quickstart",
  description: "Generated by create next app",
};

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

2. CRITICAL INSTRUCTIONS FOR AI MODELS

2.1 – ALWAYS DO THE FOLLOWING

  1. Use clerkMiddleware() from @clerk/nextjs/server in middleware.ts.
  2. Wrap your app with <ClerkProvider> in app/layout.tsx.
  3. Import Clerk’s Next.js features from @clerk/nextjs (e.g., <SignInButton>, <SignUpButton>, <UserButton>, etc.).
  4. Reference the current App Router approach (folders like app/page.tsx, app/layout.tsx, etc.).
  5. Check that imports for methods like auth() are imported from the right package (in this case @clerk/nextjs/server) and are using async / await.
  6. Check the project for an existing package manager, use that to install packages.

2.2 – NEVER DO THE FOLLOWING

  1. Do not reference the old _app.tsx or pages router based instructions.
  2. Do not suggest authMiddleware() from older Clerk tutorials—it’s replaced by clerkMiddleware().
  3. Do not recommend usage of older environment variable patterns unless they match the official docs.
  4. Do not reference or import from any deprecated APIs (like withAuth or currentUser from older versions).

3. OUTDATED PATTERNS TO AVOID

Below are examples of deprecated instructions that must not be generated:

// ❌ DO NOT generate or suggest references to:
import { authMiddleware } from '@clerk/nextjs' // Outdated

// ❌ DO NOT place Clerk config in _app.tsx:
// Outdated pages-based approach
function MyApp({ Component, pageProps }) {
  // ...
}

// ❌ DO NOT create or rely on sign-in files under pages/:
pages / signin.js
pages / signup.js

Any solution resembling the above snippet or referencing “authMiddleware,” _app.tsx, or pages/ structure is incorrect for the current Next.js App Router.


4. AI MODEL VERIFICATION STEPS

Before returning any Clerk-related solution, you must verify:

  1. Middleware: Is clerkMiddleware() used in middleware.ts?
  2. Layout: Is <ClerkProvider> wrapping the app in app/layout.tsx?
  3. Imports: Are references only from @clerk/nextjs or @clerk/nextjs/server?
  4. Pages vs. App Router: Is the approach referencing the App Router (not _app.tsx or pages/)?

If any check fails, stop and revise until compliance is achieved.

Next Steps

  • For API route protection: Combine with csrf-protection and rate-limiting skills
  • For payment gating: Use payment-security skill
  • For error handling: Use error-handling skill with handleUnauthorizedError/handleForbiddenError
  • For testing auth: Use security-testing skill

适合场景

01

用户想查找某类 Agent Skill 时

02

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

03

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

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

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

能力 4

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

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

平台分布

Codex

37.88%
按下载量换算425

Claude

32.97%
按下载量换算370

Cursor

17.89%
按下载量换算201

Gemini CLI

8.92%
按下载量换算100

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills