djangorestframework-api-key icon indicating copy to clipboard operation
djangorestframework-api-key copied to clipboard

Generated API keys are invalid – check_password fails due to mismatched hash

Open spacepc-de opened this issue 6 months ago β€’ 0 comments

Hi, I've encountered an issue where API keys generated using the django-rest-framework-api-key library via the standard frontend method are consistently invalid when used for authentication. After thorough debugging, I believe there is a bug in the create_key method responsible for key generation.

Summary API keys generated via the web frontend (using the library’s default key creation flow) result in 403 Forbidden errors: {"detail": "Authentication credentials were not provided."} The keys follow the correct format (Prefix.Secret) and are passed properly in the Authorization: Api-Key ... header. Manually created keys (via shell), using make_password for hashing and storing them in the database, do work and pass authentication. Debugging Details Verified that check_password works correctly in our environment. Verified that key objects are correctly stored and fetched from the DB based on their prefix. Compared behavior: Manual key creation (using make_password) β†’ check_password returns True, key works for auth. Web-frontend-generated key β†’ check_password returns False, key is rejected.

Conclusion

This strongly suggests that something in the create_key logic is broken. Potential causes:

The secret shown to the user may be altered (e.g. encoding/decoding issue) before hashing and storing. The hashing process itself may not use make_password correctly. The hash stored in the DB may not match the actual secret shown to the user. Steps to Reproduce

Generate an API key using the standard frontend method. Use that key in an authenticated API call: curl -H "Authorization: Api-Key ." https://your-api-endpoint/ Observe a 403 response. Check in a Django shell: from rest_framework_api_key.models import APIKey from django.contrib.auth.hashers import check_password key = APIKey.objects.get(prefix="") check_password("", key.hashed_key) # Returns False Let me know if I can help.

Thanks!

spacepc-de avatar Apr 08 '25 17:04 spacepc-de