# How is Authentication Handled in TREK: JWT, OAuth, and Passkeys Explained

> Discover TREK's layered authentication: JWT tokens, OAuth/OpenID Connect, and Passkeys. Learn how this secure system handles user access and identity management.

- Repository: [Maurice/TREK](https://github.com/mauriceboe/TREK)
- Tags: deep-dive
- Published: 2026-07-03

---

**TREK uses a layered authentication strategy that combines JWT session tokens stored in HttpOnly cookies, OAuth/OpenID Connect for external identity providers, and WebAuthn Passkeys for passwordless authentication.**

The open-source TREK repository (`mauriceboe/TREK`) implements a modern, security-focused authentication system in its Node.js/TypeScript backend. By combining three distinct mechanisms—stateless JWT sessions, OAuth federation, and cryptographic Passkeys—the application provides flexible, phishing-resistant login options while maintaining strict session security through hardened cookie policies and middleware-based verification.

## JWT Session Tokens

TREK relies on **signed JWTs** for stateless session management. Rather than storing session data server-side, the backend issues compact tokens that carry user identity and expire automatically.

### Token Generation in the OIDC Service

In [`server/src/services/oidcService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/oidcService.ts), the `generateToken` function creates signed JWTs using the `jsonwebtoken` library. When a user successfully authenticates via OAuth or Passkeys, the system calls `jwt.sign()` with a HS256 algorithm and a 5-minute expiration:

```typescript
import jwt from 'jsonwebtoken';
import { JWT_SECRET } from '@/config';

const jwtPayload = { id: userId, purpose: 'auth' };
const jwtToken = jwt.sign(jwtPayload, JWT_SECRET, {
  algorithm: 'HS256',
  expiresIn: '5m',
});

```

The `JWT_SECRET` is loaded from environment variables (see `server/.env.example`) and should be rotated regularly according to the guidelines in [`wiki/Encryption-Key-Rotation.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Encryption-Key-Rotation.md).

### Verification in the Auth Middleware

Every protected route passes through the global auth middleware located in [`server/src/middleware/auth.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/middleware/auth.ts). This middleware extracts the `trek_session` cookie, verifies the signature using `jwt.verify()`, and attaches the decoded user object to `req.user`:

```typescript
import jwt from 'jsonwebtoken';
import { JWT_SECRET } from '@/config';

export function authMiddleware(req, res, next) {
  const token = req.cookies?.trek_session;
  if (!token) return res.status(401).send('Missing auth cookie');

  try {
    const payload = jwt.verify(token, JWT_SECRET);
    req.user = { id: payload.id };
    next();
  } catch (err) {
    return res.status(401).send('Invalid or expired token');
  }
}

```

If verification fails, the middleware returns a 401 status immediately, preventing unauthenticated access to downstream resources.

## OAuth and OpenID Connect

For users preferring external identity providers, TREK implements the **OAuth 2.0 authorization code flow** with OpenID Connect extensions.

### Authorization Code Flow

When a user initiates login, the frontend redirects to `/api/auth/oidc/login`, which triggers the OIDC handshake. The [`server/src/services/oidcService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/oidcService.ts) file handles the provider redirection, while [`server/src/services/oauthService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/oauthService.ts) contains helper functions for client-secret management and scope definition.

### Token Exchange and JWT Creation

After the user authenticates with a provider like Google or Microsoft, the OIDC controller receives the authorization code and exchanges it for an ID token. The service extracts the subject identifier (`sub`), generates a TREK-specific JWT, and calls `setAuthCookie` to establish the session:

```typescript
export async function oidcCallback(req, res) {
  const { code } = req.body;
  const tokenInfo = await oidcProvider.exchangeCodeForToken(code);
  const jwtPayload = { id: tokenInfo.sub, purpose: 'auth' };
  const jwtToken = jwt.sign(jwtPayload, JWT_SECRET, {
    algorithm: 'HS256',
    expiresIn: '5m',
  });
  setAuthCookie(res, jwtToken, req);
  res.json({ token: jwtToken });
}

```

Client-side invocation requires the `credentials: 'include'` flag to ensure the HttpOnly cookie is transmitted:

```typescript
await fetch('/api/auth/oidc/login', {
  method: 'POST',
  credentials: 'include',
});

```

## Passkeys and WebAuthn

TREK supports **FIDO2/WebAuthn Passkeys** for passwordless, phishing-resistant authentication using public-key cryptography stored on user devices.

### Registration and Validation

The [`server/src/services/passkeyService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/passkeyService.ts) file manages credential registration and assertion verification. When a user opts for Passkey login, the frontend uses the WebAuthn API to generate a cryptographic signature:

```typescript
const credential = await navigator.credentials.get({ publicKey: options });
await fetch('/api/auth/passkey/login', {
  method: 'POST',
  body: JSON.stringify(credential),
  credentials: 'include',
});

```

### JWT Integration for Passkey Sessions

Upon receiving the assertion, the Passkey service validates the signature using `verifyWebAuthnAssertion()`, then issues a standard JWT identical to the OAuth flow. This design ensures that Passkey sessions integrate seamlessly with the existing cookie-based session infrastructure:

```typescript
import { verifyWebAuthnAssertion } from '@/utils/webauthn';

export async function passkeyLogin(req, res) {
  const assertion = req.body;
  const user = await verifyWebAuthnAssertion(assertion);
  const jwtToken = jwt.sign({ id: user.id, purpose: 'auth' }, JWT_SECRET, {
    algorithm: 'HS256',
    expiresIn: '5m',
  });
  setAuthCookie(res, jwtToken, req);
  res.json({ token: jwtToken });
}

```

## Security Configuration and Cookie Hardening

TREK enforces strict transport security through cookie flags and additional MFA policies.

### HttpOnly and SameSite Policies

The `setAuthCookie` implementation (called from both OIDC and Passkey controllers) configures the `trek_session` cookie with `HttpOnly`, `SameSite=Strict`, and `Secure` attributes. This prevents XSS attacks and CSRF vectors while ensuring the token only transmits over HTTPS.

### Multi-Factor Enforcement

After initial authentication, the `mfaPolicy` middleware in [`server/src/middleware/mfaPolicy.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/middleware/mfaPolicy.ts) may require additional verification before granting full resource access. This operates as a secondary layer after the JWT middleware, checking whether the authenticated user has satisfied MFA requirements based on policy rules.

## Summary

- **JWT-based sessions** provide stateless, signed tokens (HS256 algorithm, 5-minute expiry) stored in HttpOnly cookies named `trek_session`.
- **OAuth/OpenID Connect** integration in [`server/src/services/oidcService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/oidcService.ts) supports external identity providers via the authorization code flow, converting provider tokens into TREK-session JWTs.
- **Passkey authentication** via [`server/src/services/passkeyService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/passkeyService.ts) enables passwordless login using WebAuthn, reusing the same JWT cookie infrastructure for session continuity.
- **Security hardening** includes `SameSite=Strict` cookies, MFA policy enforcement in [`server/src/middleware/mfaPolicy.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/middleware/mfaPolicy.ts), and documented JWT secret rotation procedures.

## Frequently Asked Questions

### What token format does TREK use for sessions?

TREK uses **signed JWTs** (JSON Web Tokens) with the HS256 algorithm. The tokens contain a user ID and purpose claim (`auth`), expire after 5 minutes, and are stored in an HttpOnly cookie named `trek_session`. The global auth middleware verifies these tokens on every request using the `JWT_SECRET` defined in [`server/src/config.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/config.ts).

### How does TREK handle OAuth providers like Google?

TREK implements the **OAuth 2.0 authorization code flow** with OpenID Connect. The [`server/src/services/oidcService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/oidcService.ts) file handles the exchange of authorization codes for ID tokens, extracts the user identity from the provider's response, and generates a TREK-specific JWT. This allows seamless integration with Google, Microsoft, and other OIDC-compliant providers without storing provider credentials locally.

### Are Passkeys supported for passwordless login?

Yes. TREK fully supports **FIDO2/WebAuthn Passkeys** through [`server/src/services/passkeyService.ts`](https://github.com/mauriceboe/TREK/blob/main/server/src/services/passkeyService.ts). Users can register public-key credentials on their devices and authenticate without passwords. The service validates WebAuthn assertions cryptographically, then issues a standard JWT that flows through the same cookie-based session system as OAuth logins, ensuring consistent security policies across all authentication methods.

### How can I rotate the JWT secret without logging users out?

The repository includes a dedicated wiki page at [`wiki/Encryption-Key-Rotation.md`](https://github.com/mauriceboe/TREK/blob/main/wiki/Encryption-Key-Rotation.md) that describes safe rotation procedures for `JWT_SECRET`. Because TREK uses stateless JWTs stored in cookies, rotating the secret requires careful timing—typically issuing tokens with a new secret while maintaining verification capabilities for the old secret during a transition window—to prevent immediate session termination for active users.