> ## Documentation Index
> Fetch the complete documentation index at: https://pv-pushkarverma-skillrise-21.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Authentication methods, Clerk integration, protected routes, and role-based access control

## Overview

The SkillRise API uses **Clerk** for authentication and authorization. Clerk provides secure session management with JWT tokens that include user identity and role-based metadata.

## Authentication Flow

**1. User Signs In**

User authenticates through Clerk on the frontend (sign-up/sign-in)

**2. Clerk Issues Token**

Clerk generates a JWT session token containing:

* `userId` - Unique user identifier
* `sessionClaims.metadata.role` - User role (student, educator, admin)

**3. Frontend Includes Token**

Frontend includes the Clerk session token in API requests (handled automatically by Clerk SDK)

**4. API Validates Token**

Clerk middleware validates the token and populates `req.auth` with user context

**5. Role Check (if required)**

Protected routes verify user role via custom middleware

## Clerk Middleware

The API uses `@clerk/express` middleware globally:

```javascript theme={null}
import { clerkMiddleware } from '@clerk/express'

app.use(clerkMiddleware())
```

This middleware:

* Validates Clerk session tokens
* Populates `req.auth` with authentication context
* Allows both authenticated and unauthenticated requests

### Auth Context (`req.auth`)

On authenticated requests, `req.auth` contains:

**userId** `string` *required*

Clerk user ID (used as MongoDB `_id` for User documents)

**sessionClaims** `object`

Clerk session claims object

**sessionClaims.metadata.role** `string`

User role: `"student"`, `"educator"`, or `"admin"`

## Protected Routes

### User Authentication

User-specific endpoints require authentication via Clerk's `requireAuth()` middleware:

```javascript theme={null}
import { requireAuth } from '@clerk/express'

userRouter.use(requireAuth())
```

All routes under `/api/user/*` are protected:

* `/api/user/data` - Get user profile
* `/api/user/enrolled-courses` - Get enrolled courses
* `/api/user/purchase` - Purchase course
* `/api/user/ai-chat` - AI chatbot
* And more...

**Unauthenticated Request Response:**

```json theme={null}
{
  "success": false,
  "message": "Unauthorized Access"
}
```

Status Code: `401 Unauthorized`

## Role-Based Access Control

SkillRise implements three user roles with distinct permissions:

### Student (Default)

All authenticated users have student access by default. Students can:

* Browse and purchase courses
* Track progress and earn certificates
* Use AI chat assistant
* Participate in community discussions
* Take quizzes

### Educator

Educators can create and manage courses. Educator routes use custom middleware:

```javascript theme={null}
export const protectEducator = (req, res, next) => {
  if (!req.auth?.userId) {
    return res.status(401).json({ 
      success: false, 
      message: 'Unauthorized Access' 
    })
  }

  const role = req.auth.sessionClaims?.metadata?.role

  if (role !== 'educator') {
    return res.status(403).json({ 
      success: false, 
      message: 'Unauthorized Access' 
    })
  }

  next()
}
```

**Protected Educator Routes:**

* `POST /api/educator/add-course` - Create new course
* `GET /api/educator/courses` - List educator's courses
* `GET /api/educator/dashboard` - Dashboard analytics
* `GET /api/educator/enrolled-students` - Student enrollment data
* `POST /api/quiz/generate` - Generate AI quiz
* `GET /api/quiz/educator-insights` - Quiz performance insights

**Non-Educator Request Response:**

```json theme={null}
{
  "success": false,
  "message": "Unauthorized Access"
}
```

Status Code: `403 Forbidden`

### Admin

Admins have full platform access. Admin routes use custom middleware:

```javascript theme={null}
export const protectAdmin = (req, res, next) => {
  if (!req.auth?.userId) {
    return res.status(401).json({ 
      success: false, 
      message: 'Unauthorized Access' 
    })
  }

  const role = req.auth.sessionClaims?.metadata?.role

  if (role !== 'admin') {
    return res.status(403).json({ 
      success: false, 
      message: 'Unauthorized Access' 
    })
  }

  next()
}
```

**Protected Admin Routes:**

* `GET /api/admin/stats` - Platform statistics
* `GET /api/admin/chart-data` - Analytics charts
* `GET /api/admin/courses` - All courses
* `GET /api/admin/purchases` - All purchases
* `GET /api/admin/users` - User management
* `GET /api/admin/educator-applications` - Educator applications
* `PATCH /api/admin/educator-applications/:id/approve` - Approve educator
* `PATCH /api/admin/educator-applications/:id/reject` - Reject educator

