rohitg00/awesome-claude-code-toolkit

authentication-patterns

Authentication and authorization patterns including OAuth2, JWT, RBAC, session management, and PKCE flows

First seen Feb 11, 2026

Installation

$ npx skills add rohitg00/awesome-claude-code-toolkit --skill authentication-patterns

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from rohitg00/awesome-claude-code-toolkit · top by installs.

npx skills add rohitg00/awesome-claude-code-toolkit

Browse all from rohitg00/awesome-claude-code-toolkit

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 2.6K
License LICENSE
Default branch main
Open issues 17
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,558 B
  • docs SUMMARY.md 136 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 173 installs

SKILL.md

Authentication Patterns

JWT Access and Refresh Tokens

import jwt from "jsonwebtoken";

interface TokenPayload {
  sub: string;
  email: string;
  roles: string[];
}

function generateTokens(user: User) {
  const accessToken = jwt.sign(
    { sub: user.id, email: user.email, roles: user.roles },
    process.env.JWT_SECRET!,
    { expiresIn: "15m", issuer: "auth-service" }
  );

  const refreshToken = jwt.sign(
    { sub: user.id, tokenVersion: user.tokenVersion },
    process.env.REFRESH_SECRET!,
    { expiresIn: "7d", issuer: "auth-service" }
  );

  return { accessToken, refreshToken };
}

function verifyAccessToken(token: string): TokenPayload {
  return jwt.verify(token, process.env.JWT_SECRET!, {
    issuer: "auth-service",
  }) as TokenPayload;
}

Short-lived access tokens (15 minutes) with longer-lived refresh tokens (7 days). Store refresh tokens in HTTP-only cookies.

Auth Middleware

function authenticate(req: Request, res: Response, next: NextFunction) {
  const header = req.headers.authorization;
  if (!header?.startsWith("Bearer ")) {
    return res.status(401).json({ error: "Missing authorization header" });
  }

  try {
    const payload = verifyAccessToken(header.slice(7));
    req.user = payload;
    next();
  } catch (error) {
    if (error instanceof jwt.TokenExpiredError) {
      return res.status(401).json({ error: "Token expired" });
    }
    return res.status(401).json({ error: "Invalid token" });
  }
}

function authorize(...roles: string[]) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.user) return res.status(401).json({ error: "Not authenticated" });
    if (!roles.some(role => req.user.roles.includes(role))) {
      return res.status(403).json({ error: "Insufficient permissions" });
    }
    next();
  };
}

app.get("/admin/users", authenticate, authorize("admin"), listUsers);

OAuth2 Authorization Code Flow with PKCE

import crypto from "crypto";

function generatePKCE() {
  const verifier = crypto.randomBytes(32).toString("base64url");
  const challenge = crypto
    .createHash("sha256")
    .update(verifier)
    .digest("base64url");
  return { verifier, challenge };
}

app.get("/auth/login", (req, res) => {
  const { verifier, challenge } = generatePKCE();
  req.session.codeVerifier = verifier;

  const params = new URLSearchParams({
    response_type: "code",
    client_id: process.env.OAUTH_CLIENT_ID!,
    redirect_uri: `${process.env.APP_URL}/auth/callback`,
    scope: "openid profile email",
    code_challenge: challenge,
    code_challenge_method: "S256",
    state: crypto.randomBytes(16).toString("hex"),
  });

  res.redirect(`${process.env.OAUTH_AUTHORIZE_URL}?${params}`);
});

app.get("/auth/callback", async (req, res) => {
  const { code } = req.query;

  const tokenResponse = await fetch(process.env.OAUTH_TOKEN_URL!, {
    method: "POST",
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: new URLSearchParams({
      grant_type: "authorization_code",
      code: code as string,
      redirect_uri: `${process.env.APP_URL}/auth/callback`,
      client_id: process.env.OAUTH_CLIENT_ID!,
      code_verifier: req.session.codeVerifier,
    }),
  });

  const tokens = await tokenResponse.json();
  const userInfo = jwt.decode(tokens.id_token);

  req.session.user = { id: userInfo.sub, email: userInfo.email };
  res.redirect("/dashboard");
});

RBAC Model

interface Permission {
  resource: string;
  action: "create" | "read" | "update" | "delete";
}

const ROLE_PERMISSIONS: Record<string, Permission[]> = {
  viewer: [
    { resource: "posts", action: "read" },
    { resource: "comments", action: "read" },
  ],
  editor: [
    { resource: "posts", action: "create" },
    { resource: "posts", action: "read" },
    { resource: "posts", action: "update" },
    { resource: "comments", action: "create" },
    { resource: "comments", action: "read" },
  ],
  admin: [
    { resource: "*", action: "create" },
    { resource: "*", action: "read" },
    { resource: "*", action: "update" },
    { resource: "*", action: "delete" },
  ],
};

function hasPermission(roles: string[], resource: string, action: string): boolean {
  return roles.some(role =>
    ROLE_PERMISSIONS[role]?.some(
      p => (p.resource === resource || p.resource === "*") && p.action === action
    )
  );
}

Anti-Patterns

  • Storing JWTs in localStorage (vulnerable to XSS; use HTTP-only cookies)
  • Using symmetric secrets for JWTs across multiple services (use RS256 with key pairs)
  • Not validating iss, aud, and exp claims on token verification
  • Implementing custom password hashing instead of using bcrypt/argon2
  • Missing CSRF protection on cookie-based authentication
  • Returning different error messages for "user not found" vs "wrong password" (user enumeration)

Checklist

  • Access tokens are short-lived (15 minutes or less)
  • Refresh tokens stored in HTTP-only, Secure, SameSite cookies
  • Passwords hashed with bcrypt or argon2 (never MD5/SHA)
  • OAuth2 PKCE flow used for public clients
  • RBAC permissions checked at both route and data access layers
  • Token revocation supported via version counter or blocklist
  • CSRF protection enabled for cookie-based auth
  • Authentication errors do not reveal whether the user exists