Lesson 11: Authentication
"Security is not optional."
Current State
⚠️ No authentication implemented - All endpoints are open
Why Authentication Needed
- Prevent unauthorized access
- Track who does what
- Rate limiting per user
- Data isolation
JWT Implementation Guide
Step 1: Add Dependencies
python
pip install python-jose[cryptography] passlib[bcrypt]Step 2: Create User Model
python
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
email = Column(String, unique=True)
hashed_password = Column(String)Step 3: Password Hashing
python
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"])
def hash_password(password: str) -> str:
return pwd_context.hash(password)
def verify_password(plain: str, hashed: str) -> bool:
return pwd_context.verify(plain, hashed)Step 4: JWT Tokens
python
from jose import JWTError, jwt
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(hours=24)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
def verify_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return payload
except JWTError:
return NoneStep 5: Login Endpoint
python
@router.post("/login")
def login(email: str, password: str, db: Session = Depends(get_db)):
user = db.query(User).filter(User.email == email).first()
if not user or not verify_password(password, user.hashed_password):
raise HTTPException(401, "Invalid credentials")
token = create_access_token({"user_id": user.id})
return {"access_token": token, "token_type": "bearer"}Step 6: Protect Endpoints
python
def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
):
payload = verify_token(token)
if not payload:
raise HTTPException(401, "Invalid token")
user = db.query(User).filter(User.id == payload["user_id"]).first()
return user
@router.get("/agents/")
def get_agents(
user = Depends(get_current_user),
db: Session = Depends(get_db)
):
# Only return user's agents
return db.query(Agent).filter(Agent.user_id == user.id).all()OAuth2 Alternative
For social login (Google, GitHub):
python
from authlib.integrations.starlette_client import OAuth
oauth = OAuth()
oauth.register(
name='google',
client_id='YOUR_CLIENT_ID',
client_secret='YOUR_CLIENT_SECRET',
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
client_kwargs={'scope': 'openid email profile'}
)Security Best Practices
✅ Never store passwords in plain text ✅ Use HTTPS in production ✅ Set short token expiration ✅ Implement refresh tokens ✅ Rate limit login attempts ✅ Log authentication events
Key Takeaways
🎯 VeyraOps AI currently has no auth (development only) 🎯 JWT is industry standard for API authentication 🎯 Hash passwords with bcrypt 🎯 Protect endpoints with dependencies 🎯 OAuth2 for social login
Module 4 · API & Business Logic