\section{CORS}

\begin{frame}[fragile]{Mi az a CORS?}
  \begin{block}{Cross-Origin Resource Sharing}
    \begin{itemize}
      \item Biztonsági mechanizmus, amely szabályozza a kereszt-eredet HTTP kéréseket
      \item A böngészők alapértelmezés szerint blokkolják a különböző eredetről (origin) érkező kéréseket
      \item Az \textbf{origin} = protokoll + domain + port
      \item CORS policy lehetővé teszi biztonságos erőforrás-megosztást különböző domainek között
    \end{itemize}
  \end{block}
  
  \begin{exampleblock}{Példák különböző originekre}
    \begin{itemize}
      \item \texttt{https://example.com:443} $\neq$ \texttt{http://example.com:80} (protokoll)
      \item \texttt{https://example.com} $\neq$ \texttt{https://api.example.com} (subdomain)
      \item \texttt{https://example.com:3000} $\neq$ \texttt{https://example.com:4000} (port)
    \end{itemize}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{Miért van szükség CORS-ra?}
  \begin{block}{Same-Origin Policy (SOP)}
    \begin{itemize}
      \item Böngészők biztonsági mechanizmusa
      \item Megakadályozza, hogy rosszindulatú scriptek más domainek adataihoz férjenek hozzá
      \item Alapértelmezés szerint csak azonos origin-ről tölthet le erőforrásokat
    \end{itemize}
  \end{block}
  
  \begin{alertblock}{Probléma}
    Modern alkalmazásoknál gyakori:
    \begin{itemize}
      \item Frontend: \texttt{http://localhost:3000}
      \item Backend API: \texttt{http://localhost:5000}
      \item Különböző origin $\rightarrow$ CORS hiba!
    \end{itemize}
  \end{alertblock}
\end{frame}

\begin{frame}[fragile]{CORS működése - Simple Request}
  \begin{block}{Egyszerű kérések}
    Olyan kérések, amelyek nem váltanak ki preflight kérést:
    \begin{itemize}
      \item Metódus: GET, HEAD, vagy POST
      \item Content-Type: \texttt{application/x-www-form-urlencoded}, \texttt{multipart/form-data}, \texttt{text/plain}
      \item Csak standard headerek
    \end{itemize}
  \end{block}
  
  \begin{exampleblock}{Kliens oldali kérés}
\small
\begin{lstlisting}[language=JavaScript]
fetch('http://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data));
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS működése - Preflight Request}
  \begin{block}{Preflight kérés}
    \begin{itemize}
      \item Komplex kérések előtt a böngésző automatikusan küld egy OPTIONS kérést
      \item Ellenőrzi, hogy a szerver engedélyezi-e a tényleges kérést
      \item PUT, DELETE, PATCH metódusok vagy custom headerek esetén
    \end{itemize}
  \end{block}
  
  \begin{columns}[T]
    \begin{column}{0.48\textwidth}
      \textbf{1. Preflight (OPTIONS)}
      \begin{itemize}
        \item Access-Control-Request-Method
        \item Access-Control-Request-Headers
      \end{itemize}
    \end{column}
    \begin{column}{0.48\textwidth}
      \textbf{2. Actual Request}
      \begin{itemize}
        \item A tényleges HTTP kérés
        \item Csak akkor megy el, ha a preflight engedélyező választ adott
      \end{itemize}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[fragile]{CORS Headers - Szerver válaszok}
  \begin{block}{Legfontosabb CORS headerek}
    \begin{description}
      \item[\texttt{Access-Control-Allow-Origin}] Megadja, mely origin-ek férhetnek hozzá
      \item[\texttt{Access-Control-Allow-Methods}] Engedélyezett HTTP metódusok
      \item[\texttt{Access-Control-Allow-Headers}] Engedélyezett HTTP headerek
      \item[\texttt{Access-Control-Allow-Credentials}] Cookie-k küldése engedélyezett-e
      \item[\texttt{Access-Control-Max-Age}] Preflight válasz cache ideje (másodperc)
    \end{description}
  \end{block}
\end{frame}

\begin{frame}[fragile]{CORS engedélyezése Express.js-ben - Manuális (1/2)}
  \begin{exampleblock}{Egyszerű megoldás - minden origin engedélyezése}
\small
\begin{lstlisting}[language=JavaScript]
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 
    'GET, POST, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 
    'Content-Type, Authorization');
  
  next();
});
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS engedélyezése Express.js-ben - Manuális (2/2)}
  \begin{exampleblock}{Preflight request kezelése}
\small
\begin{lstlisting}[language=JavaScript]
app.use((req, res, next) => {
  // Preflight request kezelése
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  next();
});
\end{lstlisting}
  \end{exampleblock}
  \begin{alertblock}{Figyelem!}
    A \texttt{*} wildcard nem biztonságos production környezetben!
  \end{alertblock}
\end{frame}

\begin{frame}[fragile]{CORS engedélyezése Express.js-ben - CORS csomag}
  \begin{block}{Telepítés}
\small
\begin{lstlisting}[language=bash]
npm install cors
\end{lstlisting}
  \end{block}
\end{frame}

\begin{frame}[fragile]{CORS csomag - Alapértelmezett használat}
  \begin{exampleblock}{Minden origin engedélyezése}
\small
\begin{lstlisting}[language=JavaScript]
const express = require('express');
const cors = require('cors');
const app = express();

// Minden origin engedélyezése
app.use(cors());

app.get('/api/data', (req, res) => {
  res.json({ message: 'CORS enabled!' });
});
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS konfiguráció - Specifikus origin}
  \begin{exampleblock}{Csak egy origin engedélyezése}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptions = {
  origin: 'https://example.com'
};

