API Authentication & Token Management
The REST API requires authentication for all endpoints. Three methods are supported, checked in the order listed below.
Authentication Methods
1. X-API-Key Header (recommended for scripts and CI)
Send the token in an X-API-Key header. This method is checked first and is
the preferred approach for programmatic access.
curl -H "X-API-Key: <token>" https://your-host/api/dataproducers/
2. Authorization: Token Header (standard DRF)
The standard Django REST Framework token header is also accepted:
curl -H "Authorization: Token <token>" https://your-host/api/dataproducers/
3. Session Cookie (browser)
When you are logged into the web interface, session-based authentication is used automatically. No extra headers are needed.
Token Type
Tokens are standard Django REST Framework auth tokens provided by the
rest_framework.authtoken app. Each user has one token stored in the
authtoken_token database table. Tokens do not expire automatically.
Generating a Token
From the Command Line
# Local development
python manage.py drf_create_token <username>
# Production (Docker)
docker compose run --rm django python manage.py drf_create_token <username>
The command prints the token value. Save it securely — it cannot be retrieved again (only regenerated).
From the Django Admin
- Log in as a superuser.
- Navigate to Auth Token → Tokens → Add.
- Select the user and save. The token value is displayed on the confirmation page.
Using a Token
Include the token in every API request using one of the two header styles:
# Preferred
curl -H "X-API-Key: 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" \
https://your-host/api/dataproducers/
# Alternative
curl -H "Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b" \
https://your-host/api/dataproducers/
If the X-API-Key header is present but the value is invalid, the request
is rejected immediately — there is no fallback to the Authorization header.
Rotating a Token
DRF tokens have no built-in expiry. To rotate a token, delete the existing one and create a new one in a single step:
python manage.py drf_create_token -r <username>
The -r (regenerate) flag deletes the old token and issues a new one.
Distribute the new token to all clients that were using the old one.
Revoking a Token
To revoke access without issuing a replacement:
- Admin UI: Delete the token from Auth Token → Tokens.
- Django shell:
python
from rest_framework.authtoken.models import Token
Token.objects.filter(user__username="<username>").delete()
After deletion, any request using that token will receive a 401 Unauthorized
response.
Creating Users
This project uses email-based authentication — the email address is the login identifier, not a traditional username.
Creating Users from the Command Line
# Local development
python manage.py createsuperuser
# Production (Docker)
docker compose run --rm django python manage.py createsuperuser
You will be prompted for an email address and password. Superusers have full access to the admin interface and all API endpoints.
Creating Users from the Django Admin
- Log in as a superuser.
- Navigate to Users → Add user.
- Fill in the email, name, and password fields.
- Set Staff status to allow the user to log into the admin site.
Via Self-Signup (django-allauth)
If allauth is enabled, users can register at /accounts/signup/. New
accounts created this way are not staff and have no special permissions
until an admin assigns them.
Assigning Roles via Group Permissions
The project uses Django's built-in Groups and Permissions system for role-based access control.
Creating a Group
- In the Django Admin, navigate to Authentication and Authorization → Groups → Add group.
- Give the group a descriptive name (e.g.,
ssds-editors,read-only). - In the Permissions panel, select the permissions to grant. Permissions
follow the pattern
<app> | <model> | <action>, for example: ssds_metadata | datacontainer | Can add datacontainerssds_metadata | datacontainer | Can change datacontainerssds_metadata | datacontainer | Can view datacontainer- Save the group.
Assigning a User to a Group
- Navigate to Users and select the user.
- Scroll to the Permissions section.
- Under Groups, move the desired groups to the Chosen groups list.
- Save.
The user inherits all permissions from their assigned groups immediately.
From the Django Shell
python manage.py shell
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
User = get_user_model()
# Create a group with model-level permissions
editors, _ = Group.objects.get_or_create(name="ssds-editors")
from django.contrib.auth.models import Permission
perms = Permission.objects.filter(
content_type__app_label="ssds_metadata",
codename__startswith="change_",
)
editors.permissions.set(perms)
# Add a user to the group
user = User.objects.get(email="someone@mbari.org")
user.groups.add(editors)
Common Group Examples
| Group | Typical Permissions |
|---|---|
read-only |
view_* on all ssds_metadata models |
ssds-editors |
add_*, change_*, view_* on ssds_metadata models |
admin |
All permissions (or use superuser status instead) |