# How Token-Based REST API Authentication Works in MobileAudit: A Complete Guide

> Explore token-based REST API authentication in MobileAudit. Learn how to get and use auth tokens for secure access to write operations and protected endpoints.

- Repository: [Mónica Pastor/mobileaudit](https://github.com/mpast/mobileaudit)
- Tags: api-reference
- Published: 2026-03-07

---

**MobileAudit implements token-based REST API authentication using Django REST Framework's `rest_framework.authtoken` module, requiring clients to obtain a token via `POST /api/v1/auth-token/` and include it in the `Authorization: Token <token>` header for all write operations.**

MobileAudit is an open-source mobile application security testing platform that exposes a REST API for programmatic access to scan results and application data. Understanding its token-based authentication mechanism is essential for security researchers and developers integrating with the platform. This guide explains how the authentication flow works, which endpoints enforce authorization, and how to interact with the API using valid tokens.

## How Token-Based Authentication Works in MobileAudit

MobileAudit leverages Django REST Framework (DRF) together with the `rest_framework.authtoken` package to provide a stateless authentication layer. The implementation follows the standard DRF token authentication pattern with custom permission classes for object-level security.

### Token Issuance and the Auth Endpoint

Clients obtain authentication tokens by submitting valid Django user credentials to the dedicated token endpoint. In [`app/config/urls.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/urls.py) at line 56, the URL pattern maps `POST /api/v1/auth-token/` to DRF's built-in `obtain_auth_token` view:

```python

# From app/config/urls.py

path('api/v1/auth-token/', obtain_auth_token)

```

When a client sends a POST request with `username` and `password` parameters, the view validates the credentials against Django's user database. Upon successful authentication, the system returns a JSON response containing the token string:

```json
{
  "token": "a1b2c3d4e5f6g7h8i9j0"
}

```

This token is permanently associated with the user account in the `authtoken_token` database table until explicitly deleted.

### Sending Tokens in API Requests

For all subsequent API calls that require authentication, clients must include the token in the HTTP `Authorization` header using the `Token` keyword followed by a space and the token string:

```bash
Authorization: Token a1b2c3d4e5f6g7h8i9j0

```

DRF's `TokenAuthentication` class, registered in [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py) at lines 27-31, processes this header on every request:

```python

# From app/config/settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
    # ...

}

```

The authentication backend extracts the token value, queries the `authtoken_token` table, and populates `request.user` with the corresponding Django user instance. If the token is missing or invalid, the system returns a `401 Unauthorized` response.

### Permission Classes and Access Control

MobileAudit implements a layered permission system in [`app/api.py`](https://github.com/mpast/mobileaudit/blob/main/app/api.py) that combines DRF's built-in classes with custom object-level permissions. The ViewSets declare the following permission classes:

```python

# From app/api.py

permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsUserOrReadOnly)

```

**`IsAuthenticatedOrReadOnly`** allows unauthenticated users to perform safe HTTP methods (`GET`, `HEAD`, `OPTIONS`) but requires valid authentication for unsafe methods (`POST`, `PUT`, `PATCH`, `DELETE`).

**`IsUserOrReadOnly`** is a custom permission defined in [`app/api.py`](https://github.com/mpast/mobileaudit/blob/main/app/api.py) at lines 12-16 that enforces object-level ownership:

```python
class IsUserOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.user == request.user

```

This ensures that only the user who created an object can modify or delete it, even if they possess a valid token.

## API Endpoints That Require Authorization

MobileAudit exposes several REST endpoints through DRF routers. While read operations are generally public, all write operations require token-based authentication.

The following endpoints enforce the `IsAuthenticatedOrReadOnly` and `IsUserOrReadOnly` permission classes:

| Endpoint | Resource | HTTP Methods Requiring Token |
|----------|----------|------------------------------|
| `/api/v1/app/` | `ApplicationViewSet` | `POST`, `PUT`, `PATCH`, `DELETE` |
| `/api/v1/scan/` | `ScanViewSet` | `POST`, `PUT`, `PATCH`, `DELETE` |
| `/api/v1/finding/` | `FindingViewSet` | `POST`, `PUT`, `PATCH`, `DELETE` |
| `/api/v1/permission/` | `PermissionViewSet` | `POST`, `PUT`, `PATCH`, `DELETE` |

**Publicly accessible operations:**
- `GET /api/v1/app/` – List all applications
- `GET /api/v1/app/<id>/` – Retrieve specific application details
- `GET /api/v1/scan/` – List scans
- `GET /api/v1/finding/` – List security findings

**Token-protected operations:**
- `POST /api/v1/scan/` – Create a new scan (requires ownership of the referenced application)
- `PATCH /api/v1/finding/<id>/` – Update finding severity or status
- `DELETE /api/v1/app/<id>/` – Remove an application (restricted to the owner)

The token endpoint itself (`POST /api/v1/auth-token/`) is the only API entry point that explicitly does not require a token, as its purpose is to issue them.

## Code Examples: Authenticating with the MobileAudit API

### Obtaining an Authentication Token

Use the `auth-token` endpoint to exchange Django user credentials for an API token:

```bash
curl -X POST https://your-mobileaudit-instance.com/api/v1/auth-token/ \
     -H "Content-Type: application/json" \
     -d '{"username":"security_analyst","password":"complex_password_123"}'

```

Successful response:

```json
{
  "token": "9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b"
}

```

Store this token securely; it represents your identity for all subsequent API interactions.

### Making Authenticated Requests

Include the token in the `Authorization` header for any write operation:

```bash
curl -X POST https://your-mobileaudit-instance.com/api/v1/scan/ \
     -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" \
     -H "Content-Type: multipart/form-data" \
     -F "app=1" \
     -F "file=@/path/to/mobile_app.apk"

