]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
📝 Bring the `scope` claim in line with the standard in `docs_src/security/tutorial005...
authorArnaud Durand <arnaud.durand@live.com>
Sun, 31 Aug 2025 10:03:10 +0000 (12:03 +0200)
committerGitHub <noreply@github.com>
Sun, 31 Aug 2025 10:03:10 +0000 (12:03 +0200)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Yurii Motov <yurii.motov.monte@gmail.com>
docs/em/docs/advanced/security/oauth2-scopes.md
docs/en/docs/advanced/security/oauth2-scopes.md
docs_src/security/tutorial005.py
docs_src/security/tutorial005_an.py
docs_src/security/tutorial005_an_py310.py
docs_src/security/tutorial005_an_py39.py
docs_src/security/tutorial005_py310.py
docs_src/security/tutorial005_py39.py

index b8c49bd11267d8962d845c8e5921dc0feb540492..9e3bc0058715bbd1bba74c1a85cdad2fd5cdd3c7 100644 (file)
@@ -62,7 +62,7 @@ Oauth2️⃣ 👫 🎻.
 
 🥇, ➡️ 🔜 👀 🍕 👈 🔀 ⚪️➡️ 🖼 👑 **🔰 - 👩‍💻 🦮** [Oauth2️⃣ ⏮️ 🔐 (&amp; 🔁), 📨 ⏮️ 🥙 🤝](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. 🔜 ⚙️ Oauth2️⃣ ↔:
 
-{* ../../docs_src/security/tutorial005.py hl[2,4,8,12,46,64,105,107:115,121:124,128:134,139,155] *}
+{* ../../docs_src/security/tutorial005.py hl[2,4,8,12,46,64,105,107:115,121:125,129:135,140,156] *}
 
 🔜 ➡️ 📄 👈 🔀 🔁 🔁.
 
@@ -98,7 +98,7 @@ Oauth2️⃣ 👫 🎻.
 
 ///
 
-{* ../../docs_src/security/tutorial005.py hl[155] *}
+{* ../../docs_src/security/tutorial005.py hl[156] *}
 
 ## 📣 ↔ *➡ 🛠️* &amp; 🔗
 
@@ -124,7 +124,7 @@ Oauth2️⃣ 👫 🎻.
 
 ///
 
-{* ../../docs_src/security/tutorial005.py hl[4,139,168] *}
+{* ../../docs_src/security/tutorial005.py hl[4,140,169] *}
 
 /// info | 📡 ℹ
 
@@ -180,7 +180,7 @@ Oauth2️⃣ 👫 🎻.
 
 👥 ✔ 👈 👥 ✔️ 👩‍💻 ⏮️ 👈 🆔, &amp; 🚥 🚫, 👥 🤚 👈 🎏 ⚠ 👥 ✍ ⏭.
 
-{* ../../docs_src/security/tutorial005.py hl[46,116:127] *}
+{* ../../docs_src/security/tutorial005.py hl[46,116:128] *}
 
 ## ✔ `scopes`
 
@@ -188,7 +188,7 @@ Oauth2️⃣ 👫 🎻.
 
 👉, 👥 ⚙️ `security_scopes.scopes`, 👈 🔌 `list` ⏮️ 🌐 👫 ↔ `str`.
 
-{* ../../docs_src/security/tutorial005.py hl[128:134] *}
+{* ../../docs_src/security/tutorial005.py hl[129:135] *}
 
 ## 🔗 🌲 &amp; ↔
 
index 0a84435e6dfa488e2eef73e3e9a064bf28bee86f..1c1cdfc7d8fd741c9a81d5a91e87874e0e04073c 100644 (file)
@@ -62,7 +62,7 @@ For OAuth2 they are just strings.
 
 First, let's quickly see the parts that change from the examples in the main **Tutorial - User Guide** for [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md){.internal-link target=_blank}. Now using OAuth2 scopes:
 
-{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:125,129:135,140,156] *}
+{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *}
 
 Now let's review those changes step by step.
 
@@ -98,7 +98,7 @@ But in your application, for security, you should make sure you only add the sco
 
 ///
 
-{* ../../docs_src/security/tutorial005_an_py310.py hl[156] *}
+{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *}
 
 ## Declare scopes in *path operations* and dependencies { #declare-scopes-in-path-operations-and-dependencies }
 
@@ -124,7 +124,7 @@ We are doing it here to demonstrate how **FastAPI** handles scopes declared at d
 
 ///
 
-{* ../../docs_src/security/tutorial005_an_py310.py hl[5,140,171] *}
+{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *}
 
 /// info | Technical Details
 
@@ -180,7 +180,7 @@ Instead of, for example, a `dict`, or something else, as it could break the appl
 
 We also verify that we have a user with that username, and if not, we raise that same exception we created before.
 
-{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:128] *}
+{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *}
 
 ## Verify the `scopes` { #verify-the-scopes }
 
@@ -188,7 +188,7 @@ We now verify that all the scopes required, by this dependency and all the depen
 
 For this, we use `security_scopes.scopes`, that contains a `list` with all these scopes as `str`.
 
-{* ../../docs_src/security/tutorial005_an_py310.py hl[129:135] *}
+{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *}
 
 ## Dependency tree and scopes { #dependency-tree-and-scopes }
 
index ccad0796944fa03c0ee71099b9f0dfef6c665606..447dacb3724df32980df3a693dc7a23d7d6e0896 100644 (file)
@@ -119,7 +119,8 @@ async def get_current_user(
         username: str = payload.get("sub")
         if username is None:
             raise credentials_exception
-        token_scopes = payload.get("scopes", [])
+        scope: str = payload.get("scope", "")
+        token_scopes = scope.split(" ")
         token_data = TokenData(scopes=token_scopes, username=username)
     except (InvalidTokenError, ValidationError):
         raise credentials_exception
@@ -153,7 +154,7 @@ async def login_for_access_token(
         raise HTTPException(status_code=400, detail="Incorrect username or password")
     access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
     access_token = create_access_token(
-        data={"sub": user.username, "scopes": form_data.scopes},
+        data={"sub": user.username, "scope": " ".join(form_data.scopes)},
         expires_delta=access_token_expires,
     )
     return Token(access_token=access_token, token_type="bearer")
index 2e8bb3bdb3b5565df08eb0bbd0cd0553f0df2087..d2c4fe9b8d2fabcbd9153a4ab3ae62e1a1ae989e 100644 (file)
@@ -120,7 +120,8 @@ async def get_current_user(
         username = payload.get("sub")
         if username is None:
             raise credentials_exception
-        token_scopes = payload.get("scopes", [])
+        scope: str = payload.get("scope", "")
+        token_scopes = scope.split(" ")
         token_data = TokenData(scopes=token_scopes, username=username)
     except (InvalidTokenError, ValidationError):
         raise credentials_exception
@@ -154,7 +155,7 @@ async def login_for_access_token(
         raise HTTPException(status_code=400, detail="Incorrect username or password")
     access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
     access_token = create_access_token(
-        data={"sub": user.username, "scopes": form_data.scopes},
+        data={"sub": user.username, "scope": " ".join(form_data.scopes)},
         expires_delta=access_token_expires,
     )
     return Token(access_token=access_token, token_type="bearer")
index 90781587f0c40a7ef182ec4e645626defbac5a73..e3527370d893a4267a60ada266d4b6ad38b758ce 100644 (file)
@@ -119,7 +119,8 @@ async def get_current_user(
         username = payload.get("sub")
         if username is None:
             raise credentials_exception
-        token_scopes = payload.get("scopes", [])
+        scope: str = payload.get("scope", "")
+        token_scopes = scope.split(" ")
         token_data = TokenData(scopes=token_scopes, username=username)
     except (InvalidTokenError, ValidationError):
         raise credentials_exception
@@ -153,7 +154,7 @@ async def login_for_access_token(
         raise HTTPException(status_code=400, detail="Incorrect username or password")
     access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
     access_token = create_access_token(
-        data={"sub": user.username, "scopes": form_data.scopes},
+        data={"sub": user.username, "scope": " ".join(form_data.scopes)},
         expires_delta=access_token_expires,
     )
     return Token(access_token=access_token, token_type="bearer")
index a5192d8d6623cd11528130db509310c5a161e911..3dc3140c3be0d02ed2d713b772d8be2ec73af484 100644 (file)
@@ -119,7 +119,8 @@ async def get_current_user(
         username = payload.get("sub")
         if username is None:
             raise credentials_exception
-        token_scopes = payload.get("scopes", [])
+        scope: str = payload.get("scope", "")
+        token_scopes = scope.split(" ")
         token_data = TokenData(scopes=token_scopes, username=username)
     except (InvalidTokenError, ValidationError):
         raise credentials_exception
@@ -153,7 +154,7 @@ async def login_for_access_token(
         raise HTTPException(status_code=400, detail="Incorrect username or password")
     access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
     access_token = create_access_token(
-        data={"sub": user.username, "scopes": form_data.scopes},
+        data={"sub": user.username, "scope": " ".join(form_data.scopes)},
         expires_delta=access_token_expires,
     )
     return Token(access_token=access_token, token_type="bearer")
index b244ef08e98d631612200f1b8a32991fb911550b..3fc15212bd29a6a37f65b1b2945bce7e4e345cb6 100644 (file)
@@ -118,7 +118,8 @@ async def get_current_user(
         username: str = payload.get("sub")
         if username is None:
             raise credentials_exception
-        token_scopes = payload.get("scopes", [])
+        scope: str = payload.get("scope", "")
+        token_scopes = scope.split(" ")
         token_data = TokenData(scopes=token_scopes, username=username)
     except (InvalidTokenError, ValidationError):
         raise credentials_exception
@@ -152,7 +153,7 @@ async def login_for_access_token(
         raise HTTPException(status_code=400, detail="Incorrect username or password")
     access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
     access_token = create_access_token(
-        data={"sub": user.username, "scopes": form_data.scopes},
+        data={"sub": user.username, "scope": " ".join(form_data.scopes)},
         expires_delta=access_token_expires,
     )
     return Token(access_token=access_token, token_type="bearer")
index 8f0e93376ae5b1832e96948919433f5c1fbc09c5..f9aed0a42a5f1ee80e76b5caaf2c7dabecd3aace 100644 (file)
@@ -119,7 +119,8 @@ async def get_current_user(
         username: str = payload.get("sub")
         if username is None:
             raise credentials_exception
-        token_scopes = payload.get("scopes", [])
+        scope: str = payload.get("scope", "")
+        token_scopes = scope.split(" ")
         token_data = TokenData(scopes=token_scopes, username=username)
     except (InvalidTokenError, ValidationError):
         raise credentials_exception
@@ -153,7 +154,7 @@ async def login_for_access_token(
         raise HTTPException(status_code=400, detail="Incorrect username or password")
     access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
     access_token = create_access_token(
-        data={"sub": user.username, "scopes": form_data.scopes},
+        data={"sub": user.username, "scope": " ".join(form_data.scopes)},
         expires_delta=access_token_expires,
     )
     return Token(access_token=access_token, token_type="bearer")