From generate-auth-apis
Generate complete JWT + OAuth2 authentication APIs from Prisma schema. Creates: register, login, logout, refresh token, SMS-based password reset, password-change, social-login (Google/Kakao/Naver), and user profile management. Supports NestJS, NodeJS (Express), and FastAPI frameworks. Trigger when: user wants to generate auth APIs, JWT authentication, OAuth2 social login, user registration/login system, or token refresh mechanism.
How this skill is triggered — by the user, by Claude, or both
Slash command
/generate-auth-apis:generate-auth-apisThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generates complete authentication API modules for **all auth-related models** in a Prisma schema — in one shot.
Generates complete authentication API modules for all auth-related models in a Prisma schema — in one shot.
Supported Frameworks:
Database Support:
The skill auto-detects the framework from the project structure:
| Indicator | Framework |
|---|---|
package.json with @nestjs/core | NestJS |
package.json with express or fastify | NodeJS (Express/Fastify) |
requirements.txt or pyproject.toml with fastapi | FastAPI |
Specify explicitly in the prompt:
generate auth APIs for NestJSgenerate auth APIs for Expressgenerate auth APIs for FastAPIgenerate auth APIs for FastifyRead {project}/back/prisma/schema.prisma and parse all models, focusing on:
Check project structure to determine framework:
package.json with NestJS/Express/Fastify dependenciesrequirements.txt or pyproject.toml with FastAPICheck existing API modules in the framework-appropriate location:
{project}/back/src/{project}/back/src/{project}/back/Generate framework-specific auth module:
NestJS:
{project}/back/src/auth/
├── auth.controller.ts
├── auth.service.ts
├── auth.module.ts
├── strategies/
│ ├── jwt.strategy.ts
│ └── jwt-refresh.strategy.ts
├── guards/
│ ├── jwt-auth.guard.ts
│ └── roles.guard.ts
├── dto/
│ ├── register.dto.ts
│ ├── login.dto.ts
│ ├── refresh-token.dto.ts
│ ├── change-password.dto.ts
│ ├── update-profile.dto.ts
│ ├── oauth-callback.dto.ts
│ ├── find-account.dto.ts
│ └── sms-verification.dto.ts
└── entities/
└── user.entity.ts
NodeJS (Express/Fastify):
{project}/back/src/auth/
├── auth.router.js # or .ts
├── auth.service.js # or .ts
├── middleware/
│ ├── jwt-auth.js
│ └── roles.js
└── validation/
└── auth.validation.js
FastAPI:
{project}/back/
├── routers/
│ └── auth.py
├── services/
│ └── auth.py
├── schemas/
│ └── auth.py
└── dependencies/
└── auth.py
Update the framework-specific entry point:
app.module.tsapp.js or index.jsmain.pyIf the schema lacks auth models, generate them automatically:
model User {
id String @id @default(uuid())
email String @unique
password String?
name String?
role String @default("user")
verified Boolean @default(false)
verifyToken String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
refreshTokens RefreshToken[]
socialAccounts SocialAccount[]
passwordResets PasswordReset[]
}
model RefreshToken {
id String @id @default(uuid())
token String @unique
userId String
expiresAt DateTime
revoked Boolean @default(false)
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
model SocialAccount {
id String @id @default(uuid())
provider String # google, kakao, naver
providerId String
userId String
accessToken String?
refreshToken String?
expiresAt DateTime?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerId])
}
model PasswordReset {
id String @id @default(uuid())
token String @unique
userId String
expiresAt DateTime
used Boolean @default(false)
createdAt DateTime @default(now())
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
Access Token (expires in 1 hour):
{
"sub": "user-uuid",
"email": "[email protected]",
"role": "user",
"iat": 1234567890,
"exp": 1234571490
}
Refresh Token (stored in DB, expires in 7 days):
{
"sub": "user-uuid",
"type": "refresh",
"iat": 1234567890,
"exp": 1235171490
}
Always use bcrypt with salt rounds of 12:
// TypeScript
const hashed = await bcrypt.hash(password, 12);
// Python
import bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(12))
1. GET /auth/sns/:provider → Redirect to provider auth URL
2. GET /auth/sns/:provider/callback → Code exchange → Access + Refresh tokens
3. POST /auth/refresh → Refresh access token
4. POST /auth/logout → Revoke refresh token
**SPA Frontend Note**: The callback endpoint `GET /auth/sns/:provider/callback` exchanges the code for tokens and immediately redirects to `{FRONTEND_URL}/auth/callback?accessToken=...&refreshToken=...&userId=...`. The frontend should listen on `/auth/callback` to capture these query parameters.
> ⚠️ **Important**: Ensure `FRONTEND_URL` is set in your `.env` file. If missing, the server falls back to `http://localhost:3000` (or whatever `FRONTEND_URL` defaults to in your code). Always set `FRONTEND_URL` explicitly in `.env` to match your frontend's actual URL (e.g., `http://localhost:5173` for Vite). If the skill generates a `.env` file and `FRONTEND_URL` is absent, add it manually before running the app.
### Social Login Providers
| Provider | Auth URL | Token URL | User Info URL |
|----------|----------|-----------|---------------|
| Google | accounts.google.com | oauth2.googleapis.com | www.googleapis.com/oauth2/v2/userinfo |
| Kakao | kauth.kakao.com | kauth.kakao.com |kapi.kakao.com/v2/user/me |
| Naver | nopenapis.naver.com | nopenapis.naver.com |openapi.naver.com/v1/nid/me |
### Error Handling
| HTTP Code | Condition |
|-----------|-----------|
| 200 | Success |
| 201 | User created |
| 400 | Validation error, invalid credentials |
| 401 | Unauthorized, token expired |
| 403 | Forbidden, insufficient role |
| 404 | User not found |
| 409 | Email already exists |
| 429 | Rate limit exceeded |
| 500 | Server error |
---
## API Endpoints
| Method | Path | Description |
|--------|------|-------------|
| POST | `/auth/register` | Register new user |
| POST | `/auth/login` | Login with email + password |
| POST | `/auth/logout` | Logout (revoke refresh token) |
| POST | `/auth/refresh` | Refresh access token |
| POST | `/auth/find-account` | Find account by phone or name |
| POST | `/auth/send-verification` | Send SMS verification code |
| POST | `/auth/verify-code` | Verify SMS code |
| POST | `/auth/reset-password-sms` | Reset password with temp token |
| POST | `/auth/change-password` | Change password (auth required) |
| GET | `/auth/sns/:provider` | Start OAuth flow (Google/Kakao/Naver) |
| GET | `/auth/sns/:provider/callback` | OAuth callback |
| GET | `/auth/me` | Get current user (auth required) |
| PATCH | `/auth/me` | Update current user profile (auth required) |
---
## Framework-Specific References
Full implementation by framework:
| Framework | Controller/Router | Service/Logic |
|-----------|-------------------|---------------|
| NestJS | See `references/nestjs-auth-controller.md` | See `references/nestjs-auth-service.md` |
| NodeJS | See `references/nodejs-auth-implementation.md` | Same file |
| FastAPI | See `references/fastapi-auth-implementation.md` | Same file |
### Additional References
- **OAuth2 PKCE**: `references/oauth2-pkce.md`
- **JWT Utilities**: `references/jwt-util.md`
- **Social Login**: `references/social-login.md`
- **Password Reset**: `references/password-reset.md`
---
## Environment Variables Required
JWT_ACCESS_SECRET=your-access-secret JWT_REFRESH_SECRET=your-refresh-secret JWT_ACCESS_EXPIRES=1h JWT_REFRESH_EXPIRES=7d
GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= GOOGLE_REDIRECT_URI=http://localhost:8000/auth/sns/google/callback KAKAO_CLIENT_ID= KAKAO_CLIENT_SECRET= KAKAO_REDIRECT_URI=http://localhost:8000/auth/sns/kakao/callback NAVER_CLIENT_ID= NAVER_CLIENT_SECRET= NAVER_REDIRECT_URI=http://localhost:8000/auth/sns/naver/callback
FRONTEND_URL=http://localhost:5173 DATABASE_URL=file:./dev.db
NCP_ACCESS_KEY= NCP_SECRET_KEY= NCP_SMS_SERVICE_ID= NCP_SMS_SENDER=01012345678
---
## Quick Reference
### Registration Flow
POST /auth/register Body: { "email": "[email protected]", "password": "SecurePass123!", "name": "John" }
Response 201: { "user": { "id": "...", "email": "..." } }
### Login Flow
POST /auth/login Body: { "email": "[email protected]", "password": "SecurePass123!" }
Response 200: { "accessToken": "eyJ...", "refreshToken": "eyJ...", "user": { "id": "...", "email": "..." } }
### Refresh Token Flow
POST /auth/refresh Body: { "refreshToken": "eyJ..." }
Response 200: { "accessToken": "eyJ...", "refreshToken": "eyJ..." }
### OAuth Flow (Google example)
GET /auth/sns/google → Redirects to Google consent screen
GET /auth/sns/google/callback?code=xxx → Returns tokens + user info
### Password Reset Flow (SMS)
POST /auth/find-account Body: { "phone": "01012345678" } or { "name": "John" } → { "userId": "...", "maskedPhone": "010****5678" }
POST /auth/send-verification Body: { "phone": "01012345678" } → { "success": true, "expiresIn": 300 }
POST /auth/verify-code Body: { "phone": "01012345678", "code": "123456" } → { "valid": true, "tempToken": "..." }
POST /auth/reset-password-sms Headers: { "Authorization": "Bearer {tempToken}" } Body: { "newPassword": "NewSecure123!" } → { "success": true }
Provides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.
npx claudepluginhub auraworks/my-marketplace --plugin generate-auth-apis