<!-- Source: https://www.wappi.dev/security/jwt-authentication -->

# JWT Authentication

JSON Web Tokens (JWT) provide a secure way to handle user authentication and session management in Wappi applications. JWTs are stateless, scalable, and perfect for modern API architectures.

## How JWT Works in Wappi

Wappi uses JWT tokens for user authentication through a dedicated login endpoint:

1. 1. User provides credentials to the login endpoint
2. 2. Wappi validates credentials and generates a JWT token
3. 3. Token is returned to the client and stored (usually in localStorage)
4. 4. Subsequent requests include the JWT token for authentication
5. 5. Wappi validates the token on each protected endpoint

## Login Endpoint Implementation

Create a login endpoint that generates JWT tokens:

```typescript
// API/Core/Login/1.0.0/index.ts
import jwt from 'jsonwebtoken'
import bcrypt from 'bcrypt'

interface Core_Login_1_0_0__Body {
  email: string
  password: string
}

export default async function CoreLogin(body: Core_Login_1_0_0__Body) {
  try {
    // Validate user credentials
    const user = await validateUser(body.email, body.password)
    
    if (!user) {
      throw new Error('Invalid credentials')
    }

    // Generate JWT token
    const token = jwt.sign(
      {
        userId: user.id,
        email: user.email,
        role: user.role
      },
      process.env.JWT_SECRET,
      {
        expiresIn: '24h',
        issuer: 'wappi-api',
        audience: 'wappi-client'
      }
    )

    return {
      success: true,
      data: {
        user: {
          id: user.id,
          email: user.email,
          name: user.name,
          role: user.role
        },
        token,
        expiresIn: '24h'
      }
    }
  } catch (error) {
    throw new Error('Authentication failed')
  }
}

async function validateUser(email: string, password: string) {
  // Implement your user validation logic
  const user = await getUserByEmail(email)
  
  if (!user || !await bcrypt.compare(password, user.hashedPassword)) {
    return null
  }
  
  return user
}
```

## JWT Configuration

### Environment Variables

```bash
# JWT Secret for token signing
JWT_SECRET=your-super-secret-jwt-key-here

# Token expiration settings
JWT_EXPIRES_IN=24h
JWT_REFRESH_EXPIRES_IN=7d

# JWT issuer and audience
JWT_ISSUER=wappi-api
JWT_AUDIENCE=wappi-client
```

### wappi.json Configuration

```json
{
  "authRotation": "0 0 * * *",  // Daily token rotation
  "apiKey": "your-api-key",
  "domains": "yourdomain.com, app.yourdomain.com"
}
```

## Protected Endpoints

Protect endpoints by requiring JWT authentication:

```typescript
// API/User/GetProfile/1.0.0/index.ts
interface User_GetProfile_1_0_0__Body {
  // JWT auth data is automatically added to authenticated requests
  auth: {
    userId: string
    email: string
    role: string
  }
}

export default async function GetUserProfile(body: User_GetProfile_1_0_0__Body) {
  try {
    // Access authenticated user data from body.auth
    const userId = body.auth.userId
    
    const userProfile = await getUserProfile(userId)
    
    return {
      success: true,
      data: userProfile
    }
  } catch (error) {
    throw new Error('Failed to get user profile')
  }
}
```

## Frontend Integration

### Login Implementation

```typescript
import { request } from 'wappi-fe'
import { WAPPI_CONFIG } from './wappiConfig'

// Login function
export const login = async (email: string, password: string) => {
  const response = await request(WAPPI_CONFIG, {
    name: 'User Login',
    query: 'Core_Login_1_0_0',
    data: { email, password },
    authRequired: false,  // Login doesn't require existing auth
    successCallback: (data) => {
      // Store JWT token in localStorage
      localStorage.setItem('wappiAuthToken', data.token)
      localStorage.setItem('wappiUser', JSON.stringify(data.user))
    },
    errorCallback: (error) => {
      console.error('Login failed:', error)
    }
  })
  
  return response
}
```

### Authenticated Requests

```typescript
// Making authenticated requests
export const getUserProfile = async () => {
  return await request(WAPPI_CONFIG, {
    name: 'Get User Profile',
    query: 'User_GetProfile_1_0_0',
    data: {},
    authRequired: true,  // Automatically includes JWT token
    errorCallback: (error) => {
      if (error.statusCode === 401) {
        // Token expired or invalid - redirect to login
        localStorage.removeItem('wappiAuthToken')
        window.location.href = '/login'
      }
    }
  })
}
```

