Skip to content

Commit 71c1444

Browse files
committed
Implemented Session Cookies with CSRF Protection
1 parent b462485 commit 71c1444

File tree

34 files changed

+113
-61
lines changed

34 files changed

+113
-61
lines changed

code/client/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const firebaseConfig = {
1111
};
1212

1313
const app = initializeApp(firebaseConfig);
14+
1415
const auth = getAuth(app);
1516
const googleAuthProvider = new GoogleAuthProvider();
1617
const githubAuthProvider = new GithubAuthProvider();

code/client/src/App.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@ import Header from '@ui/components/header/Header';
44
import Workspace from '@ui/pages/workspace/Workspace';
55
import NotFound from '@ui/pages/notfound/NotFound';
66
import './App.scss';
7-
import { ErrorProvider } from '@ui/contexts/error/ErrorContext';
7+
import { ErrorProvider } from '@/contexts/error/ErrorContext';
88
import Sidebar from '@ui/components/sidebar/Sidebar';
9-
import { WorkspaceProvider } from '@ui/contexts/workspace/WorkspaceContext';
9+
import { WorkspaceProvider } from '@/contexts/workspace/WorkspaceContext';
1010
import Workspaces from '@ui/pages/workspaces/Workspaces';
11-
import { CommunicationProvider } from '@ui/contexts/communication/CommunicationContext';
11+
import { CommunicationProvider } from '@/contexts/communication/CommunicationContext';
1212
import Home from '@ui/pages/home/Home';
13-
import AuthProvider from '@ui/contexts/auth/AuthContext';
13+
import AuthProvider from '@/contexts/auth/AuthContext';
1414
import Profile from '@ui/pages/profile/Profile';
1515
import Landing from '@ui/pages/landing/Landing';
1616

1717
function App() {
1818
return (
1919
<div className="app">
2020
<ErrorProvider>
21-
<AuthProvider>
22-
<CommunicationProvider>
23-
<Router>
21+
<CommunicationProvider>
22+
<Router>
23+
<AuthProvider>
2424
<Header />
2525
<div className="content">
2626
<Routes>
@@ -66,9 +66,9 @@ function App() {
6666
<Route path="*" element={<NotFound />} />
6767
</Routes>
6868
</div>
69-
</Router>
70-
</CommunicationProvider>
71-
</AuthProvider>
69+
</AuthProvider>
70+
</Router>
71+
</CommunicationProvider>
7272
</ErrorProvider>
7373
</div>
7474
);

code/client/src/ui/contexts/auth/AuthContext.tsx renamed to code/client/src/contexts/auth/AuthContext.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import Cookies from 'js-cookie';
22
import { auth, githubAuthProvider, googleAuthProvider } from '@config';
33
import { createContext, ReactNode, useEffect, useState } from 'react';
4-
import { signInWithPopup, signOut, User, type AuthProvider as Provider } from 'firebase/auth';
5-
import useError from '@ui/contexts/error/useError';
4+
import { signInWithPopup, signOut, User, type AuthProvider as Provider, inMemoryPersistence } from 'firebase/auth';
5+
import useError from '@/contexts/error/useError';
66
import useAuthService from '@services/auth/useAuthService';
7+
import { useNavigate } from 'react-router-dom';
78

89
export type AuthContextType = {
910
currentUser: User | null;
@@ -29,14 +30,17 @@ export function AuthProvider({ children }: AuthProviderProps) {
2930
const [currentUser, setCurrentUser] = useState<User | null>(null);
3031
const [loading, setLoading] = useState(true);
3132
const { publishError } = useError();
32-
const { registerUser } = useAuthService();
33+
const { sessionLogin, sessionLogout } = useAuthService();
34+
const navigate = useNavigate();
3335

3436
const loginWithProvider = async (provider: Provider) => {
3537
try {
38+
auth.setPersistence(inMemoryPersistence); // for httpOnly cookies, do not persist any state client side
3639
const { user } = await signInWithPopup(auth, provider);
37-
await registerUser(user.uid, { name: user.displayName!, email: user.email! });
38-
const token = await user.getIdToken(true);
39-
Cookies.set('token', token, { expires: 1, secure: true, sameSite: 'Strict' });
40+
const userInfo = { name: user.displayName!, email: user.email! };
41+
const idToken = await user.getIdToken();
42+
const csrfToken = Cookies.get('csrfToken')!;
43+
await sessionLogin(idToken, csrfToken, user.uid, userInfo);
4044
} catch (e) {
4145
publishError(e as Error);
4246
}
@@ -47,15 +51,16 @@ export function AuthProvider({ children }: AuthProviderProps) {
4751
const loginWithGithub = () => loginWithProvider(githubAuthProvider);
4852

4953
const logout = async () => {
54+
console.log('logging out');
55+
await sessionLogout();
5056
await signOut(auth);
51-
Cookies.remove('token');
52-
window.location.href = '/';
57+
navigate('/');
5358
};
5459

5560
const deleteAccount = async () => {
61+
await sessionLogout();
5662
await currentUser?.delete();
57-
Cookies.remove('token');
58-
window.location.href = '/';
63+
navigate('/');
5964
};
6065

6166
useEffect(() => {

code/client/src/ui/contexts/auth/useAuth.ts renamed to code/client/src/contexts/auth/useAuth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useContext } from 'react';
2-
import { AuthContext, AuthContextType } from '@ui/contexts/auth/AuthContext';
2+
import { AuthContext, AuthContextType } from '@/contexts/auth/AuthContext';
33

44
export function useAuth(): AuthContextType {
55
return useContext(AuthContext);

code/client/src/ui/contexts/communication/useCommunication.ts renamed to code/client/src/contexts/communication/useCommunication.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Communication } from '@services/communication/communication';
22
import { useContext } from 'react';
3-
import { CommunicationContext } from '@ui/contexts/communication/CommunicationContext';
3+
import { CommunicationContext } from '@/contexts/communication/CommunicationContext';
44

55
export function useCommunication(): Communication {
66
return useContext(CommunicationContext);

code/client/src/ui/contexts/error/useError.ts renamed to code/client/src/contexts/error/useError.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useContext } from 'react';
2-
import { ErrorContext } from '@ui/contexts/error/ErrorContext';
2+
import { ErrorContext } from '@/contexts/error/ErrorContext';
33

44
const useError = () => useContext(ErrorContext);
55

code/client/src/ui/contexts/workspace/WorkspaceContext.tsx renamed to code/client/src/contexts/workspace/WorkspaceContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import * as React from 'react';
22
import { useState, createContext, useEffect } from 'react';
33
import { WorkspaceMeta } from '@notespace/shared/src/workspace/types/workspace';
4-
import { useCommunication } from '@ui/contexts/communication/useCommunication';
5-
import useError from '@ui/contexts/error/useError';
4+
import { useCommunication } from '@/contexts/communication/useCommunication';
5+
import useError from '@/contexts/error/useError';
66
import { useParams } from 'react-router-dom';
77
import useWorkspaceService from '@services/workspace/useWorkspaceService';
88
import useResources from '@domain/workspaces/useResources';

code/client/src/ui/contexts/workspace/useWorkspace.ts renamed to code/client/src/contexts/workspace/useWorkspace.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useContext } from 'react';
2-
import { WorkspaceContext } from '@ui/contexts/workspace/WorkspaceContext';
2+
import { WorkspaceContext } from '@/contexts/workspace/WorkspaceContext';
33

44
const useWorkspace = () => useContext(WorkspaceContext);
55

0 commit comments

Comments
 (0)