API Authentication & Token Management

The REST API requires authentication for all endpoints. Three methods are supported, checked in the order listed below.

Authentication Methods

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/

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

  1. Log in as a superuser.
  2. Navigate to Auth Token → Tokens → Add.
  3. 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

  1. Log in as a superuser.
  2. Navigate to Users → Add user.
  3. Fill in the email, name, and password fields.
  4. 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

  1. In the Django Admin, navigate to Authentication and Authorization → Groups → Add group.
  2. Give the group a descriptive name (e.g., ssds-editors, read-only).
  3. In the Permissions panel, select the permissions to grant. Permissions follow the pattern <app> | <model> | <action>, for example:
  4. ssds_metadata | datacontainer | Can add datacontainer
  5. ssds_metadata | datacontainer | Can change datacontainer
  6. ssds_metadata | datacontainer | Can view datacontainer
  7. Save the group.

Assigning a User to a Group

  1. Navigate to Users and select the user.
  2. Scroll to the Permissions section.
  3. Under Groups, move the desired groups to the Chosen groups list.
  4. 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)