# Getting Started with SwiftOps Authentication **For Frontend Developers** | Estimated Time: 30 minutes --- ## 👋 Welcome! This guide will help you integrate SwiftOps authentication into your frontend application. By the end, you'll have: - ✅ Working login/logout functionality - ✅ User profile display - ✅ Protected routes - ✅ Error handling --- ## 📚 Documentation Overview You have access to three documents: 1. **This Guide (Getting Started)** - Start here (30 min read) 2. **Quick Reference** - For quick lookups later 3. **Complete API Guide** - For deep dives and advanced features **Read them in order:** Getting Started → Quick Reference → Complete Guide --- ## 🎯 What You'll Build ### Step 1: Login Page User enters email/password → System returns token → Store token → Redirect to dashboard ### Step 2: Dashboard Check if token exists → Fetch user profile → Display user info ### Step 3: Protected Routes Before showing any page → Check token → If invalid, redirect to login ### Step 4: Logout User clicks logout → Call logout API → Clear token → Redirect to login --- ## 🚀 Let's Start! ### Prerequisites - Basic JavaScript/React knowledge - Fetch API or Axios experience - Understanding of localStorage --- ## Step 1: Create Auth Service (10 minutes) Create a file: `src/services/auth.js` ```javascript // auth.js - Your authentication service const API_BASE = 'https://your-api-domain.com/api/v1'; const TOKEN_KEY = 'swiftops_token'; class AuthService { // Get token from localStorage getToken() { return localStorage.getItem(TOKEN_KEY); } // Save token to localStorage setToken(token) { localStorage.setItem(TOKEN_KEY, token); } // Remove token from localStorage clearToken() { localStorage.removeItem(TOKEN_KEY); } // Check if user is logged in isAuthenticated() { return !!this.getToken(); } // Get headers for authenticated requests getHeaders() { const token = this.getToken(); return { 'Content-Type': 'application/json', ...(token && { 'Authorization': `Bearer ${token}` }) }; } // Login user async login(email, password) { const response = await fetch(`${API_BASE}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); if (!response.ok) { const error = await response.json(); throw new Error(error.detail || 'Login failed'); } const data = await response.json(); this.setToken(data.access_token); return data.user; } // Get current user profile async getCurrentUser() { const response = await fetch(`${API_BASE}/auth/me`, { method: 'GET', headers: this.getHeaders() }); if (!response.ok) { if (response.status === 401) { // Token expired or invalid this.clearToken(); } throw new Error('Failed to fetch user profile'); } return await response.json(); } // Logout user async logout() { try { // Call logout endpoint for audit await fetch(`${API_BASE}/auth/logout`, { method: 'POST', headers: this.getHeaders() }); } catch (error) { console.error('Logout error:', error); } finally { // Always clear token this.clearToken(); } } } // Export singleton instance export default new AuthService(); ``` **What this does:** - Stores/retrieves JWT token in localStorage - Provides methods for login, logout, and getting user - Handles token expiration automatically --- ## Step 2: Create Login Page (15 minutes) Create a file: `src/pages/LoginPage.jsx` ```javascript import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import AuthService from '../services/auth'; function LoginPage() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); const navigate = useNavigate(); const handleSubmit = async (e) => { e.preventDefault(); setError(''); setLoading(true); try { // Call login API const user = await AuthService.login(email, password); // Success! Redirect to dashboard console.log('Logged in as:', user.email); navigate('/dashboard'); } catch (err) { // Show error to user setError(err.message); setLoading(false); } }; return (

Login to SwiftOps