app.use(cors(corsOptions));
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS konfiguráció - Több origin (1/2)}
  \begin{exampleblock}{Engedélyezett origin-ek listája}
\small
\begin{lstlisting}[language=JavaScript]
const allowedOrigins = [
  'https://example.com',
  'https://app.example.com',
  'http://localhost:3000'
];
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS konfiguráció - Több origin (2/3)}
  \begin{exampleblock}{Dinamikus origin validáció}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptions = {
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  }
};
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS konfiguráció - Több origin (3/3)}
  \begin{exampleblock}{CORS middleware beállítása}
\small
\begin{lstlisting}[language=JavaScript]
// Korábban definiált corsOptions használata
app.use(cors(corsOptions));
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS konfiguráció - Credentials}
  \begin{block}{Mi az a credentials?}
    \begin{itemize}
      \item Cookie-k, HTTP authentication, client-side SSL certificates
      \item Alapértelmezés szerint a böngésző nem küldi el ezeket cross-origin kéréseknél
    \end{itemize}
  \end{block}
  
  \begin{exampleblock}{Szerver oldal - Express}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptions = {
  origin: 'https://example.com',
  credentials: true  // Cookie-k engedélyezése
};

app.use(cors(corsOptions));
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS Credentials - Kliens oldal}
  \begin{exampleblock}{Kliens oldal - Fetch API}
\small
\begin{lstlisting}[language=JavaScript]
fetch('https://api.example.com/data', {
  credentials: 'include'  // Cookie-k küldése
})
  .then(response => response.json())
  .then(data => console.log(data));
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS konfiguráció - További opciók (1/2)}
  \begin{exampleblock}{Részletes konfiguráció}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptions = {
  origin: 'https://example.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  exposedHeaders: ['X-Total-Count'],
  credentials: true
};
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS konfiguráció - További opciók (2/2)}
  \begin{exampleblock}{Cache és preflight beállítások}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptions = {
  // ...előző beállítások
  maxAge: 3600,  // Preflight cache 1 órára
  preflightContinue: false,
  optionsSuccessStatus: 204
};

app.use(cors(corsOptions));
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS-specifikus route-okhoz (1/3)}
  \begin{exampleblock}{Public endpoint CORS-szal}
\small
\begin{lstlisting}[language=JavaScript]
const express = require('express');
const cors = require('cors');
const app = express();

// Csak public API-hoz engedélyezve
app.get('/api/public', cors(), (req, res) => {
  res.json({ message: 'Public data' });
});
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS-specifikus route-okhoz (2/3)}
  \begin{exampleblock}{Protected endpoint CORS nélkül}
\small
\begin{lstlisting}[language=JavaScript]
// Protected endpoint CORS nélkül
app.get('/api/private', (req, res) => {
  res.json({ message: 'Private data' });
});
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS-specifikus route-okhoz (3/3)}
  \begin{exampleblock}{Specifikus CORS konfig egy route-hoz}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptionsRestricted = {
  origin: 'https://trusted.example.com'
};

app.post('/api/sensitive', 
  cors(corsOptionsRestricted), 
  (req, res) => {
    res.json({ message: 'Sensitive operation' });
  }
);
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS hibakezelés (1/2)}
  \begin{exampleblock}{Engedélyezett origin-ek}
\small
\begin{lstlisting}[language=JavaScript]
const allowedOrigins = [
  'https://example.com',
  'http://localhost:3000'
];
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS hibakezelés (2/3)}
  \begin{exampleblock}{Dinamikus origin ellenőrzés hibakezeléssel}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptions = {
  origin: (origin, callback) => {
    if (!origin) return callback(null, true);
    if (allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      const msg = `Origin ${origin} not allowed`;
      callback(new Error(msg), false);
    }
  },
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS hibakezelés (3/3)}
  \begin{exampleblock}{CORS konfiguráció befejezése}
