# Authentication Guide

This comprehensive guide covers the complete authentication system for the radFi backend API, including JWT tokens, BIP322 signature verification, error handling, and frontend integration.

## Overview

The authentication system uses BIP322 signature verification combined with JWT tokens to provide secure, stateless authentication. Users authenticate by signing a message with their Bitcoin wallet, and the system returns JWT access and refresh tokens for subsequent API calls.

### Key Features

* **BIP322 Signature Verification**: Users sign messages with their Bitcoin wallet
* **JWT Token System**: Access tokens (10 minutes) and refresh tokens (7 days)
* **Stateless Authentication**: No server-side session storage required
* **Comprehensive Error Handling**: 8 specific error codes for different failure scenarios
* **Wallet Integration**: Automatic wallet creation during authentication

## Authentication Flow

{% stepper %}
{% step %}

### User Authentication (Initial)

Frontend signs a message with BIP322 and sends the signature and related data to the backend. The backend verifies the BIP322 signature, creates or finds the wallet, generates JWT access and refresh tokens, and returns them to the client.

Request sent from client to API:

* POST /api/auth/authenticate with body:
  * message
  * signature
  * address
  * publicKey

Response includes:

* accessToken (expires in 10 minutes)
* refreshToken (expires in 7 days)
* tradingAddress
* wallet object
  {% endstep %}

{% step %}

### Protected API Calls

For protected endpoints, the frontend includes the access token in the Authorization header:

Authorization: Bearer

The backend validates the JWT and, if valid, processes the request (e.g., creating transactions).
{% endstep %}

{% step %}

### Token Refresh (When Access Token Expires)

When the access token expires, the client sends the refresh token to obtain a new access token:

* POST /api/auth/refresh-token with body:
  * refreshToken

On success, the backend returns a new accessToken (and wallet info).
{% endstep %}
{% endstepper %}

## API Endpoints

### Public Endpoints (No Authentication Required)

| Method | Endpoint                   | Description                                  |
| ------ | -------------------------- | -------------------------------------------- |
| POST   | `/api/auth/authenticate`   | Initial authentication with BIP322 signature |
| POST   | `/api/auth/refresh-token`  | Refresh expired access token                 |
| POST   | `/api/wallets`             | Create new wallet                            |
| GET    | `/api/wallets`             | List wallets                                 |
| GET    | `/api/wallets/details/:id` | Get wallet details                           |

### Protected Endpoints (JWT Required)

| Method | Endpoint                                  | Description                |
| ------ | ----------------------------------------- | -------------------------- |
| POST   | `/api/transactions`                       | Create transaction         |
| POST   | `/api/transactions/sign`                  | Sign transaction           |
| POST   | `/api/etch/commit-tx`                     |                            |
| POST   | `/api/etch/submit-etching`                | Submit rune etching        |
| POST   | `/api/etch/build-get-reward-tx`           |                            |
| POST   | `/api/etch/sign-reward-tx`                |                            |
| POST   | `/api/diamond-hand/request-claim-rewards` | Claim diamond hand rewards |
| POST   | `/api/diamond-hand/sign`                  |                            |
| POST   | `/api/vm-transactions`                    | Create VM transaction      |
| POST   | `/api/vm-transactions/sign`               | Create VM transaction      |
| POST   | `/api/refunds`                            | Create refund              |
| POST   | `/api/refunds/sign`                       | Create refund              |

## Error Codes

### Error Code Structure

All authentication errors follow the pattern `4xxx` where:

* `4` indicates authentication/authorization errors
* `xxx` is a sequential number for specific error types

### Error Response Format

```json
{
    "code": "4xxx",
    "message": "auth.errorType",
    "details": "Human-readable error description",
    "additionalData": {} // Optional additional context
}
```

### Error Codes Reference

| Code | Error Type                       | Description                                      | HTTP Status      |
| ---- | -------------------------------- | ------------------------------------------------ | ---------------- |
| 4002 | Invalid Token                    | JWT token is malformed or cannot be parsed       | 401 Unauthorized |
| 4003 | Token Expired                    | JWT token has passed its expiration time         | 401 Unauthorized |
| 4004 | Token Not Found                  | No Authorization header or Bearer token provided | 401 Unauthorized |
| 4005 | Invalid Refresh Token            | Refresh token is invalid, expired, or wrong type | 400 Bad Request  |
| 4006 | User Not Found                   | JWT is valid but user doesn't exist in database  | 401 Unauthorized |
| 4007 | Signature Verification Failed    | BIP322 signature verification process fails      | 400 Bad Request  |
| 4008 | Wallet Creation Failed           | Wallet creation fails during authentication      | 400 Bad Request  |
| 4009 | Invalid Standard Taproot Address | Address doesn't match expected taproot format    | 400 Bad Request  |