{error && (
{error}
)}
setEmail(e.target.value)} placeholder="user@example.com" required disabled={loading} />
setPassword(e.target.value)} placeholder="Enter your password" required disabled={loading} />
Forgot password?
); } export default LoginPage; ``` **CSS (optional):** ```css .login-container { display: flex; justify-content: center; align-items: center; min-height: 100vh; background: #f5f5f5; } .login-box { background: white; padding: 40px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); width: 100%; max-width: 400px; } .error-message { background: #fee; color: #c00; padding: 12px; border-radius: 4px; margin-bottom: 20px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 8px; font-weight: 600; } .form-group input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; } .btn-primary { width: 100%; padding: 12px; background: #007bff; color: white; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; } .btn-primary:hover { background: #0056b3; } .btn-primary:disabled { background: #ccc; cursor: not-allowed; } .login-footer { margin-top: 20px; text-align: center; } ``` --- ## Step 3: Create Dashboard (5 minutes) Create a file: `src/pages/Dashboard.jsx` ```javascript import React, { useState, useEffect } from 'react'; import { useNavigate } from 'react-router-dom'; import AuthService from '../services/auth'; function Dashboard() { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const navigate = useNavigate(); useEffect(() => { loadUser(); }, []); const loadUser = async () => { try { const userData = await AuthService.getCurrentUser(); setUser(userData); } catch (err) { setError(err.message); // If token invalid, redirect to login navigate('/login'); } finally { setLoading(false); } }; const handleLogout = async () => { await AuthService.logout(); navigate('/login'); }; if (loading) { return
Loading...
; } if (error) { return
Error: {error}
; } return (

Welcome, {user.name}!

Your Profile

Email: {user.email}

Role: {user.role}

Phone: {user.phone || 'Not set'}

Status: {user.status}

); } export default Dashboard; ``` --- ## Step 4: Set Up Routes (5 minutes) Update your `src/App.jsx`: ```javascript import React from 'react'; import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom'; import LoginPage from './pages/LoginPage'; import Dashboard from './pages/Dashboard'; import AuthService from './services/auth'; // Protected Route component function ProtectedRoute({ children }) { if (!AuthService.isAuthenticated()) { return ; } return children; } function App() { return ( } /> } /> } /> ); } export default App; ``` --- ## 🎉 You're Done! Test It Out ### Test Login 1. Start your dev server: `npm start` 2. Go to `http://localhost:3000/login` 3. Enter credentials: - Email: `user@example.com` - Password: `SecurePass123!` 4. Click "Login" 5. Should redirect to dashboard ### Test Protected Route 1. Go to `http://localhost:3000/dashboard` without logging in 2. Should redirect to `/login` ### Test Logout 1. On dashboard, click "Logout" 2. Should redirect to `/login` 3. Try accessing `/dashboard` again 4. Should redirect to `/login` --- ## 🐛 Common Issues & Solutions ### Issue: "Login failed" **Solution:** Check if API URL is correct. Verify email/password. ### Issue: "Failed to fetch user profile" **Solution:** Token might be expired. Clear localStorage and login again. ### Issue: Infinite redirect loop **Solution:** Check if token is being stored correctly in localStorage. ### Issue: CORS error **Solution:** Backend needs to allow your frontend domain in CORS settings. --- ## 📝 What You Just Built ✅ **Login System** - Users can login with email/password ✅ **Token Management** - JWT token stored in localStorage ✅ **Protected Routes** - Dashboard only accessible when logged in ✅ **Auto-Logout** - Expired tokens handled automatically ✅ **User Profile** - Display current user information ✅ **Logout** - Users can logout --- ## 🚀 Next Steps ### Phase 2: Profile Management Add ability to update user profile: ```javascript // In Dashboard.jsx const updateProfile = async () => { const response = await fetch(`${API_BASE}/auth/me`, { method: 'PUT', headers: AuthService.getHeaders(), body: JSON.stringify({ first_name: 'Jane', phone: '+254712345678' }) }); const updatedUser = await response.json(); setUser(updatedUser); }; ``` ### Phase 3: Invitation System Handle invitation links when users are invited: ```javascript // InvitationAcceptPage.jsx const acceptInvitation = async (token, password, name) => { const response = await fetch(`${API_BASE}/invitations/accept`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ token, password, name, accept_terms: true }) }); const data = await response.json(); AuthService.setToken(data.access_token); navigate('/dashboard'); }; ``` ### Phase 4: Password Reset Add forgot password and reset password flows. --- ## 📚 Where to Go Next 1. **Quick Reference** - For quick endpoint lookups 2. **Complete API Guide** - For advanced features: - Password management - Invitation system - Error handling patterns - Security best practices --- ## 💬 Need Help? ### Common Questions **Q: How long does the token last?** A: 24 hours. After that, user must login again. **Q: Can I use axios instead of fetch?** A: Yes! Just replace fetch calls with axios. Example: ```javascript const response = await axios.post(`${API_BASE}/auth/login`, { email, password }); const { access_token, user } = response.data; ``` **Q: How do I show loading spinners?** A: Use the `loading` state variable like in the examples. **Q: What if I need to call other APIs?** A: Use `AuthService.getHeaders()` to include the auth token: ```javascript fetch(`${API_BASE}/users`, { headers: AuthService.getHeaders() }); ``` **Q: Mobile app development?** A: Use SecureStore instead of localStorage: ```javascript import * as SecureStore from 'expo-secure-store'; await SecureStore.setItemAsync('token', token); ``` --- ## ✅ Checklist Before moving to production: - [ ] Login page works - [ ] Dashboard shows user info - [ ] Logout works - [ ] Protected routes redirect to login - [ ] Error messages display properly - [ ] Token stored in localStorage - [ ] 401 errors handled (auto-logout) - [ ] Loading states shown - [ ] Password validation on client side --- ## 🎯 Summary **What you learned:** - How to integrate SwiftOps authentication - Token-based authentication flow - Protected routes implementation - Error handling patterns **Time invested:** 30-60 minutes **Result:** Working auth system **Next steps:** Read the Quick Reference for other features like password reset, invitation system, and profile management. --- **Good luck with your implementation! 🚀** Need detailed information? See `AUTH_API_COMPLETE.md` Need quick lookup? See `AUTH_API_QUICK_REFERENCE.md`