```

For JSON payloads:

```bash
curl -X PATCH https://your-mobileaudit-instance.com/api/v1/finding/42/ \
     -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" \
     -H "Content-Type: application/json" \
     -d '{"severity":"HIGH","status":"CONFIRMED"}'

```

### Read-Only vs. Write Operations

Demonstrate the difference between public read access and protected write access:

```bash

# Public: No token required for GET requests

curl https://your-mobileaudit-instance.com/api/v1/app/

# Protected: Token required for POST

curl -X POST https://your-mobileaudit-instance.com/api/v1/app/ \
     -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" \
     -H "Content-Type: application/json" \
     -d '{"name":"TestApp","package":"com.example.test"}'

```

If you omit the `Authorization` header on the POST request, the API returns:

```json
{
  "detail": "Authentication credentials were not provided."
}

```

## Key Implementation Files

The token-based authentication system is implemented across several configuration and view files in the MobileAudit codebase:

| File | Purpose | Key Components |
|------|---------|----------------|
| [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py) | DRF configuration | `TokenAuthentication` in `DEFAULT_AUTHENTICATION_CLASSES` (lines 27-31) |
| [`app/config/urls.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/urls.py) | URL routing | `obtain_auth_token` view mapped to `/api/v1/auth-token/` (line 56) |
| [`app/api.py`](https://github.com/mpast/mobileaudit/blob/main/app/api.py) | API viewsets and permissions | `IsUserOrReadOnly` custom permission class (lines 12-16); ViewSets with `IsAuthenticatedOrReadOnly` |
| [`app/views.py`](https://github.com/mpast/mobileaudit/blob/main/app/views.py) | Web UI views | `@login_required` decorators for session-based web authentication (lines 56-62) |
| [`requirements.txt`](https://github.com/mpast/mobileaudit/blob/main/requirements.txt) | Dependencies | `djangorestframework`, `djangorestframework-authtoken` packages |

These files collectively define the authentication pipeline: [`settings.py`](https://github.com/mpast/mobileaudit/blob/main/settings.py) configures the authentication backend, [`urls.py`](https://github.com/mpast/mobileaudit/blob/main/urls.py) exposes the token acquisition endpoint, and [`api.py`](https://github.com/mpast/mobileaudit/blob/main/api.py) enforces permission rules on the actual data resources.

## Summary

MobileAudit implements a straightforward yet secure token-based REST API authentication system using Django REST Framework. Here are the essential points:

- **Token Acquisition**: Clients obtain tokens by posting credentials to `POST /api/v1/auth-token/`, handled by DRF's `obtain_auth_token` view in [`app/config/urls.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/urls.py).
- **Request Authentication**: All protected endpoints require the `Authorization: Token <token>` header, processed by `TokenAuthentication` configured in [`app/config/settings.py`](https://github.com/mpast/mobileaudit/blob/main/app/config/settings.py).
- **Permission Model**: The API uses `IsAuthenticatedOrReadOnly` to allow public read access while restricting writes to authenticated users, plus the custom `IsUserOrReadOnly` permission in [`app/api.py`](https://github.com/mpast/mobileaudit/blob/main/app/api.py) to enforce object-level ownership.
- **Protected Endpoints**: All write operations (`POST`, `PUT`, `PATCH`, `DELETE`) on `/api/v1/app/`, `/api/v1/scan/`, `/api/v1/finding/`, and `/api/v1/permission/` require valid tokens.
- **Web UI Separation**: The web interface uses Django session authentication via `@login_required` decorators in [`app/views.py`](https://github.com/mpast/mobileaudit/blob/main/app/views.py), distinct from the token-based API authentication.

## Frequently Asked Questions

### How do I obtain an API token for MobileAudit?

You must send a POST request to the `/api/v1/auth-token/` endpoint with your Django username and password in the request body. The system validates these credentials against the user database and returns a JSON response containing your unique token string. Store this token securely, as it serves as your authentication credential for all subsequent API requests.

### Which HTTP methods require token-based authentication in MobileAudit?

Safe read-only methods including `GET`, `HEAD`, and `OPTIONS` are publicly accessible without authentication across all API endpoints. However, any write operation using `POST`, `PUT`, `PATCH`, or `DELETE` requires a valid token in the `Authorization` header. This policy is enforced by the `IsAuthenticatedOrReadOnly` permission class applied to all ViewSets in [`app/api.py`](https://github.com/mpast/mobileaudit/blob/main/app/api.py).

### What is the difference between token authentication and the web UI login?

MobileAudit uses two distinct authentication mechanisms: the REST API employs token-based authentication via DRF's `TokenAuthentication` class, while the web interface relies on Django's traditional session-based authentication. The web views in [`app/views.py`](https://github.com/mpast/mobileaudit/blob/main/app/views.py) are protected by the `@login_required` decorator, which checks for an active user session rather than an API token. You cannot use API tokens to access web HTML pages, nor can you use session cookies to authenticate API requests that require tokens.

### How does MobileAudit enforce object-level permissions?

Beyond requiring authentication for write operations, MobileAudit implements a custom permission class named `IsUserOrReadOnly` in [`app/api.py`](https://github.com/mpast/mobileaudit/blob/main/app/api.py) (lines 12-16). This class checks whether the authenticated user making the request is the same as the user who originally created the object (`obj.user == request.user`). If the check fails, the API returns a `403 Forbidden` response, ensuring users can only modify or delete their own scan results and application data, even if they possess a valid authentication token.