9.9 KiB
title, description, icon
| title | description | icon |
|---|---|---|
| Authentication API | User registration, login, tokens, email verification, sessions | i-carbon-password |
Authentication API
User authentication, registration, API token management, and email verification.
Registration
Register New User
Pattern: POST /auth/register
Authentication: Public (no auth required)
Query Parameters:
invitation_token(optional): Required if server is in invitation-only mode
Request Body:
{
"username": "alice",
"email": "alice@example.com",
"password": "secure_password_123"
}
Response:
{
"success": true,
"message": "User created successfully",
"email_verified": true
}
With Email Verification Enabled:
{
"success": true,
"message": "User created. Please check your email to verify your account.",
"email_verified": false
}
Validation:
- Username: Not reserved, not already taken, no normalized conflicts
- Email: Valid format, not already registered
- Password: Minimum length (enforced by server config)
Reserved Usernames:
models, datasets, spaces, admin, api, organizations, settings, new, login, register, logout, docs, and more (see validation.py)
Status Codes:
200 OK- User created400 Bad Request- Username/email taken, reserved name, or validation error403 Forbidden- Invitation required but not provided
Login & Sessions
Login
Pattern: POST /auth/login
Authentication: Public
Request Body:
{
"username": "alice",
"password": "secure_password_123"
}
Response:
{
"success": true,
"message": "Logged in successfully",
"username": "alice",
"session_secret": "random_secret_for_client_side_encryption"
}
Response Headers:
Set-Cookie: session_id=abc123...; HttpOnly; SameSite=Lax; Max-Age=2592000
Session Duration: 30 days (default, configurable)
Checks:
- Username and password match
- Account is active (
is_active = true) - Email verified (if
require_email_verification = true)
Status Codes:
200 OK- Logged in successfully401 Unauthorized- Invalid credentials403 Forbidden- Account disabled or email not verified
Logout
Pattern: POST /auth/logout
Authentication: Required (session cookie or token)
Response:
{
"success": true,
"message": "Logged out successfully"
}
Behavior:
- Deletes all user sessions from database
- Clears session_id cookie
Get Current User
Pattern: GET /auth/me
Authentication: Required
Response:
{
"id": 1,
"username": "alice",
"email": "alice@example.com",
"email_verified": true,
"created_at": "2025-01-01T00:00:00Z"
}
Use Case: Check if still logged in, get basic user info
API Tokens
List Tokens
Pattern: GET /auth/tokens
Authentication: Required (session cookie or existing token)
Response:
{
"tokens": [
{
"id": 1,
"name": "My API Token",
"last_used": "2025-01-20T10:15:32Z",
"created_at": "2025-01-01T00:00:00Z"
},
{
"id": 2,
"name": "CI/CD Token",
"last_used": null,
"created_at": "2025-01-15T08:00:00Z"
}
]
}
Notes:
- Token values are never shown after creation
last_usedupdates when token is used- Tokens don't expire by default
Create Token
Pattern: POST /auth/tokens/create
Authentication: Required
Request Body:
{
"name": "My API Token"
}
Response:
{
"success": true,
"token": "hf_abc123def456ghi789jkl...",
"token_id": 3,
"session_secret": "encryption_secret",
"message": "Token created. Save it securely - you won't see it again!"
}
Important:
- Token value shown only once
- Copy immediately and store securely
- Cannot retrieve token value later
- Prefix:
hf_(HuggingFace compatible)
Revoke Token
Pattern: DELETE /auth/tokens/{token_id}
Authentication: Required (must own token)
Response:
{
"success": true,
"message": "Token revoked successfully"
}
Status Codes:
200 OK- Token revoked404 Not Found- Token not found or not owned by user
Email Verification
Verify Email
Pattern: GET /auth/verify-email?token={verification_token}
Authentication: Public
Purpose: Verify email address after registration
Response:
- Redirects to user profile on success:
302 -> /{username} - Redirects to login with error on failure:
302 -> /?error=invalid_token
Behavior:
- Validates verification token
- Checks token not expired (24 hours default)
- Marks user email as verified
- Deletes verification token
- Creates session and auto-logs in user
Cookie Set:
Set-Cookie: session_id=abc123...; HttpOnly; SameSite=Lax
Resend Verification Email
Pattern: POST /auth/resend-verification
Authentication: Required (can be unverified user)
Purpose: Resend verification email if not received
Response:
{
"success": true,
"message": "Verification email sent"
}
Validation:
- User must not be already verified
- Rate limit: Once per hour (TODO: implement)
Usage Examples
Register and Login
import requests
API_BASE = "http://localhost:28080"
# Register
register_resp = requests.post(
f"{API_BASE}/auth/register",
json={
"username": "alice",
"email": "alice@example.com",
"password": "secure123"
}
)
result = register_resp.json()
print(result["message"])
# If email verification required
if not result.get("email_verified"):
print("Check your email and click verification link")
# After clicking link, user is auto-logged in
# Login (if email verification not required)
login_resp = requests.post(
f"{API_BASE}/auth/login",
json={
"username": "alice",
"password": "secure123"
}
)
# Session cookie set automatically
session_cookie = login_resp.cookies.get("session_id")
print(f"Session ID: {session_cookie}")
Create and Use API Token
import requests
API_BASE = "http://localhost:28080"
# Login first (or use existing session)
session = requests.Session()
session.post(
f"{API_BASE}/auth/login",
json={"username": "alice", "password": "secure123"}
)
# Create token
token_resp = session.post(
f"{API_BASE}/auth/tokens/create",
json={"name": "My API Token"}
)
token_data = token_resp.json()
token = token_data["token"] # hf_abc123...
print(f"Token created: {token}")
print("SAVE THIS TOKEN - you won't see it again!")
# Use token in API requests
headers = {"Authorization": f"Bearer {token}"}
# List repositories
repos_resp = requests.get(
f"{API_BASE}/api/models",
headers=headers
)
print(f"Found {len(repos_resp.json())} models")
Manage Tokens
# List all tokens
tokens_resp = session.get(f"{API_BASE}/auth/tokens")
tokens = tokens_resp.json()["tokens"]
for t in tokens:
print(f"Token: {t['name']} (ID: {t['id']})")
print(f" Created: {t['created_at']}")
print(f" Last used: {t['last_used'] or 'Never'}")
# Revoke old token
old_token_id = tokens[0]["id"]
revoke_resp = session.delete(f"{API_BASE}/auth/tokens/{old_token_id}")
print(revoke_resp.json()["message"])
Registration with Invitation
# For invitation-only servers
invitation_token = "invitation_token_from_link"
register_resp = requests.post(
f"{API_BASE}/auth/register?invitation_token={invitation_token}",
json={
"username": "bob",
"email": "bob@example.com",
"password": "secure456"
}
)
# If invitation was for joining an organization
# User automatically added to that organization
Security
Password Hashing
- Algorithm: bcrypt
- Salt rounds: Automatic (bcrypt default)
- Passwords never stored in plaintext
Session Security
- HTTP-only cookies (not accessible via JavaScript)
- SameSite: Lax (CSRF protection)
- Secure flag in production (HTTPS only)
- 30-day expiration (configurable)
Token Security
- SHA256 hashed in database
- Prefix:
hf_(64 characters total) - Never logged in plaintext
- Single-use viewing (on creation only)
Session Secret
- Random 32-character string
- Used for client-side token encryption
- Unique per session
- Returned on login and token creation
Configuration
Environment Variables
# Session duration (hours)
KOHAKU_HUB_SESSION_EXPIRE_HOURS=720 # 30 days default
# Email verification
KOHAKU_HUB_REQUIRE_EMAIL_VERIFICATION=false
# Invitation-only registration
KOHAKU_HUB_INVITATION_ONLY=false
# Session secret (for cookie signing)
KOHAKU_HUB_SESSION_SECRET=change_this_in_production
# Email SMTP (for verification emails)
KOHAKU_HUB_SMTP_HOST=smtp.gmail.com
KOHAKU_HUB_SMTP_PORT=587
KOHAKU_HUB_SMTP_USERNAME=your_email@gmail.com
KOHAKU_HUB_SMTP_PASSWORD=your_app_password
KOHAKU_HUB_SMTP_FROM=noreply@yourdomain.com
Best Practices
For Users:
- Use strong passwords (mix of letters, numbers, symbols)
- Create tokens for CI/CD (don't use password)
- Revoke unused tokens
- Don't share tokens in public repos
For Developers:
- Store tokens in environment variables
- Use session cookies for browser apps
- Use Bearer tokens for API/CLI
- Handle 401/403 errors (prompt re-login)
For Admins:
- Enable email verification in production
- Use invitation-only mode for private instances
- Set strong SESSION_SECRET
- Enable HTTPS in production
- Monitor token usage via admin API
Error Responses
401 Unauthorized:
{
"detail": "Invalid username or password"
}
403 Forbidden:
{
"detail": "Account is disabled"
}
400 Bad Request:
{
"detail": "Username already exists"
}
Next Steps
- User Settings API - Profile, preferences
- Organizations API - Org membership
- Invitations API - Invite users
- Admin API - User management