How Token-Based REST API Authentication Works in MobileAudit: A Complete Guide
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 at line 56, the URL pattern maps POST /api/v1/auth-token/ to DRF's built-in obtain_auth_token view:
# 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:
{
"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:
Authorization: Token a1b2c3d4e5f6g7h8i9j0
DRF's TokenAuthentication class, registered in app/config/settings.py at lines 27-31, processes this header on every request:
# 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 that combines DRF's built-in classes with custom object-level permissions. The ViewSets declare the following permission classes:
# 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 at lines 12-16 that enforces object-level ownership:
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 applicationsGET /api/v1/app/<id>/– Retrieve specific application detailsGET /api/v1/scan/– List scansGET /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 statusDELETE /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:
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:
{
"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:
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:
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:
# 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:
{
"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 |
DRF configuration | TokenAuthentication in DEFAULT_AUTHENTICATION_CLASSES (lines 27-31) |
app/config/urls.py |
URL routing | obtain_auth_token view mapped to /api/v1/auth-token/ (line 56) |
app/api.py |
API viewsets and permissions | IsUserOrReadOnly custom permission class (lines 12-16); ViewSets with IsAuthenticatedOrReadOnly |
app/views.py |
Web UI views | @login_required decorators for session-based web authentication (lines 56-62) |
requirements.txt |
Dependencies | djangorestframework, djangorestframework-authtoken packages |
These files collectively define the authentication pipeline: settings.py configures the authentication backend, urls.py exposes the token acquisition endpoint, and 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'sobtain_auth_tokenview inapp/config/urls.py. - Request Authentication: All protected endpoints require the
Authorization: Token <token>header, processed byTokenAuthenticationconfigured inapp/config/settings.py. - Permission Model: The API uses
IsAuthenticatedOrReadOnlyto allow public read access while restricting writes to authenticated users, plus the customIsUserOrReadOnlypermission inapp/api.pyto 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_requireddecorators inapp/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.
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 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 (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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →