Receber por email
← Voltar para o catálogo

better-auth-skill

Configure uma autenticação aprimorada com JWT para uma segurança robusta.

556estrelas
Atualizado há 2 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add majiayu000/claude-skill-registry

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/better-auth-skill/svg)](https://www.skillteca.com.br/skills/better-auth-skill)

Skills relacionadas

Ver todas de Pesquisa e Web →

Alerta por categoria

Receba novas skills de Pesquisa e Web toda segunda

1 email curto, só com as skills novas de Pesquisa e Web. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Better Auth Skill

Instructions

This skill provides guidance for configuring Better Auth with JWT for secure user authentication.

Project Structure

backend/
├── auth/
│   ├── __init__.py
│   ├── service.py          # Auth business logic
│   ├── dependencies.py     # FastAPI dependencies
│   ├── routes.py           # Auth endpoints
│   └── schemas.py          # Pydantic schemas
frontend/
└── src/
    ├── lib/
    │   └── auth.ts         # Frontend auth utilities
    └── hooks/
        └── useAuth.ts      # Auth state hook

JWT Configuration

# backend/auth/config.py
from pydantic_settings import BaseSettings
from datetime import timedelta
from typing import Optional

class AuthSettings(BaseSettings):
    SECRET_KEY: str
    ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
    REFRESH_TOKEN_EXPIRE_DAYS: int = 7

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"

auth_settings = AuthSettings()

Better Auth Setup

# backend/auth/service.py
from datetime import datetime, timedelta
from typing import Optional
from jose import JWTError, jwt
from passlib.context import CryptContext
from models.user import User
from database import AsyncSessionLocal
from sqlalchemy import select
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None) -> str:
    """Create JWT access token."""
    to_encode = data.copy()
    if expires_delta:
        expire = datetime.utcnow() + expires_delta
    else:
        expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(
        to_encode,
        auth_settings.SECRET_KEY,
        algorithm=ALGORITHM
    )
    return encoded_jwt

def create_refresh_token(data: dict) -> str:
    """Create JWT refresh token."""
    to_encode = data.copy()
    expire = datetime.utcnow() + timedelta(days=7)
    to_encode.update({"exp": expire, "type": "refresh"})
    return jwt.encode(to_encode, auth_settings.SECRET_KEY, algorithm=ALGORITHM)

def verify_password(plain_password: str, hashed_password: str) -> bool:
    """Verify password against hash."""
    return pwd_context.verify(plain_password, hashed_password)

def hash_password(password: str) -> str:
    """Hash password for storage."""
    return pwd_context.hash(password)

async def authenticate_user(email: str, password: str) -> Optional[User]:
    """Authenticate user by email and password."""
    async with AsyncSessionLocal() as db:
        result = await db.execute(
            select(User).where(User.email == email)
        )
        user = result.scalar_one_or_none()

        if not user:
            return None
        if not verify_password(password, user.hashed_password):
            return None
        return user

async def get_user_by_email(email: str) -> Optional[User]:
    """Get user by email."""
    async with AsyncSessionLocal() as db:
        result = await db.execute(
            select(User).where(User.email == email)
        )
        return result.scalar_one_or_none()

async def create_user(email: str, password: str, name: str) -> User:
    """Create new user."""
    async with AsyncSessionLocal() as db:
        hashed_password = hash_password(password)
        user = User(
            email=email,
            hashed_password=hashed_password,
            name=name
        )
        db.add(user)
        await db.commit()
        await db.refresh(user)
        return user

Auth Dependencies

# backend/auth/dependencies.py
from datetime import datetime
from typing import Optional
from jose import JWTError, jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.ext.asyncio import AsyncSession

from database import get_db
from models.user import User
from auth.service import oauth2_scheme, ALGORITHM, auth_settings

class TokenData:
    """Data extracted from JWT token."""
    email: Optional[str] = None
    user_id: Optional[int] = None

async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: AsyncSession = Depends(get_db)
) -> User:
    """Get current authenticated user from JWT token."""
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Could not validate credentials",
        headers={"WWW-Authenticate": "Bearer"},
    )

    try:
        payload = jwt.decode(
            token,
            auth_settings.SECRET_KEY,
            algorithms=[ALGORITHM]
        )
        email: str = payload.get("sub")
        if email is None:
            raise credentials_exception

        token_data = TokenData(email=email, user_id=payload.get("user_id"))
    except JWTError:
        raise credentials_exception

    async with AsyncSessionLocal() as session:
        result = await session.execute(
            select(User).where(User.email == token_data.email)
        )
        user = result.scalar_one_or_none()

        if user is None:
            raise credentials_exception

        if not user.is_active:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="User account is disabled"
            )

        return user

async def get_current_active_user(
    current_user: User = Depends(get_current_user)
) -> User:
    """Get current active user (alias for get_current_user)."""
    return current_user

def decode_token(token: str) -> TokenData:
    """Decode JWT token without raising exceptions."""
    try:
        payload = jwt.decode(
            token,
            auth_settings.SECRET_KEY,
            algorithms=[ALGORITHM]
        )
        return TokenData(
            email=payload.get("sub"),
            user_id=payload.get("user_id")
        )
    except JWTError:
        return TokenData()

Auth Schemas (Pydantic)

# backend/auth/schemas.py
from pydantic import BaseModel, EmailStr
from datetime import datetime
from typing import Optional

# Request schemas
class UserCreate(BaseModel):
    """Schema for user registration."""
    email: EmailStr
    password: str = Field(..., min_length=8)
    name: str = Field(..., min_length=1, max_length=100)

class UserLogin(BaseModel):
    """Schema for user login."""
    email: EmailStr
    password: str

class TokenRefresh(BaseModel):
    """Schema for token refresh."""
    refresh_token: str

# Response schemas
class Token(BaseModel):
    """Schema for authentication tokens."""
    access_token: str
    refresh_token: str
    token_type: str = "bearer"

class TokenPayload(BaseModel):
    """Schema for token payload."""
    sub: str
    user_id: int
    exp: datetime

class UserResponse(BaseModel):
    """Schema for user response."""
    id: int
    email: str
    name: str
    is_active: bool
    created_at: datetime

    class Config:
        from_attributes = True

class AuthResponse(BaseModel):
    """Schema for authentication response."""
    user: UserResponse
    tokens: Token

Auth Routes

# backend/auth/routes.py
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.ext.asyncio import AsyncSession

from database import get_db
from auth.service import (
    authenticate_user,
    create_user,
    create_access_token,
    create_refresh_token,
    get_user_by_email,
)
from auth.schemas import (
    UserCreate,
    UserLogin,
    Token,
    UserResponse,
    AuthResponse,
    TokenRefresh,
)
from auth.dependencies import get_current_user
from models.user import User

router = APIRouter(prefix="/auth", tags=["Authen
Compartilhar X LinkedIn