Estoy probando hacer un servidor OAuth con FastAPI. Tengo un lado, que es el servidor Oauth que tiene un punto final que se ve así:
@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"}Y luego, en un proceso separado, tengo una aplicación falsa con un punto final de inicio de sesión que se ve así:
@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 responseEl servidor OAuth está respondiendo con
{ "detail": [ { "loc": [ "body", "grant_type" ], "msg": "string does not match regex \"password\"", "type": "value_error.str.regex", "ctx": { "pattern": "password" } } ] }¿Cómo puedo usar aiohttp para publicar los datos del formulario en el servidor oauth?
Falta el campo grant_type en sus datos. Aunque grant_type es un campo opcional, según la documentación (eche un vistazo en la sección "Consejo"):
La especificación OAuth2 en realidad requiere un campo grant_type con un valor fijo de
password, pero OAuth2PasswordRequestForm no lo impone.Si necesita aplicarlo, use OAuth2PasswordRequestFormStrict en lugar de OAuth2PasswordRequestForm.
Por lo tanto, su formulario debería verse como el siguiente. grant_type="password" significa que está enviando un nombre de usuario y una contraseña al punto final /token (eche un vistazo a esta respuesta también).
form = OAuth2PasswordRequestForm( grant_type="password", username=username, password=password, scope="me" )