Authentication Setup
AV API supports multiple authentication methods:
- Email/Password (Traditional signup & login)
- Google OAuth 2.0 (Social login)
- Facebook OAuth 2.0 (Social login)
- Microsoft OAuth 2.0 (Social login)
All methods return JWT tokens for API authorization.
Authentication Flow
User (Frontend)
↓
├─ Email/Password Signup: POST /api/signup/
├─ Email/Password Login: POST /api/login/
├─ Google OAuth: POST /api/auth/google/
├─ Facebook OAuth: POST /api/auth/facebook/
└─ Microsoft OAuth: POST /api/auth/microsoft/
↓
Backend validates credentials/token
↓
Returns JWT tokens + User profile
↓
Frontend uses JWT for all API requests
Option 1: Email/Password Authentication
The simplest authentication method - create an account and login with email and password.
Sign Up
Endpoint: POST /api/signup/
Request:
{
"email": "[email protected]",
"password": "MySecurePassword123",
"password_confirm": "MySecurePassword123",
"first_name": "John",
"last_name": "Doe"
}
Requirements: - Email must be unique - Password must be at least 8 characters long - Passwords must match
Response (201 Created):
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"date_joined": "2025-10-29T12:00:00Z"
}
}
Login
Endpoint: POST /api/login/
Request:
{
"email": "[email protected]",
"password": "MySecurePassword123"
}
Response (200 OK):
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"date_joined": "2025-10-29T12:00:00Z"
}
}
JavaScript Example
// Signup
async function signup(email, password, firstName, lastName) {
const response = await fetch('http://localhost:8000/api/signup/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email,
password,
password_confirm: password,
first_name: firstName,
last_name: lastName
})
});
if (response.ok) {
const data = await response.json();
localStorage.setItem('accessToken', data.access);
localStorage.setItem('refreshToken', data.refresh);
return data.user;
}
throw new Error('Signup failed');
}
// Login
async function login(email, password) {
const response = await fetch('http://localhost:8000/api/login/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
if (response.ok) {
const data = await response.json();
localStorage.setItem('accessToken', data.access);
localStorage.setItem('refreshToken', data.refresh);
return data.user;
}
throw new Error('Login failed');
}
Option 2: Google OAuth
Get Google OAuth Token (Frontend)
Use Google Sign-In on your frontend to get a Google OAuth token.
Using Google Sign-In Library
<!-- Add Google Sign-In script -->
<script src="https://accounts.google.com/gsi/client" async defer></script>
// Initialize Google Sign-In
google.accounts.id.initialize({
client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
callback: handleGoogleResponse
});
// Show sign-in button
google.accounts.id.renderButton(
document.getElementById('googleSignInButton'),
{ theme: 'outline', size: 'large' }
);
// Handle response
function handleGoogleResponse(response) {
const googleToken = response.credential;
// Now exchange for JWT tokens (Step 2)
authenticateWithBackend(googleToken);
}
Exchange Google Token for JWT Tokens
Send the Google token to the backend to get JWT tokens.
Endpoint: POST /api/auth/google/
Request:
Response
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": 1,
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe"
}
}
JavaScript Example
async function authenticateWithBackend(googleToken) {
const response = await fetch('http://localhost:8000/api/auth/google/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
access_token: googleToken
})
});
if (response.ok) {
const data = await response.json();
// Store tokens
const accessToken = data.access;
const refreshToken = data.refresh;
const user = data.user;
console.log('Authenticated as:', user.email);
// Store in memory (recommended)
window.authTokens = {
access: accessToken,
refresh: refreshToken
};
}
}
async function authenticateWithBackend(googleToken) {
try {
const response = await axios.post('http://localhost:8000/api/auth/google/', {
access_token: googleToken
});
const { access, refresh, user } = response.data;
console.log('Authenticated as:', user.email);
// Store tokens
window.authTokens = {
access: access,
refresh: refresh
};
} catch (error) {
console.error('Authentication failed:', error);
}
}
Option 3: Facebook OAuth
Endpoint: POST /api/auth/facebook/
Authenticate using Facebook OAuth token.
Request:
Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"date_joined": "2025-10-29T12:00:00Z"
}
}
JavaScript Example:
// Using Facebook SDK
FB.login(function(response) {
if (response.authResponse) {
const accessToken = response.authResponse.accessToken;
fetch('http://localhost:8000/api/auth/facebook/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ access_token: accessToken })
})
.then(res => res.json())
.then(data => {
localStorage.setItem('accessToken', data.access);
localStorage.setItem('refreshToken', data.refresh);
console.log('Authenticated as:', data.user.email);
});
}
}, {scope: 'public_profile,email'});
Option 4: Microsoft OAuth
Endpoint: POST /api/auth/microsoft/
Authenticate using Microsoft OAuth token.
Request:
Response:
{
"access": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"date_joined": "2025-10-29T12:00:00Z"
}
}
JavaScript Example:
// Using Microsoft MSAL
const msalConfig = {
auth: {
clientId: 'YOUR_MICROSOFT_CLIENT_ID'
}
};
const msalInstance = new msal.PublicClientApplication(msalConfig);
msalInstance.loginPopup({
scopes: ['User.Read']
}).then(response => {
const accessToken = response.accessToken;
fetch('http://localhost:8000/api/auth/microsoft/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ access_token: accessToken })
})
.then(res => res.json())
.then(data => {
localStorage.setItem('accessToken', data.access);
localStorage.setItem('refreshToken', data.refresh);
console.log('Authenticated as:', data.user.email);
});
}).catch(error => console.error('Login failed:', error));
Using Access Token for API Requests
Include the access token in the Authorization header for all API requests.
Request Example
JavaScript Example
async function makeAPIRequest(endpoint) {
const accessToken = window.authTokens.access;
const response = await fetch(`http://localhost:8000${endpoint}`, {
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
});
if (response.ok) {
return await response.json();
} else if (response.status === 401) {
// Token expired - refresh it (see Token Management)
console.log('Token expired');
}
}
// Example: Get user profile
async function getUserProfile() {
const profile = await makeAPIRequest('/api/me/');
console.log(profile);
}
Token Information
| Token | Lifetime | Purpose |
|---|---|---|
| Access Token | 60 minutes | API requests |
| Refresh Token | 1 day | Get new access token |
Token Expiration
Access tokens expire after 60 minutes. See Token Management for how to handle expiration.
Security Best Practices
✅ DO:
- Store tokens in memory (JavaScript variables)
- Use HTTPS in production
- Clear tokens on logout
- Handle token expiration
❌ DON'T:
- Store tokens in localStorage (XSS risk)
- Log tokens to console in production
- Expose tokens in URLs
- Share tokens between users
Testing with cURL
# 1. Get Google OAuth token (use Google OAuth Playground or your frontend)
GOOGLE_TOKEN="your_google_oauth_token"
# 2. Exchange for JWT tokens
curl -X POST http://localhost:8000/api/auth/google/ \
-H "Content-Type: application/json" \
-d "{\"access_token\":\"$GOOGLE_TOKEN\"}"
# Response will contain access and refresh tokens
Next Steps
- Token Management - Handle token expiration and refresh
- API Reference - Complete endpoint documentation
- Interactive API Explorer - Try the API live
Email Verification
Email verification is optional by default in development mode.
Configuration
| Setting | Value | Meaning |
|---|---|---|
| ACCOUNT_EMAIL_VERIFICATION | optional |
Users can verify email but it's not required |
| Email Verification | ❌ Not enforced | Sign up works immediately without email confirmation |
| Good for | Development | Faster testing, no email required |
In Production
For production, consider changing to enforce email verification:
# In core/settings.py
ACCOUNT_EMAIL_VERIFICATION = "mandatory" # Require email verification before login
# or
ACCOUNT_EMAIL_VERIFICATION = "optional" # Suggest email verification
Security Best Practices
✅ DO:
- Store access tokens in memory only (React Context recommended)
- Store refresh token securely (httpOnly cookies or secure localStorage)
- Use HTTPS in production
- Clear tokens on logout
- Handle token expiration with automatic refresh
- Validate refresh token on every app load
- Set secure CORS origins
❌ DON'T:
- Store access tokens in localStorage (XSS risk!)
- Log tokens to console in production
- Expose tokens in URLs
- Share tokens between users
- Use weak passwords (< 8 characters)
- Store OAuth app secrets in frontend code
- Skip HTTPS in production
- Store sensitive data in JWT payload
Token Storage Recommendations
Best Practice (Recommended):
// Store in memory/React Context
const [authTokens, setAuthTokens] = useState({ access: null, refresh: null });
// Lost on page refresh - implement persistent login with secure refresh
Implementation Pattern:
// On app load, check if refresh token exists
useEffect(() => {
const refreshToken = localStorage.getItem('refreshToken');
if (refreshToken && !authTokens.access) {
// Refresh tokens to restore session
refreshAccessToken();
}
}, []);
Avoid:
// DON'T store access tokens in localStorage
localStorage.setItem('accessToken', token); // ❌ XSS vulnerability!
Logout
Always clear tokens when user logs out:
function logout() {
// Clear all tokens
localStorage.removeItem('refreshToken');
setAuthTokens({ access: null, refresh: null });
setUser(null);
// Redirect to login
window.location.href = '/login';
}
Setting Up OAuth Credentials
Google OAuth
- Go to Google Cloud Console
- Create a new project
- Enable Google+ API
- Create OAuth 2.0 credentials (Web application)
- Add authorized redirect URI:
http://localhost:3000/auth/callback/google - Copy Client ID and Client Secret to
.env:
Facebook OAuth
- Go to Facebook Developers
- Create a new app → Facebook Login
- In Settings > Basic, get App ID and App Secret
- In Settings > Basic, add Valid OAuth Redirect URIs:
http://localhost:3000/auth/callback/facebook- Copy credentials to
.env:
Microsoft OAuth
- Go to Azure Portal
- Create App Registration
- In Certificates & secrets, create Client Secret
- In Authentication, add Redirect URI:
http://localhost:3000/auth/callback/microsoft- Copy Client ID and Client Secret to
.env:
Complete Authentication Flow Diagram
┌─────────────────────────────────────────────────────────────────┐
│ Frontend (React) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ User clicks "Sign Up" │
│ ↓ │
│ Fills email, password → POST /api/signup/ │
│ ↓ │
│ Response: { access, refresh, user } │
│ ↓ │
│ Store: access in memory, refresh in secure storage │
│ ↓ │
│ Display: Welcome, {user.first_name}! │
│ ↓ │
│ Make API requests: Authorization: Bearer {access} │
│ ↓ │
│ After 60 minutes, access token expires (401 error) │
│ ↓ │
│ Auto-refresh: POST /api/token/refresh/ with {refresh} │
│ ↓ │
│ Get new access token → Continue using API │
│ ↓ │
│ After 1 day, refresh token expires │
│ ↓ │
│ Prompt: "Session expired. Please sign in again." │
│ ↓ │
│ Clear tokens & redirect to login │
│ │
└─────────────────────────────────────────────────────────────────┘
Common Issues & Solutions
Issue: "Invalid email or password"
- ✅ Check email spelling
- ✅ Verify password is correct
- ✅ Ensure user account exists
Issue: "A user with this email already exists"
- ✅ Use login endpoint instead of signup
- ✅ Use different email for new account
- ✅ Request password reset
Issue: "Given token not valid for any token type"
- ✅ Access token has expired → use refresh token
- ✅ Refresh token is invalid → user must re-authenticate
Issue: "OAuth token invalid"
- ✅ Google/Facebook/Microsoft token expired → get fresh token
- ✅ Wrong provider token → use correct provider endpoint
- ✅ Token revoked in OAuth provider settings
Testing Authentication
With cURL
# 1. Sign up
curl -X POST http://localhost:8000/api/signup/ \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "TestPassword123",
"password_confirm": "TestPassword123",
"first_name": "Test",
"last_name": "User"
}' | jq
# 2. Login
curl -X POST http://localhost:8000/api/login/ \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "TestPassword123"
}' | jq
# 3. Use access token
ACCESS_TOKEN=$(curl -s -X POST http://localhost:8000/api/login/ \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"TestPassword123"}' | jq -r '.access')
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
http://localhost:8000/api/me/ | jq
# 4. Refresh token
REFRESH_TOKEN=$(curl -s -X POST http://localhost:8000/api/login/ \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"TestPassword123"}' | jq -r '.refresh')
curl -X POST http://localhost:8000/api/token/refresh/ \
-H "Content-Type: application/json" \
-d "{\"refresh\":\"$REFRESH_TOKEN\"}" | jq
Environment Configuration
See .env.example for all required environment variables:
# Copy and customize
cp .env.example .env
# Edit .env and add your OAuth credentials
GOOGLE_OAUTH_CLIENT_ID=...
GOOGLE_OAUTH_CLIENT_SECRET=...
FACEBOOK_APP_ID=...
FACEBOOK_APP_SECRET=...
MICROSOFT_APP_ID=...
MICROSOFT_APP_SECRET=...
Related Documentation
- Token Management: Token Refresh & Expiration
- API Reference: Complete Endpoint Documentation
- Interactive Docs: API Explorer