]> git.ipfire.org Git - thirdparty/fastapi/fastapi.git/commitdiff
:sparkles: Add docs for HTTP Basic Auth and tests (#177)
authorSebastián Ramírez <tiangolo@gmail.com>
Sun, 21 Apr 2019 18:30:58 +0000 (22:30 +0400)
committerGitHub <noreply@github.com>
Sun, 21 Apr 2019 18:30:58 +0000 (22:30 +0400)
docs/img/tutorial/security/image12.png [new file with mode: 0644]
docs/src/security/tutorial006.py [new file with mode: 0644]
docs/src/security/tutorial007.py [new file with mode: 0644]
docs/tutorial/security/http-basic-auth.md [new file with mode: 0644]
mkdocs.yml
tests/test_tutorial/test_security/test_tutorial006.py [moved from tests/test_security_http_basic.py with 87% similarity]

diff --git a/docs/img/tutorial/security/image12.png b/docs/img/tutorial/security/image12.png
new file mode 100644 (file)
index 0000000..58006d6
Binary files /dev/null and b/docs/img/tutorial/security/image12.png differ
diff --git a/docs/src/security/tutorial006.py b/docs/src/security/tutorial006.py
new file mode 100644 (file)
index 0000000..29121ff
--- /dev/null
@@ -0,0 +1,11 @@
+from fastapi import Depends, FastAPI
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+@app.get("/users/me")
+def read_current_user(credentials: HTTPBasicCredentials = Depends(security)):
+    return {"username": credentials.username, "password": credentials.password}
diff --git a/docs/src/security/tutorial007.py b/docs/src/security/tutorial007.py
new file mode 100644 (file)
index 0000000..dc4f4fb
--- /dev/null
@@ -0,0 +1,22 @@
+from fastapi import Depends, FastAPI, HTTPException
+from fastapi.security import HTTPBasic, HTTPBasicCredentials
+from starlette.status import HTTP_401_UNAUTHORIZED
+
+app = FastAPI()
+
+security = HTTPBasic()
+
+
+def get_current_username(credentials: HTTPBasicCredentials = Depends(security)):
+    if credentials.username != "foo" or credentials.password != "password":
+        raise HTTPException(
+            status_code=HTTP_401_UNAUTHORIZED,
+            detail="Incorrect email or password",
+            headers={"WWW-Authenticate": "Basic"},
+        )
+    return credentials.username
+
+
+@app.get("/users/me")
+def read_current_user(username: str = Depends(get_current_username)):
+    return {"username": username}
diff --git a/docs/tutorial/security/http-basic-auth.md b/docs/tutorial/security/http-basic-auth.md
new file mode 100644 (file)
index 0000000..d6ee6bc
--- /dev/null
@@ -0,0 +1,40 @@
+For the simplest cases, you can use HTTP Basic Auth.
+
+In HTTP Basic Auth, the application expects a header that contains a username and a password.
+
+If it doesn't receive it, it returns an HTTP 401 "Unauthorized" error.
+
+And returns a header `WWW-Authenticate` with a value of `Basic`, and an optional `realm` parameter.
+
+That tells the browser to show the integrated prompt for a username and password.
+
+Then, when you type that username and password, the browser sends them in the header automatically.
+
+## Simple HTTP Basic Auth
+
+* Import `HTTPBAsic` and `HTTPBasicCredentials`.
+* Create a "`security` scheme" using `HTTPBAsic`.
+* Use that `security` with a dependency in your *path operation*.
+* It returns an object of type `HTTPBasicCredentials`:
+    * It contains the `username` and `password` sent.
+
+
+```Python hl_lines="2 6 10"
+{!./src/security/tutorial006.py!}
+```
+
+When you try to open the URL for the first time (or click the "Execute" button in the docs) the browser will ask you for your username and password:
+
+<img src="/img/tutorial/security/image12.png">
+
+## Check the username
+
+Here's a more complete example.
+
+Use a dependency to check if the username and password are correct.
+
+If the credentials are incorrect, return an `HTTPException` with a status code 401 (the same returned when no credentials are provided) and add the header `WWW-Authenticate` to make the browser show the login prompt again:
+
+```Python hl_lines="10 11 12 13 14 15 16 17 21"
+{!./src/security/tutorial007.py!}
+```
index d1d6c20ed0efbb7d0c8df2e3615a1127967e8bda..2ea289d8eee5dc73849511d0894d333bc1778a4f 100644 (file)
@@ -58,6 +58,7 @@ nav:
             - Simple OAuth2 with Password and Bearer: 'tutorial/security/simple-oauth2.md'
             - OAuth2 with Password (and hashing), Bearer with JWT tokens: 'tutorial/security/oauth2-jwt.md'
             - OAuth2 scopes: 'tutorial/security/oauth2-scopes.md'
+            - HTTP Basic Auth: 'tutorial/security/http-basic-auth.md'
         - Middleware: 'tutorial/middleware.md'    
         - CORS (Cross-Origin Resource Sharing): 'tutorial/cors.md'    
         - Using the Request Directly: 'tutorial/using-request-directly.md'    
similarity index 87%
rename from tests/test_security_http_basic.py
rename to tests/test_tutorial/test_security/test_tutorial006.py
index 7d380fef0f0b3ffeff6c31c2e589bc9369d7c433..9dc753202aaa8401750785907f47a4a902d6a1de 100644 (file)
@@ -1,19 +1,9 @@
 from base64 import b64encode
 
-from fastapi import FastAPI, Security
-from fastapi.security import HTTPBasic, HTTPBasicCredentials
 from requests.auth import HTTPBasicAuth
 from starlette.testclient import TestClient
 
-app = FastAPI()
-
-security = HTTPBasic()
-
-
-@app.get("/users/me")
-def read_current_user(credentials: HTTPBasicCredentials = Security(security)):
-    return {"username": credentials.username, "password": credentials.password}
-
+from security.tutorial006 import app
 
 client = TestClient(app)