### Detailed Error Descriptions

#### 4002 - Invalid Token

* Message: `auth.invalidToken`
* Details: `Invalid or malformed JWT token`
* When: JWT token is malformed or cannot be parsed
* HTTP Status: 401 Unauthorized

#### 4003 - Token Expired

* Message: `auth.tokenExpired`
* Details: `JWT token has expired`
* When: JWT token has passed its expiration time
* HTTP Status: 401 Unauthorized

#### 4004 - Token Not Found

* Message: `auth.tokenNotFound`
* Details: `JWT token not provided in request`
* When: No Authorization header or Bearer token provided
* HTTP Status: 401 Unauthorized

#### 4005 - Invalid Refresh Token

* Message: `auth.invalidRefreshToken`
* Details: `Invalid or expired refresh token`
* When: Refresh token is invalid, expired, or wrong type
* HTTP Status: 400 Bad Request

#### 4006 - User Not Found

* Message: `auth.userNotFound`
* Details: `User not found for the provided token`
* When: JWT is valid but user doesn't exist in database
* HTTP Status: 401 Unauthorized

#### 4007 - Signature Verification Failed

* Message: `auth.signatureVerificationFailed`
* Details: `BIP322 signature verification failed`
* When: BIP322 signature verification process fails
* HTTP Status: 400 Bad Request

#### 4008 - Wallet Creation Failed

* Message: `auth.walletCreationFailed`
* Details: `Failed to create wallet during authentication`
* When: Wallet creation fails during authentication process
* HTTP Status: 400 Bad Request

#### 4009 - Invalid Standard Taproot Address

* Message: `auth.invalidStandardTaprootAddress`
* Details: `Address is not a valid standard taproot address`
* When: Address doesn't match the expected taproot format
* HTTP Status: 400 Bad Request

## Frontend Implementation

### Header Format

All protected API calls require the following header:

```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

### Authentication APIs

#### API: Initial Authentication

Endpoint: `POST /api/auth/authenticate`\
Purpose: Get initial JWT tokens after BIP322 signature verification

Request Body example:

```json
{
    "message": "1759413612750",
    "signature": "AUE5z8iM+Y3M6ey8j7zluhzf75R...XZ+nQH7lRAQ==",
    "address": "bc1py270r0u9y8248s45tpe479j8w...xspezlzu",
    "publicKey": "0324e27cae4cec8374d1c970caf...7c03"
}
```

Response (Success 200) example:

```json
{
    "success": true,
    "data": {
        "tradingAddress": "bc1p...",
        "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "wallet": {
            "_id": "68e1fc5a73513ef283c17b2f",
            "deletedAt": null,
            "tradingAddress": "bc1p...",
            "userAddress": "bc1pge...",
            "userPublicKey": "4ae4...",
            "requiredSignNumber": 2,
            "pubKeysNum": 2,
            "agreeTerm": false,
            "createdAt": 1759640666632,
            "updatedAt": 1759640666632,
            "__v": 0
        }
    },
    "message": "Authentication successful. AccessToken expires in 10 minutes. RefreshToken expires in 7 days."
}
```

Response (Error 400) example:

```json
{
    "code": "4007",
    "message": "auth.signatureVerificationFailed",
    "details": "BIP322 signature verification failed"
}
```

#### API: Refresh Access Token

Endpoint: `POST /api/auth/refresh-token`\
Purpose: Get new access token when current one expires

Request Body example:

```json
{
    "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
```

Response (Success 200) example:

```json
{
    "success": true,
    "data": {
        "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
         "wallet": {
            "_id": "68e1fc5a73513ef283c17b2f",
            "deletedAt": null,
            "tradingAddress": "bc1p...",
            "userAddress": "bc1pge...",
            "userPublicKey": "4ae4...",
            "requiredSignNumber": 2,
            "pubKeysNum": 2,
            "agreeTerm": false,
            "createdAt": 1759640666632,
            "updatedAt": 1759640666632,
            "__v": 0
        }
    },
    "message": "New access token generated successfully"
}
```

Response (Error 400) example:

```json
{
    "code": "4005",
    "message": "auth.invalidRefreshToken",
    "details": "Invalid or expired refresh token"
}
```

### cURL Examples

```bash
# Authenticate
curl -X POST http://localhost:8100/api/auth/authenticate \
  -H "Content-Type: application/json" \
  -d '{
    "message": "1759413612750",
    "signature": "AUE5z8iM+Y3M6e...==",
    "address": "bc1py27...zlzu",
    "publicKey": "0324e27cae...7c03"
  }'