\small
\begin{lstlisting}[language=JavaScript]
  // ...folytatás
  credentials: true
};
app.use(cors(corsOptions));
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{Gyakori CORS hibák és megoldások (1/2)}
  \begin{alertblock}{1. "No 'Access-Control-Allow-Origin' header"}
    \textbf{Ok:} A szerver nem küldi vissza a CORS headereket\\
    \textbf{Megoldás:} CORS middleware beállítása
  \end{alertblock}
  
  \begin{alertblock}{2. "Credentials + wildcard origin"}
    \textbf{Ok:} \texttt{credentials: true} és \texttt{origin: '*'} együttes használata\\
    \textbf{Megoldás:} Specifikus origin megadása credentials használatakor
  \end{alertblock}
\end{frame}

\begin{frame}[fragile]{Gyakori CORS hibák és megoldások (2/2)}
  \begin{alertblock}{3. "Preflight request failed"}
    \textbf{Ok:} OPTIONS kérés nem megfelelő válasza\\
    \textbf{Megoldás:} OPTIONS metódus explicit kezelése, megfelelő headerek
  \end{alertblock}
  
  \begin{alertblock}{4. "Custom headers blokkolva"}
    \textbf{Ok:} Custom header nincs az \texttt{allowedHeaders} listában\\
    \textbf{Megoldás:} Header hozzáadása az \texttt{allowedHeaders}-hoz
  \end{alertblock}
\end{frame}

\begin{frame}[fragile]{Best Practices}
  \begin{block}{Biztonsági ajánlások}
    \footnotesize
    \begin{enumerate}
      \item \textbf{Soha ne használj} \texttt{origin: '*'} production környezetben, főleg credentials esetén
      \item \textbf{Whitelist megközelítés}: csak konkrét, megbízható origin-ek engedélyezése
      \item \textbf{Minimális jogosultságok}: csak a szükséges metódusok és headerek engedélyezése
      \item \textbf{Credentials óvatos kezelése}: csak akkor engedélyezd, ha feltétlenül szükséges
      \item \textbf{maxAge beállítás}: csökkenti a preflight kérések számát
    \end{enumerate}
  \end{block}
\end{frame}

\begin{frame}[fragile]{Production konfiguráció}
  \begin{exampleblock}{Ajánlott production konfiguráció}
\small
\begin{lstlisting}[language=JavaScript]
const corsOptions = {
  origin: process.env.ALLOWED_ORIGINS?.split(',') 
    || [],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true,
  maxAge: 86400  // 24 óra
};
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS proxy fejlesztési környezetben (1/2)}
  \begin{block}{Development server proxy}
    Frontend fejlesztési szerverekben (pl. Vite, Create React App) konfigurálható proxy
  \end{block}
  
  \begin{exampleblock}{Vite proxy alapkonfiguráció (vite.config.js)}
\small
\begin{lstlisting}[language=JavaScript]
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true
      }
    }
  }
};
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}[fragile]{CORS proxy fejlesztési környezetben (2/2)}
  \begin{exampleblock}{Rewrite funkció hozzáadása}
\small
\begin{lstlisting}[language=JavaScript]
// Proxy konfigurációban:
proxy: {
  '/api': {
    rewrite: (path) => 
      path.replace(/^\/api/, '')
  }
}
\end{lstlisting}
  \end{exampleblock}
\end{frame}

\begin{frame}{Proxy működése}
  \begin{itemize}
    \item Kliens \texttt{http://localhost:3000} $\rightarrow$ \texttt{/api/users}
    \item Proxy továbbítja \texttt{http://localhost:5000} $\rightarrow$ \texttt{/users}
    \item Nincs CORS probléma, mert a böngésző szempontjából azonos origin
    \item Csak development használatra, production esetén backend CORS konfiguráció szükséges
  \end{itemize}
\end{frame}

\begin{frame}{Összefoglalás}
  \begin{block}{CORS lényege}
    \begin{itemize}
      \item Biztonsági mechanizmus a cross-origin kérések szabályozására
      \item Same-Origin Policy kiegészítése, nem helyettesítése
      \item Preflight requests komplex kérések előtt
      \item Explicit szerver-oldali engedélyezés szükséges
    \end{itemize}
  \end{block}
  
  \begin{block}{Implementáció}
    \begin{itemize}
      \item Express.js-ben: \texttt{cors} middleware csomag
      \item Konfiguráció: origin, methods, headers, credentials
      \item Fejlesztés: proxy használata, production: explicit whitelist
      \item Biztonsági szempontok elsődlegesek!
    \end{itemize}
  \end{block}
\end{frame}

