I am trying to use the django-oauth-toolkit but continually hitting an invalid_grant error.
I believe I have followed the instructions at https://django-oauth-toolkit.readthedocs.io/en/latest/getting_started.html#oauth2-authorization-grants to the letter. I have created the following script to test with (mostly just extracted the code mentioned in the above page:
import random
import string
import base64
import hashlib
code_verifier = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(43, 128)))
code_verifier = base64.urlsafe_b64encode(code_verifier.encode('utf-8'))
code_challenge = hashlib.sha256(code_verifier).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8').replace('=', '')
client_id = input("Enter client id: ")
client_secret = input("Enter client secret: ")
redirect_url = input("Enter callback url: ")
print(f'vist http://127.0.0.1:8000/o/authorize/?response_type=code&code_challenge={code_challenge}&code_challenge_method=S256&client_id={client_id}&redirect_uri={redirect_url}')
code = input("Enter code: ")
print(f'enter: curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" "http://127.0.0.1:8000/o/token/" -d "client_id={client_id}" -d "client_secret={client_secret}" -d "code={code}" -d "code_verifier={code_verifier}" -d "redirect_uri={redirect_url}" -d "grant_type=authorization_code"')
The following shows the output (I haven't redacted the details, they are only temporary):
(venv) (base) peter@Peters-MacBook-Air Intra-Site % python api_test.py
Enter client id: sJ3ijzbmdogfBZPfhkF6hOqifPuPSKKpOnN8hq1N
Enter client secret: GnXNWqw7t1OwPRbOWTmDXKiuaqeJ7LRMhY9g2CWe00f3QrHLvx6aDKjGf5eF1t6QPkD1YO8BR43HNmzCjZYBW81FIjTng7QnVypzshMljEJRGTj5N7r8giwjKIiXyVng
Enter callback url: https://192.168.1.44/authenticate/callback
vist http://127.0.0.1:8000/o/authorize/?response_type=code&code_challenge=WiaJdysQ6aFnmkaO8yztt9kPBGUj-aqZSFVgmWYRBlU&code_challenge_method=S256&client_id=sJ3ijzbmdogfBZPfhkF6hOqifPuPSKKpOnN8hq1N&redirect_uri=https://192.168.1.44/authenticate/callback
Enter code: hrLeADVEmQF8mDLKJXhAZJRQ2dElV7
enter: curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" "http://127.0.0.1:8000/o/token/" -d "client_id=sJ3ijzbmdogfBZPfhkF6hOqifPuPSKKpOnN8hq1N" -d "client_secret=GnXNWqw7t1OwPRbOWTmDXKiuaqeJ7LRMhY9g2CWe00f3QrHLvx6aDKjGf5eF1t6QPkD1YO8BR43HNmzCjZYBW81FIjTng7QnVypzshMljEJRGTj5N7r8giwjKIiXyVng" -d "code=hrLeADVEmQF8mDLKJXhAZJRQ2dElV7" -d "code_verifier=b'UDZGREwyR0ZVMjNCTzRBQlFaVlBUQk9TWkVRUDlCQzFSUTY1MkFNMUUzRTVCRVBNNlkwR0k4UEtGMUhaVVlTVkQ0QVowMzJUR0xLTDQ1U0VNOEtaWVcxT0tP'" -d "redirect_uri=https://192.168.1.44/authenticate/callback" -d "grant_type=authorization_code"
(venv) (base) peter@Peters-MacBook-Air Intra-Site % curl -X POST -H "Cache-Control: no-cache" -H "Content-Type: application/x-www-form-urlencoded" "http://127.0.0.1:8000/o/token/" -d "client_id=sJ3ijzbmdogfBZPfhkF6hOqifPuPSKKpOnN8hq1N" -d "client_secret=GnXNWqw7t1OwPRbOWTmDXKiuaqeJ7LRMhY9g2CWe00f3QrHLvx6aDKjGf5eF1t6QPkD1YO8BR43HNmzCjZYBW81FIjTng7QnVypzshMljEJRGTj5N7r8giwjKIiXyVng" -d "code=hrLeADVEmQF8mDLKJXhAZJRQ2dElV7" -d "code_verifier=b'UDZGREwyR0ZVMjNCTzRBQlFaVlBUQk9TWkVRUDlCQzFSUTY1MkFNMUUzRTVCRVBNNlkwR0k4UEtGMUhaVVlTVkQ0QVowMzJUR0xLTDQ1U0VNOEtaWVcxT0tP'" -d "redirect_uri=https://192.168.1.44/authenticate/callback" -d "grant_type=authorization_code"
{"error": "invalid_grant"}%
I have the following in my settings.py:
OAUTH2_PROVIDER = {
'ALLOWED_REDIRECT_URI_SCHEMES': ["https", "intra"],
"SCOPES": {
"read": "Read scope",
"write": "Write scope",
"groups": "Access to your groups",
},
}
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
"DEFAULT_AUTHENTICATION_CLASSES": [
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
],
}
I also have the following in my installed apps:
"oauth2_provider",
"rest_framework",
It is most likely something mundane I have missed but cannot identify what.
Can anyone shed any light on why I might be getting the grant_type error.
I have confirmed that the redirect URL, client id, client secret are correct as they are in the application registered in dJango
I have also ensured that the code verifier and code challenge are correct and appear to be sent at the right times.
After testing in Postman and this being able to create a token I managed to rule out a setup issue. After playing around with the script I have identified that the instructions are wrong in the documentation.
The following:
code_verifier = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(43, 128)))
code_verifier = base64.urlsafe_b64encode(code_verifier.encode('utf-8'))
code_challenge = hashlib.sha256(code_verifier).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8').replace('=', '')
needs to be replaced with:
code_verifier = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(43, 128)))
code_challenge = hashlib.sha256(code_verifier.encode('utf-8')).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode('utf-8').replace('=', '')