mirror of https://github.com/tiangolo/fastapi.git
🐛 Fix `OAuth2PasswordRequestForm` and `OAuth2PasswordRequestFormStrict` fixed `grant_type` "password" RegEx (#9783)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Alejandra <90076947+alejsdev@users.noreply.github.com> Co-authored-by: Sofie Van Landeghem <svlandeg@users.noreply.github.com> Co-authored-by: svlandeg <svlandeg@github.com> Co-authored-by: Sebastián Ramírez <tiangolo@gmail.com>
This commit is contained in:
parent
43d9a4d2b1
commit
d5ecbaceae
|
|
@ -63,7 +63,7 @@ class OAuth2PasswordRequestForm:
|
|||
*,
|
||||
grant_type: Annotated[
|
||||
Union[str, None],
|
||||
Form(pattern="password"),
|
||||
Form(pattern="^password$"),
|
||||
Doc(
|
||||
"""
|
||||
The OAuth2 spec says it is required and MUST be the fixed string
|
||||
|
|
@ -217,7 +217,7 @@ class OAuth2PasswordRequestFormStrict(OAuth2PasswordRequestForm):
|
|||
self,
|
||||
grant_type: Annotated[
|
||||
str,
|
||||
Form(pattern="password"),
|
||||
Form(pattern="^password$"),
|
||||
Doc(
|
||||
"""
|
||||
The OAuth2 spec says it is required and MUST be the fixed string
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI, Security
|
||||
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
|
||||
|
|
@ -137,10 +138,18 @@ def test_strict_login_no_grant_type():
|
|||
)
|
||||
|
||||
|
||||
def test_strict_login_incorrect_grant_type():
|
||||
@pytest.mark.parametrize(
|
||||
argnames=["grant_type"],
|
||||
argvalues=[
|
||||
pytest.param("incorrect", id="incorrect value"),
|
||||
pytest.param("passwordblah", id="password with suffix"),
|
||||
pytest.param("blahpassword", id="password with prefix"),
|
||||
],
|
||||
)
|
||||
def test_strict_login_incorrect_grant_type(grant_type: str):
|
||||
response = client.post(
|
||||
"/login",
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": "incorrect"},
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
|
|
@ -149,9 +158,9 @@ def test_strict_login_incorrect_grant_type():
|
|||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern 'password'",
|
||||
"input": "incorrect",
|
||||
"ctx": {"pattern": "password"},
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -161,9 +170,9 @@ def test_strict_login_incorrect_grant_type():
|
|||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": 'string does not match regex "password"',
|
||||
"msg": 'string does not match regex "^password$"',
|
||||
"type": "value_error.str.regex",
|
||||
"ctx": {"pattern": "password"},
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -248,7 +257,7 @@ def test_openapi_schema():
|
|||
"properties": {
|
||||
"grant_type": {
|
||||
"title": "Grant Type",
|
||||
"pattern": "password",
|
||||
"pattern": "^password$",
|
||||
"type": "string",
|
||||
},
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI, Security
|
||||
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
|
||||
|
|
@ -141,10 +142,18 @@ def test_strict_login_no_grant_type():
|
|||
)
|
||||
|
||||
|
||||
def test_strict_login_incorrect_grant_type():
|
||||
@pytest.mark.parametrize(
|
||||
argnames=["grant_type"],
|
||||
argvalues=[
|
||||
pytest.param("incorrect", id="incorrect value"),
|
||||
pytest.param("passwordblah", id="password with suffix"),
|
||||
pytest.param("blahpassword", id="password with prefix"),
|
||||
],
|
||||
)
|
||||
def test_strict_login_incorrect_grant_type(grant_type: str):
|
||||
response = client.post(
|
||||
"/login",
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": "incorrect"},
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
|
|
@ -153,9 +162,9 @@ def test_strict_login_incorrect_grant_type():
|
|||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern 'password'",
|
||||
"input": "incorrect",
|
||||
"ctx": {"pattern": "password"},
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -165,9 +174,9 @@ def test_strict_login_incorrect_grant_type():
|
|||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": 'string does not match regex "password"',
|
||||
"msg": 'string does not match regex "^password$"',
|
||||
"type": "value_error.str.regex",
|
||||
"ctx": {"pattern": "password"},
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -252,7 +261,7 @@ def test_openapi_schema():
|
|||
"properties": {
|
||||
"grant_type": {
|
||||
"title": "Grant Type",
|
||||
"pattern": "password",
|
||||
"pattern": "^password$",
|
||||
"type": "string",
|
||||
},
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI, Security
|
||||
from fastapi.security import OAuth2, OAuth2PasswordRequestFormStrict
|
||||
|
|
@ -142,10 +143,18 @@ def test_strict_login_no_grant_type():
|
|||
)
|
||||
|
||||
|
||||
def test_strict_login_incorrect_grant_type():
|
||||
@pytest.mark.parametrize(
|
||||
argnames=["grant_type"],
|
||||
argvalues=[
|
||||
pytest.param("incorrect", id="incorrect value"),
|
||||
pytest.param("passwordblah", id="password with suffix"),
|
||||
pytest.param("blahpassword", id="password with prefix"),
|
||||
],
|
||||
)
|
||||
def test_strict_login_incorrect_grant_type(grant_type: str):
|
||||
response = client.post(
|
||||
"/login",
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": "incorrect"},
|
||||
data={"username": "johndoe", "password": "secret", "grant_type": grant_type},
|
||||
)
|
||||
assert response.status_code == 422
|
||||
assert response.json() == IsDict(
|
||||
|
|
@ -154,9 +163,9 @@ def test_strict_login_incorrect_grant_type():
|
|||
{
|
||||
"type": "string_pattern_mismatch",
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": "String should match pattern 'password'",
|
||||
"input": "incorrect",
|
||||
"ctx": {"pattern": "password"},
|
||||
"msg": "String should match pattern '^password$'",
|
||||
"input": grant_type,
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -166,9 +175,9 @@ def test_strict_login_incorrect_grant_type():
|
|||
"detail": [
|
||||
{
|
||||
"loc": ["body", "grant_type"],
|
||||
"msg": 'string does not match regex "password"',
|
||||
"msg": 'string does not match regex "^password$"',
|
||||
"type": "value_error.str.regex",
|
||||
"ctx": {"pattern": "password"},
|
||||
"ctx": {"pattern": "^password$"},
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -253,7 +262,7 @@ def test_openapi_schema():
|
|||
"properties": {
|
||||
"grant_type": {
|
||||
"title": "Grant Type",
|
||||
"pattern": "password",
|
||||
"pattern": "^password$",
|
||||
"type": "string",
|
||||
},
|
||||
"username": {"title": "Username", "type": "string"},
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ def test_openapi_schema(client: TestClient):
|
|||
{
|
||||
"title": "Grant Type",
|
||||
"anyOf": [
|
||||
{"pattern": "password", "type": "string"},
|
||||
{"pattern": "^password$", "type": "string"},
|
||||
{"type": "null"},
|
||||
],
|
||||
}
|
||||
|
|
@ -158,7 +158,7 @@ def test_openapi_schema(client: TestClient):
|
|||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Grant Type",
|
||||
"pattern": "password",
|
||||
"pattern": "^password$",
|
||||
"type": "string",
|
||||
}
|
||||
),
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ def test_openapi_schema(mod: ModuleType):
|
|||
{
|
||||
"title": "Grant Type",
|
||||
"anyOf": [
|
||||
{"pattern": "password", "type": "string"},
|
||||
{"pattern": "^password$", "type": "string"},
|
||||
{"type": "null"},
|
||||
],
|
||||
}
|
||||
|
|
@ -372,7 +372,7 @@ def test_openapi_schema(mod: ModuleType):
|
|||
# TODO: remove when deprecating Pydantic v1
|
||||
{
|
||||
"title": "Grant Type",
|
||||
"pattern": "password",
|
||||
"pattern": "^password$",
|
||||
"type": "string",
|
||||
}
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in New Issue