# Make protected API call
curl -X POST http://localhost:8100/api/transactions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{"userAddress": "bc1p...", "type": "SWAP"}'

# Refresh token
curl -X POST http://localhost:8100/api/auth/refresh-token \
  -H "Content-Type: application/json" \
  -d '{"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}'
```

## Testing

### Test Scripts

Use the provided test scripts to verify the authentication system:

```bash
# Test authentication endpoint
node test/auth/scripts/test-authenticate.js

# Test JWT guard with invalid tokens
node test/auth/scripts/test-jwt-guard.js

# Test protected APIs with valid JWT
node test/auth/scripts/test-with-valid-jwt.js

# Test all authentication error codes
node test/auth/scripts/test-auth-errors.js

# Comprehensive test of all protected APIs
node test/auth/scripts/test-protected-apis.js

# Run demo script
./test/auth/scripts/demo-protected-apis.sh
```

### Test Coverage

The test suite covers:

* ✅ Authentication endpoint functionality
* ✅ JWT token validation
* ✅ Protected API access
* ✅ Error code verification
* ✅ Token refresh functionality
* ✅ Multiple authentication scenarios

## Reference Tables

### Endpoint Summary

| Category       | Endpoint                                       | Auth Required | Description            |
| -------------- | ---------------------------------------------- | ------------- | ---------------------- |
| Auth           | `POST /api/auth/authenticate`                  | No            | Initial authentication |
| Auth           | `POST /api/auth/refresh-token`                 | No            | Refresh access token   |
| Wallet         | `POST /api/wallets`                            | No            | Create wallet          |
| Wallet         | `GET /api/wallets`                             | No            | List wallets           |
| Wallet         | `GET /api/wallets/details/:id`                 | No            | Wallet details         |
| Diamond Hand   | `POST /api/diamond-hand/request-claim-rewards` | Yes           | Claim rewards          |
| Transaction    | `POST /api/transactions`                       | Yes           | Create transaction     |
| Transaction    | `POST /api/transactions/sign`                  | Yes           | Sign transaction       |
| VM Transaction | `POST /api/vm-transactions`                    | Yes           | Create VM transaction  |
| Refund         | `POST /api/refunds`                            | Yes           | Create refund          |
| Etch           | `POST /api/etch/submit-etching`                | Yes           | Submit rune etching    |

### Error Code Quick Reference

| Code | Type                          | HTTP Status | Action             |
| ---- | ----------------------------- | ----------- | ------------------ |
| 4002 | Invalid Token                 | 401         | Redirect to login  |
| 4003 | Token Expired                 | 401         | Refresh token      |
| 4004 | Token Not Found               | 401         | Redirect to login  |
| 4005 | Invalid Refresh Token         | 400         | Redirect to login  |
| 4006 | User Not Found                | 401         | Redirect to login  |
| 4007 | Signature Verification Failed | 400         | Show error message |
| 4008 | Wallet Creation Failed        | 400         | Show error message |
| 4009 | Invalid Taproot Address       | 400         | Show error message |

### Token Lifecycle

| Token Type    | Expiration | Purpose            | Storage      |
| ------------- | ---------- | ------------------ | ------------ |
| Access Token  | 10 minutes | API authentication | localStorage |
| Refresh Token | 7 days     | Token renewal      | localStorage |

## Summary

The authentication system provides:

* 8 specific error codes covering all major authentication failure scenarios
* JWT Token Issues: 4002, 4003, 4004, 4005, 4006
* Signature Verification: 4007
* Wallet Operations: 4008, 4009

All error codes are actively used in the codebase and provide clear, actionable feedback for both developers and end users. The system is designed to be secure, stateless, and easy to integrate with frontend applications.


---

# 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://docs.radfi.co/dev/authentication-guide.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.
