\section{JWT}

\begin{frame}[shrink=15]{Mi az a JWT?}
  \begin{block}{JSON Web Token (RFC 7519)}
    Kompakt, önálló token információ biztonságos továbbításához.
  \end{block}
  \begin{itemize}
    \item Digitálisan aláírt, Base64URL kódolt
    \item Használat: authentikáció, stateless session
    \item \textbf{NEM} titkosított - payload olvasható!
  \end{itemize}
\end{frame}

\begin{frame}[fragile,shrink=15]{JWT formátum}
  \texttt{\textcolor{red}{HEADER}.\textcolor{purple}{PAYLOAD}.\textcolor{blue}{SIGNATURE}}
  \begin{tiny}
  \begin{verbatim}
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZ
SI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36P
  \end{verbatim}
  \end{tiny}
  \begin{itemize}
    \item \textcolor{red}{Header}: Algoritmus + token típus
    \item \textcolor{purple}{Payload}: Claims (user adatok)
    \item \textcolor{blue}{Signature}: Integritás védelem
  \end{itemize}
\end{frame}

\begin{frame}[fragile,shrink=15]{JWT Header \& Payload}
  \begin{columns}
    \begin{column}{0.48\textwidth}
      \textbf{Header:}
      \begin{verbatim}
{
  "alg": "HS256",
  "typ": "JWT"
}
      \end{verbatim}
    \end{column}
    \begin{column}{0.48\textwidth}
      \textbf{Payload:}
      \begin{verbatim}
{
  "sub": "1234",
  "name": "John",
  "iat": 1516239022,
  "exp": 1516242622
}
      \end{verbatim}
    \end{column}
  \end{columns}
  \begin{alertblock}{Fontos}
    Ne tároljunk jelszót payload-ban!
  \end{alertblock}
\end{frame}

\begin{frame}[fragile,shrink=15]{JWT Signature}
  \begin{verbatim}
HMACSHA256(
  base64(header) + "." + base64(payload),
  secret
)
  \end{verbatim}
  \begin{columns}
    \begin{column}{0.48\textwidth}
      \textbf{HMAC:} Egy kulcs, gyors (HS256)
    \end{column}
    \begin{column}{0.48\textwidth}
      \textbf{RSA:} Privát+publikus, biztonságosabb (RS256)
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[fragile,shrink=20]{JWT generálás Node.js}
  \begin{verbatim}
const jwt = require('jsonwebtoken');

const payload = { userId: user.id, role: user.role };

const token = jwt.sign(
  payload,
  process.env.JWT_SECRET,
  { expiresIn: '1h' }
);

res.json({ token });
  \end{verbatim}
\end{frame}

\begin{frame}[fragile,shrink=20]{JWT validálás Node.js}
  \begin{verbatim}
const token = req.headers.authorization?.split(' ')[1];

if (!token) return res.status(401).json({ error: 'No token' });

try {
  const decoded = jwt.verify(token, process.env.JWT_SECRET);
  req.user = decoded;
  next();
} catch (err) {
  res.status(403).json({ error: 'Invalid' });
}
  \end{verbatim}
\end{frame}

\begin{frame}[fragile,shrink=20]{JWT middleware}
  \begin{verbatim}
const authJWT = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).send('Token required');
  
  jwt.verify(token, process.env.JWT_SECRET, (err, user) => {
    if (err) return res.status(403).send('Invalid');
    req.user = user;
    next();
  });
};

app.get('/protected', authJWT, (req, res) => {
  res.json({ data: 'Secret', user: req.user });
});
  \end{verbatim}
\end{frame}

\begin{frame}[shrink=15]{JWT vs Session}
  \begin{columns}
    \begin{column}{0.48\textwidth}
      \textbf{JWT:}
      \begin{itemize}
        \item Stateless
        \item Skálázható
        \item Cross-domain
        \item Nehéz visszavonni
        \item Token méret
      \end{itemize}
    \end{column}
    \begin{column}{0.48\textwidth}
      \textbf{Session:}
      \begin{itemize}
        \item Stateful
        \item Szerver tárolja
        \item Könnyű visszavonás
        \item Nehezebb skálázás
        \item Kis cookie
      \end{itemize}
    \end{column}
  \end{columns}
\end{frame}

\begin{frame}[shrink=15]{Access \& Refresh Token}
  \begin{block}{Két token stratégia}
    \textbf{Access token}: Rövid élet (15 perc), API hozzáférés\\
    \textbf{Refresh token}: Hosszú élet (7 nap), új access token generálás
  \end{block}
  \begin{enumerate}
    \item Login $\to$ Access + Refresh token
    \item API kérés Access token-nel
    \item Access lejár $\to$ Refresh-el új Access-t kér
    \item Refresh lejár $\to$ Újra login
  \end{enumerate}
\end{frame}

\begin{frame}[fragile,shrink=20]{Refresh Token példa}
  \begin{verbatim}
app.post('/refresh', (req, res) => {
  const { refreshToken } = req.body;
  if (!refreshToken) return res.sendStatus(401);
  
  jwt.verify(refreshToken, REFRESH_SECRET, (err, user) => {
    if (err) return res.sendStatus(403);
    
    const accessToken = jwt.sign(
      { userId: user.userId },
      ACCESS_SECRET,
      { expiresIn: '15m' }
    );
    res.json({ accessToken });
  });
});
  \end{verbatim}
\end{frame}

\begin{frame}[shrink=15]{JWT Security Best Practices}
  \begin{enumerate}
    \item Rövid lejárat (15-60 perc)
    \item Erős secret kulcs (min 256 bit)
    \item HTTPS kötelező
    \item Ne tároljunk érzékeny adatot payload-ban
    \item Validáld mindig az \texttt{exp} és \texttt{iat} claim-eket
    \item Használj RS256-ot HS256 helyett production-ben
    \item Refresh token rotation
    \item Token blacklist megfontolása
  \end{enumerate}
\end{frame}
