auth/implementing-local-auth/SKILL.md
User registration, login, and password hashing with bcrypt for local authentication flows.
npx skillsauth add 7a336e6e/skills implementing-local-authInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Implement a secure local authentication system with user registration, login, and password hashing using bcrypt. The system must validate inputs, enforce password policy, and return JWTs on successful authentication.
The registration flow follows these steps: validate input, check uniqueness, hash password, create user, return token.
import bcrypt
from flask import Blueprint, request, jsonify
from marshmallow import Schema, fields, validate, ValidationError
auth_bp = Blueprint("auth", __name__, url_prefix="/api/v1/auth")
class RegisterSchema(Schema):
email = fields.Email(required=True)
password = fields.Str(
required=True,
validate=validate.Length(min=8),
)
name = fields.Str(required=True, validate=validate.Length(min=1, max=255))
def hash_password(plain: str) -> str:
"""Hash a password with bcrypt using a work factor of 12."""
salt = bcrypt.gensalt(rounds=12)
return bcrypt.hashpw(plain.encode("utf-8"), salt).decode("utf-8")
@auth_bp.route("/register", methods=["POST"])
def register():
schema = RegisterSchema()
try:
data = schema.load(request.get_json())
except ValidationError as err:
return jsonify({"error": "Validation failed", "details": err.messages}), 400
# Check uniqueness
existing = User.query.filter_by(email=data["email"]).first()
if existing:
# Return generic message to avoid revealing registered emails
return jsonify({"error": "Registration failed. Please try again."}), 400
# Hash password and create user
hashed = hash_password(data["password"])
user = User(email=data["email"], password_hash=hashed, name=data["name"])
db.session.add(user)
db.session.commit()
token = generate_access_token(user)
return jsonify({"access_token": token}), 201
The login flow follows these steps: find user by email, verify password, generate token, return token.
class LoginSchema(Schema):
email = fields.Email(required=True)
password = fields.Str(required=True)
def verify_password(plain: str, hashed: str) -> bool:
"""Verify a plaintext password against a bcrypt hash."""
return bcrypt.checkpw(plain.encode("utf-8"), hashed.encode("utf-8"))
@auth_bp.route("/login", methods=["POST"])
def login():
schema = LoginSchema()
try:
data = schema.load(request.get_json())
except ValidationError as err:
return jsonify({"error": "Invalid credentials"}), 401
user = User.query.filter_by(email=data["email"]).first()
if not user or not verify_password(data["password"], user.password_hash):
return jsonify({"error": "Invalid credentials"}), 401
token = generate_access_token(user)
return jsonify({"access_token": token}), 200
Always use bcrypt with a work factor of 12. This provides a good balance between security and performance. The work factor doubles the computation for each increment, so 12 results in 2^12 (4096) iterations of the key derivation.
# Work factor 12 is the recommended default
salt = bcrypt.gensalt(rounds=12)
hashed = bcrypt.hashpw(password.encode("utf-8"), salt)
Registration success (201):
{ "access_token": "<jwt>" }
Login success (200):
{ "access_token": "<jwt>" }
Validation error (400):
{ "error": "Validation failed", "details": { "email": ["Not a valid email address."] } }
Auth failure (401):
{ "error": "Invalid credentials" }
development
Implement features using the Red-Green-Refactor cycle to ensure testability and correctness from the start.
data-ai
Manage the `tasks.md` ledger with strict locking and collision avoidance protocols to allow multiple agents to work in parallel safely.
development
The git-workflow skill defines branching conventions, commit message formats, and pull request standards that all agents must follow for consistent version control.
development
The environment-config skill standardizes how agents manage environment variables, secrets, and application configuration across local development and deployed environments.