# How Auth works

This document explains how authentication works in the application.

## Overview: Refresh Token + Access Token Approach

Our authentication system uses two types of tokens:

1. **Access Token**: Short-lived token (valid for 15 minutes) used to authenticate users for protected API routes. These tokens are kept **only in memory** and never stored in persistent storage.
2. **Refresh Token**: Long-lived token (valid for 90 days) used only to obtain a new pair of access and refresh tokens when the access token expires. This token is stored in browser's local storage.

This approach follows security best practices by minimizing the exposure of the more powerful access token while providing seamless user experience.

## Authentication Flow

1. **Initial Login**:
   * User logs in with credentials (email/password) or via OAuth provider
   * Server validates credentials and creates a token pair
   * Access token is kept in memory (JavaScript variable)
   * Refresh token is stored in local storage
2. **Authenticated Requests**:
   * For each API request, the access token is attached in the Authorization header
   * Server validates the token and processes the request
3. **Token Refresh Flow**:
   * When access token expires (or is about to expire), client uses the refresh token to get a new token pair
   * If refresh is successful, new access token is kept in memory and new refresh token replaces the old one in local storage
   * This creates a persistent login experience across page refreshes
4. **Token Rotation**:
   * For security, we implement refresh token rotation - each time a refresh token is used, it's replaced with a new one
   * This helps prevent token replay attacks
   * If a refresh token is used more than once (potentially indicating it was leaked), the system invalidates the entire token family

For more detailed information on refresh token rotation, see the [Auth0 documentation](https://auth0.com/docs/secure/tokens/refresh-tokens/refresh-token-rotation).

## Key Files

### Client-side (ClojureScript)

* **src/cljs/saas/auth.cljs**: Contains the core authentication logic for the front-end including:
  * Token management
  * Login/logout functions
  * Token refresh logic
  * OAuth authentication

### Server-side (Clojure)

* **src/clj/saas/web/controllers/auth/handlers.clj**: Contains server-side authentication handlers:
  * User registration
  * Login
  * Token generation
  * Refresh token rotation logic
  * OAuth providers integration

## Protecting API Routes

API routes that require authentication are protected using middleware:

```clojure
;; Example from src/clj/saas/web/routes/api.clj
["" {:middleware [[mw/wrap-jwt-auth]]}
  ;; Public routes that only need JWT parsing but don't require authentication
  
  ["/me" {:middleware [[mw/wrap-authenticated]]}
   ;; Protected routes that require valid authentication
   ]]
```

The application uses two middleware functions:

1. **wrap-jwt-auth**: Decodes the JWT token and adds `:claims` to the request object
2. **wrap-authenticated**: Ensures that a user is authenticated by checking for the existence of `:sub` in claims

## Accessing User Information in Route Handlers

When handling requests for authenticated routes, you can access the user information from the token claims:

```clojure
(defn get-user-data [req]
  (let [claims (:claims req)
        user-id (:sub claims)]
    ;; Access other claims like :email, :role, etc.
    ;; Process request with user context
    ))
```

Common claims available in the token:

* `:sub`: The subject (user ID)
* `:exp`: Expiration time
* `:iat`: Issued at time
* Other custom claims depending on your application

## Refresh Token Persistence

Login persistence works because:

1. On page load/refresh, the system checks for a refresh token in local storage
2. If found, it uses this token to request a new token pair from the server
3. This happens automatically before the user interacts with the application
4. As long as the refresh token is valid, the user remains logged in without having to re-enter credentials

This approach balances security (access tokens are ephemeral and never stored) with user experience (seamless login persistence through refresh tokens).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://shipclojure.gitbook.io/shipclojure-docs/auth/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
