- Extend your Flask app so it supports both GitHub OAuth and traditional username/password authentication, and allows authenticated users to create API keys for programmatic access.
- Build an app that accepts two authentication methods (OAuth and username/password). Users should be able to create API keys (one-time display), use keys to call protected API endpoints, and revoke keys. This activity is intentionally open-ended — no starter code will be provided here. Use the existing labs as references.
- App runs locally on
http://localhost:8000. - Preserve working GitHub OAuth flow (callback
http://localhost:8000/callback). - Add username/password signup and login (in-memory, file, or simple DB is fine for the lab).
- Implement API-key creation for authenticated users:
- Generate a secure random key and show the raw key exactly once after creation.
- Store only a hashed version of the key server-side.
- Support revocation (delete stored hash).
- Protect web routes with a
login_requireddecorator and API routes with anapi_key_requireddecorator. - Accept API-key auth via a header (e.g.
Authorization: ApiKey <key>orX-Api-Key). - Log each request (method, path, client IP, duration).
- Updated Flask app with both auth methods and API-key support.
requirements.txtand briefREADME.mdwith setup/run/test steps.- A short demo (curl commands) showing key creation, key-authenticated request, and key revocation.
- OAuth login still works and returns to
/dashboard. - Username/password signup/login works and returns to
/dashboard. - User can generate an API key and see the raw key exactly once.
- API endpoint (e.g.
/api/data) accepts requests authenticated with the API key header and returns JSON. - Revoked keys are rejected (401).
- Server logs show method, path, IP, and timing for requests.
- Never store raw API keys. Hash them (HMAC with a server secret, bcrypt, or similar) before storage.
- Use strong random key material (e.g., 32 bytes, URL-safe base64).
- For the lab, in-memory dict or a small JSON file is acceptable; explain production differences.
- Mark session cookies with
httponly=Trueandsecure=Truewhen HTTPS is used.
- Missing environment variables: ensure any
GITHUB_CLIENT_ID,GITHUB_CLIENT_SECRET, or DB path vars are set. - Callback URL mismatch: the callback configured in the GitHub app must exactly match your redirect URI (scheme, host, port, path).
- "bad verification code": usually the OAuth code was used twice or expired — try logging in again.
- API key 401 responses: verify the header name, key format, and that the server compares using the same hashing function.
- Add per-key rate limiting (token-bucket or sliding window).
- Implement scopes/permissions for API keys (read vs write).
- Add key expiry and rotation UI.
- Persist users/keys in SQLite or Postgres instead of memory.
- Build a nicer web UI (React/Vue) and separate API and web sessions.
- Add analytics: counts, last-used timestamps, usage dashboard.
- Implement retry/backoff and idempotency for API clients.
- Add multiple OAuth providers (Google, GitLab) and account linking.
- Deploy behind an HTTPS reverse proxy and document cert setup.
- Implement CSRF protection for form-based actions. For AJAX/CLI API calls using API keys the header-based auth is not vulnerable to CSRF.
- Create a key via web UI, then call API using curl:
curl -H "Authorization: ApiKey <your_raw_key>" http://localhost:8000/api/data- Revoke the key in the UI and confirm the same curl returns 401.
- This is intentionally open-ended. Encourage students to explain design choices (storage, hashing, headers, UX) in a short README.
- Grading rubric ideas: security (hashed keys, randomness), correctness (auth flows), UX (clear one-time display and revocation), and extras (rate-limiting, persistence).
If you want, I can also add a short README.md and requirements.txt with example curl commands — say "yes" and I will create them.