Implement user authentication with JWT, including login and registration features#52
Implement user authentication with JWT, including login and registration features#52Davictory2003 wants to merge 5 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds JWT-based authentication (login/registration/token refresh) across the Django backend and React frontend, wiring routing + an auth context provider so the UI can log in/out and display the current user.
Changes:
- Introduce an
AuthContextin the frontend with login/register/logout and periodic token refresh - Add
/api/token/,/api/token/refresh/, and/api/register/endpoints backed by SimpleJWT + a user serializer - Update the app shell to use React Router routes and show auth controls in the header
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/main.jsx | Wraps the app with BrowserRouter and AuthProvider |
| frontend/src/context/AuthContext.jsx | Adds auth state management, JWT decode, token refresh, and auth actions |
| frontend/src/components/Login.jsx | Adds login form wired to AuthContext |
| frontend/src/components/SignUp.jsx | Adds registration form wired to AuthContext |
| frontend/src/App.jsx | Adds routes for login/signup and header auth UI |
| frontend/src/App.css | Adjusts .btn styling and hover behavior (used by auth links/buttons) |
| frontend/package.json | Adds jwt-decode and react-router-dom dependencies |
| backend/requirements.txt | Adds djangorestframework-simplejwt |
| backend/cheat_sheet/settings.py | Enables JWTAuthentication in DRF settings |
| backend/api/views.py | Adds custom token view and registration view |
| backend/api/urls.py | Exposes token, refresh, and register endpoints |
| backend/api/serializers.py | Adds user serializer and custom token claims |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const [authTokens, setAuthTokens] = useState(() => | ||
| localStorage.getItem('authTokens') ? JSON.parse(localStorage.getItem('authTokens')) : null | ||
| ); | ||
| const [user, setUser] = useState(() => | ||
| localStorage.getItem('authTokens') ? jwtDecode(localStorage.getItem('authTokens')) : null | ||
| ); |
| const response = await fetch('/api/token/', { | ||
| method: 'POST', | ||
| headers: { | ||
| 'Content-Type': 'application/json', | ||
| }, | ||
| body: JSON.stringify({ username, password }), | ||
| }); | ||
|
|
||
| const data = await response.json(); | ||
|
|
||
| if (response.status === 200) { |
| if (response.status === 201) { | ||
| // Auto login after registration | ||
| loginUser(username, password); | ||
| } else { | ||
| const data = await response.json(); | ||
| const errorMessage = typeof data === 'object' ? JSON.stringify(data) : 'Registration failed'; | ||
| alert(`Registration failed: ${errorMessage}`); | ||
| } |
| if (response.status === 200) { | ||
| setAuthTokens(data); | ||
| setUser(jwtDecode(data.access)); | ||
| localStorage.setItem('authTokens', JSON.stringify(data)); |
| const logoutUser = () => { | ||
| setAuthTokens(null); | ||
| setUser(null); | ||
| localStorage.removeItem('authTokens'); |
| navigate('/login'); | ||
| } | ||
| } catch (err) { | ||
| console.error('Token refresh failed', err); |
| "rest_framework_simplejwt.authentication.JWTAuthentication", | ||
| ), | ||
| "DEFAULT_PERMISSION_CLASSES": [ | ||
| "rest_framework.permissions.AllowAny", |
| <label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: 500, color: 'var(--text)' }}>Username</label> | ||
| <input | ||
| type="text" | ||
| placeholder="Enter your username" | ||
| value={username} | ||
| onChange={(e) => setUsername(e.target.value)} | ||
| className="input-field" | ||
| required |
| <label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: 500, color: 'var(--text)' }}>Username</label> | ||
| <input | ||
| type="text" | ||
| placeholder="Choose a username" | ||
| value={username} | ||
| onChange={(e) => setUsername(e.target.value)} | ||
| className="input-field" | ||
| required | ||
| style={{ marginBottom: 0 }} | ||
| /> | ||
| </div> | ||
| <div> | ||
| <label style={{ display: 'block', marginBottom: '0.5rem', fontWeight: 500, color: 'var(--text)' }}>Password</label> | ||
| <input | ||
| type="password" | ||
| placeholder="Choose a password" | ||
| value={password} | ||
| onChange={(e) => setPassword(e.target.value)} |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
|
@copilot apply changes based on the comments in this thread |
…rmissions Agent-Logs-Url: https://github.com/ChicoState/cheat-sheet/sessions/c698eda3-f6c3-4ef7-ae11-c8fae0da2fd9 Co-authored-by: Davictory2003 <68972845+Davictory2003@users.noreply.github.com>
…ndly registration errors Agent-Logs-Url: https://github.com/ChicoState/cheat-sheet/sessions/c698eda3-f6c3-4ef7-ae11-c8fae0da2fd9 Co-authored-by: Davictory2003 <68972845+Davictory2003@users.noreply.github.com>
Applied all changes from the review thread (commits AuthContext.jsx:
settings.py / views.py:
Login.jsx / SignUp.jsx:
tests.py:
|
There was a problem hiding this comment.
Pull request overview
Implements JWT-based authentication (login + registration) across the Django REST backend and the React frontend, introducing routing/auth context on the client and SimpleJWT endpoints/permissions on the server.
Changes:
- Frontend: add
AuthContextprovider, login/signup pages, and React Router routes/navigation. - Backend: enable SimpleJWT, add token + refresh + register endpoints, and switch DRF default permissions to authenticated-by-default.
- Tests: update API tests to authenticate requests via a new fixture.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/main.jsx | Wraps the app in React Router + AuthProvider. |
| frontend/src/context/AuthContext.jsx | Adds JWT login/register/logout and periodic refresh logic. |
| frontend/src/components/Login.jsx | New login form component. |
| frontend/src/components/SignUp.jsx | New registration form component. |
| frontend/src/App.jsx | Adds routes and header UI for auth actions. |
| frontend/src/App.css | Updates .btn styling and hover behavior. |
| frontend/package.json | Adds jwt-decode and react-router-dom. |
| frontend/package-lock.json | Locks new frontend dependencies. |
| backend/requirements.txt | Adds djangorestframework-simplejwt. |
| backend/cheat_sheet/settings.py | Enables JWT auth + changes default permissions to IsAuthenticated. |
| backend/api/views.py | Adds custom token view + register view; allows anonymous health check. |
| backend/api/urls.py | Adds token/refresh/register routes. |
| backend/api/tests.py | Adds authenticated client fixture; updates tests to use it. |
| backend/api/serializers.py | Adds user registration serializer + custom token claims serializer. |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const data = await response.json().catch(() => ({ detail: 'Invalid server response' })); | ||
|
|
||
| if (response.ok) { | ||
| setAuthTokens(data); |
| ), | ||
| "DEFAULT_PERMISSION_CLASSES": [ | ||
| "rest_framework.permissions.AllowAny", | ||
| "rest_framework.permissions.IsAuthenticated", |
| <Routes> | ||
| <Route path="/" element={ | ||
| <CreateCheatSheet | ||
| initialData={cheatSheet} | ||
| onSave={handleSave} | ||
| onReset={handleReset} | ||
| isSaving={isSaving} | ||
| onCancel={() => {}} | ||
| /> | ||
| } /> | ||
| <Route path="/login" element={<Login />} /> | ||
| <Route path="/signup" element={<SignUp />} /> | ||
| </Routes> |
| @pytest.fixture | ||
| def auth_client(db): | ||
| """Authenticated API client (bypasses JWT for speed).""" | ||
| client = APIClient() | ||
| user = User.objects.create_user(username="testuser", password="testpass123") | ||
| client.force_authenticate(user=user) | ||
| return client |
| path('register/', views.RegisterView.as_view(), name='register'), | ||
|
|
||
| path("health/", views.health_check, name="health-check"), | ||
| path("classes/", views.get_classes, name="get-classes"), |
| class UserSerializer(serializers.ModelSerializer): | ||
| class Meta: | ||
| model = User | ||
| fields = ('id', 'username', 'password') | ||
| extra_kwargs = {'password': {'write_only': True}} | ||
|
|
||
| def create(self, validated_data): | ||
| user = User.objects.create_user( | ||
| username=validated_data['username'], | ||
| password=validated_data['password'] | ||
| ) |
|
@copilot apply changes based on the comments in this thread |
…word validation, auth endpoint tests Agent-Logs-Url: https://github.com/ChicoState/cheat-sheet/sessions/660affe3-e8c1-4d15-84ff-21145c2762ff Co-authored-by: Davictory2003 <68972845+Davictory2003@users.noreply.github.com>
Applied all changes from the review thread in commit
|
No description provided.