## Token Refresh

Implement token refresh for seamless user experience:

```typescript
// API/Core/RefreshToken/1.0.0/index.ts
interface Core_RefreshToken_1_0_0__Body {
  refreshToken: string
}

export default async function RefreshToken(body: Core_RefreshToken_1_0_0__Body) {
  try {
    // Validate refresh token
    const decoded = jwt.verify(body.refreshToken, process.env.JWT_REFRESH_SECRET)
    
    // Generate new access token
    const newToken = jwt.sign(
      {
        userId: decoded.userId,
        email: decoded.email,
        role: decoded.role
      },
      process.env.JWT_SECRET,
      { expiresIn: '24h' }
    )

    return {
      success: true,
      data: {
        token: newToken,
        expiresIn: '24h'
      }
    }
  } catch (error) {
    throw new Error('Invalid refresh token')
  }
}
```

## JWT Middleware

Wappi automatically handles JWT validation for protected endpoints:

```typescript
// Automatic JWT validation middleware (built into Wappi)
function validateJWT(token: string) {
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET)
    
    // Check token expiration
    if (decoded.exp < Date.now() / 1000) {
      throw new Error('Token expired')
    }
    
    return {
      success: true,
      user: decoded
    }
  } catch (error) {
    return {
      success: false,
      error: error.message
    }
  }
}
```

## Security Best Practices

- **Use strong JWT secrets:** Generate cryptographically secure secrets
- **Set appropriate expiration:** Balance security and user experience
- **Implement token refresh:** Allow seamless token renewal
- **Validate token claims:** Check issuer, audience, and custom claims
- **Use HTTPS only:** Never transmit tokens over unencrypted connections
- **Store tokens securely:** Use httpOnly cookies or secure storage
- **Implement logout:** Provide token invalidation mechanism
- **Monitor token usage:** Track authentication events for security

## Logout Implementation

```typescript
// Frontend logout function
export const logout = () => {
  // Remove tokens from storage
  localStorage.removeItem('wappiAuthToken')
  localStorage.removeItem('wappiRefreshToken')
  localStorage.removeItem('wappiUser')
  
  // Redirect to login page
  window.location.href = '/login'
}

// Optional: Server-side token blacklisting
// API/Core/Logout/1.0.0/index.ts
export default async function Logout(body: Core_Logout_1_0_0__Body) {
  try {
    // Add token to blacklist (optional)
    await blacklistToken(body.auth.token)
    
    return {
      success: true,
      message: 'Logged out successfully'
    }
  } catch (error) {
    throw new Error('Logout failed')
  }
}
```

## Error Handling

Handle JWT-related errors gracefully:

```typescript
// Common JWT error responses
{
  "success": false,
  "message": "Token expired",
  "statusCode": 401,
  "code": "TOKEN_EXPIRED"
}

{
  "success": false,
  "message": "Invalid token",
  "statusCode": 401,
  "code": "INVALID_TOKEN"
}

{
  "success": false,
  "message": "Token required",
  "statusCode": 401,
  "code": "TOKEN_REQUIRED"
}
```

## Testing JWT Authentication

```typescript
// Test JWT authentication
curl -X POST https://api.yourdomain.com/Core/Login/1.0.0 \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "password123"
  }'

// Use returned token for authenticated requests
curl -X GET https://api.yourdomain.com/User/GetProfile/1.0.0 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json"
```

## Advanced Features

### Role-Based Access Control

```typescript
// Implement role-based access in endpoints
export default async function AdminOnlyEndpoint(body: Admin_ManageUsers_1_0_0__Body) {
  // Check user role from JWT token
  if (body.auth.role !== 'admin') {
    throw new Error('Insufficient permissions')
  }
  
  // Admin-only logic here
  return {
    success: true,
    data: await getAdminData()
  }
}
```

### Custom Claims

```typescript
// Add custom claims to JWT tokens
const token = jwt.sign(
  {
    userId: user.id,
    email: user.email,
    role: user.role,
    permissions: user.permissions,
    organizationId: user.organizationId,
    lastLogin: new Date().toISOString()
  },
  process.env.JWT_SECRET,
  { expiresIn: '24h' }
)
```

URL: https://www.wappi.dev/security/jwt-authentication