**Non-Admin Request Response:**

```json theme={null}
{
  "success": false,
  "message": "Unauthorized Access"
}
```

Status Code: `403 Forbidden`

## Becoming an Educator

Users can apply to become educators through the application system:

**1. Submit Application**

`POST /api/educator/apply` - Submit educator application (no role required)

**2. Admin Review**

Admin reviews application via `/api/admin/educator-applications`

**3. Approval/Rejection**

Admin approves or rejects via PATCH endpoints

**4. Role Updated**

On approval, user's Clerk metadata is updated with `role: "educator"`

**Check Application Status:**

```bash theme={null}
GET /api/educator/application-status
```

No role protection - any authenticated user can check their status.

## Public Endpoints

Some endpoints are publicly accessible without authentication:

**GET /api/course/all** `Public`

List all published courses

**GET /api/course/:id** `Public`

Get course details (lecture URLs hidden for non-free content)

**GET /api/certificate/verify/:certificateId** `Public`

Verify certificate authenticity via QR code

**GET /api/community/groups** `Public`

List community groups (membership requires auth)

**GET /api/community/posts** `Public`

Browse community posts (voting/posting requires auth)

## Webhooks Authentication

### Clerk Webhooks

Clerk webhooks use **Svix** signature verification:

```javascript theme={null}
import { Webhook } from 'svix'

const wh = new Webhook(process.env.CLERK_WEBHOOK_SECRET)
const evt = wh.verify(body, headers)
```

The webhook handles user lifecycle events to sync data with MongoDB.

### Razorpay Webhooks

Razorpay webhooks use HMAC signature verification:

```javascript theme={null}
import crypto from 'crypto'

const expectedSignature = crypto
  .createHmac('sha256', process.env.RAZORPAY_WEBHOOK_SECRET)
  .update(JSON.stringify(req.body))
  .digest('hex')

if (expectedSignature !== receivedSignature) {
  throw new Error('Invalid signature')
}
```

## Example: Making Authenticated Requests

### Frontend (with Clerk React)

```javascript theme={null}
import { useAuth } from '@clerk/clerk-react'

const { getToken } = useAuth()

const response = await fetch('http://localhost:3000/api/user/data', {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${await getToken()}`
  }
})
```

Clerk automatically handles token injection when using `@clerk/clerk-react` hooks.

### Direct API Call (with token)

```bash theme={null}
curl -X GET http://localhost:3000/api/user/data \
  -H "Authorization: Bearer YOUR_CLERK_SESSION_TOKEN"
```

## Security Best Practices

> [!WARNING]
>
> **Never** expose Clerk secret keys on the frontend. Use Clerk's publishable keys only.

> [!NOTE]
>
> Rate limiting is tied to `userId` when authenticated, preventing users from bypassing limits by switching IP addresses.

### Token Validation

* Tokens are validated on every request via Clerk middleware
* Expired tokens receive `401 Unauthorized`
* Role changes take effect immediately (no token refresh needed)

### CORS Protection

API accepts requests only from configured frontend origin:

```javascript theme={null}
app.use(cors({ 
  origin: process.env.FRONTEND_URL || 'http://localhost:5173' 
}))
```

## Troubleshooting

### 401 Unauthorized

> **Missing Authorization Header**
>
> Ensure Clerk SDK is properly configured and token is included in request headers

> **Expired Session**
>
> User needs to re-authenticate. Clerk SDK handles this automatically.

> **Invalid Token**
>
> Token may be malformed or from wrong Clerk instance. Verify `CLERK_PUBLISHABLE_KEY` matches backend.

### 403 Forbidden

> **Insufficient Role**
>
> User lacks required role (educator/admin) for this endpoint. Check `req.auth.sessionClaims.metadata.role`.

> **Course Not Purchased**
>
> User attempting to access enrolled course content without purchasing. Verify enrollment via `/api/user/enrolled-courses`.

## Next Steps

> **[API Overview](https://pv-pushkarverma-skillrise-21.mintlify.site/api/overview.md)**
>
> Learn about API structure and response formats

> **[Endpoints](https://pv-pushkarverma-skillrise-21.mintlify.site/api/endpoints)**
>
> Browse all available API endpoints


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.