Tutorial¶
This tutorial takes you from zero to a working authenticated endpoint. It assumes you completed Install.
Step 1 - Create a token¶
Tokens can exist without a linked user, but attaching one populates request.user / request.keysmith_user in your views.
from django.contrib.auth import get_user_model
from keysmith.services.tokens import create_token
user = get_user_model().objects.get(username="api-user")
token, raw_token = create_token(
name="tutorial-token",
user=user,
)
print(raw_token) # copy this somewhere safe
print(token.prefix)
Tip
You can also create tokens from the Django admin. The raw secret is shown once after creation.
Step 2 - Protect an endpoint¶
# views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from keysmith.drf.permissions import RequireKeysmithToken
class StatusView(APIView):
permission_classes = [RequireKeysmithToken]
def get(self, request):
return Response({
"ok": True,
"prefix": request.auth.prefix,
})
If you set global DRF defaults, you can omit permission_classes.
Step 3 - Make a request¶
Send the raw token in the X-KEYSMITH-TOKEN header:
Expected response:
Without a token (or with an invalid one), protected endpoints return 401 Unauthorized.
Step 4 - Rotate the token¶
If a secret is exposed, rotate immediately. The old raw token stops working at once; the database record (prefix, scopes, metadata) is preserved.
from keysmith.services.tokens import rotate_token
new_raw_token = rotate_token(token, actor=user, request=request)
Hand new_raw_token to the client. The previous value is now invalid.
Step 5 - Revoke the token¶
When a credential is permanently retired:
The token can no longer authenticate. A revoked audit event is recorded.
What you learned¶
| Concept | Detail |
|---|---|
| Raw token | Shown once at creation; never stored in plaintext |
| Header | X-KEYSMITH-TOKEN by default |
| Django | @keysmith_required + middleware |
| DRF | KeysmithAuthentication + RequireKeysmithToken |
| Lifecycle | rotate_token and revoke_token via service API |