Reputation: 6359
I am testing making an OAuth server with FastAPI. I have one side, which is the Oauth server which has an endpoint that looks like:
@router.post("/token")
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()) -> Dict[str, str]:
return {"access_token": form_data.username, "token_type": "bearer"}
And then on a separate process, I have a fake app with a log-in endpoint which looks like:
@router.post("/")
async def login(username: str, password: str) -> Dict[str, str]:
form = OAuth2PasswordRequestForm(
username=username,
password=password,
scope="me"
)
form_data = aiohttp.FormData()
for key, val in form.__dict__.items():
form_data.add_field(key, val)
async with aiohttp.ClientSession() as session:
async with session.post(f"http://localhost:8001/oauth/token", data=form_data()) as server_response:
response = await server_response.text()
response = json.loads(response)
return response
The OAuth server is responding with
{
"detail": [
{
"loc": [
"body",
"grant_type"
],
"msg": "string does not match regex \"password\"",
"type": "value_error.str.regex",
"ctx": {
"pattern": "password"
}
}
]
}
How can I use aiohttp to post the form data to the oauth server?
Upvotes: 1
Views: 1474
Reputation: 34307
The grant_type
field is missing from your data. Although grant_type
is an optional field, as per the documentation (have a look under the "Tip" section):
The OAuth2 spec actually requires a field grant_type with a fixed value of
password
, but OAuth2PasswordRequestForm doesn't enforce it.If you need to enforce it, use OAuth2PasswordRequestFormStrict instead of OAuth2PasswordRequestForm.
Thus, your form should look like the one below. The grant_type="password"
means that you are sending a username and a password to the /token
endpoint (have a look at this answer as well).
form = OAuth2PasswordRequestForm(
grant_type="password",
username=username,
password=password,
scope="me"
)
Upvotes: 1