1633745009
FastAPI की मूल बातें जानें, कैसे जल्दी से सर्वर सेट करें और Auth0 के साथ सुरक्षित समापन बिंदु।
FastAPI एक अपेक्षाकृत नया पायथन ढांचा है जो आपको बहुत जल्दी एप्लिकेशन बनाने में सक्षम बनाता है। यह ढांचा आपको अंतर्निहित मॉड्यूल के साथ एपीआई अनुरोध डेटा को मूल रूप से पढ़ने की अनुमति देता है और फ्लास्क का हल्का विकल्प है।
इस लेख में, हम FastAPI
Auth0 का उपयोग करके , एक मूल API सेट अप करने, एक समापन बिंदु की सुरक्षा करने की सुविधाओं पर चर्चा करेंगे, और आप सीखेंगे कि आरंभ करना कितना आसान है।
FastAPI के साथ निर्माण शुरू करने से पहले , आपके पास Python और एक निःशुल्क Auth0 खाता होना चाहिए; आप यहां साइन अप कर सकते हैं ।3.8.2
यदि आपने वह पायथन संस्करण स्थापित किया है और आपका Auth0 खाता है, तो आप एक नया FastAPI
एप्लिकेशन बना सकते हैं । शुरू करने के लिए, भीतर विकसित करने के लिए एक नई निर्देशिका बनाएं। इस उदाहरण के लिए, आप नाम की एक निर्देशिका और नामक एक सबफ़ोल्डर बनाएंगे ; यह सबफ़ोल्डर वह जगह है जहाँ आपका कोड रहेगा।fastapi-exampleapplication
में फ़ोल्डर, निम्न आदेश का उपयोग कर एक आभासी वातावरण बनाने:fastapi-example
python3 -m venv .env
यह एक आभासी वातावरण बनाता है, और यह निर्भरता को आपके कंप्यूटर के बाकी पुस्तकालयों से अलग करता है। दूसरे शब्दों में, आप पुस्तकालयों और निर्भरताओं के साथ वैश्विक नामस्थान को प्रदूषित नहीं करते हैं, जो अन्य पायथन परियोजनाओं को प्रभावित कर सकता है।
वर्चुअल वातावरण बनाने के बाद, आपको इसे सक्रिय करने की आवश्यकता है। यूनिक्स-आधारित ऑपरेटिंग सिस्टम के लिए, यहाँ कमांड है:
source .env/bin/activate
यदि आप किसी अन्य ऑपरेटिंग सिस्टम में हैं, तो आप इस दस्तावेज़ीकरण पृष्ठ पर इस बात की सूची पा सकते हैं कि आप किसी परिवेश को कैसे सक्रिय कर सकते हैं । अपने आभासी वातावरण को सक्रिय करने के बाद, आप उन पैकेजों को स्थापित कर सकते हैं जिनका आप उपयोग करने जा रहे हैं: FastAPI
, uvicorn सर्वर, pyjwt , और अद्यतन pip
:
pip install -U pip
pip install fastapi uvicorn 'pyjwt[crypto]'
अब जब सभी पुस्तकालय स्थापित हो गए हैं, तो आप फ़ोल्डर के अंदर एक फ़ाइल बना सकते हैं ; वहीं आपका एपीआई कोड रहेगा। वसीयत की सामग्री इस तरह दिखेगी:main.pyapplicationmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import FastAPI
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
आइए इसे तोड़ते हैं: - शुरू करने के लिए, आप FastAPI
पुस्तकालय का आयात कर रहे हैं ; - फिर किसी ऑब्जेक्ट को इंस्टेंट करके अपना ऐप बनाना ; - उसके बाद, आप अनुरोधों को संभालने वाले मार्ग को परिभाषित करने के लिए उपयोग करते हैं ; - अंत में, आपके पास पथ संचालन फ़ंक्शन कहा जाता है , जो एक ऐसा फ़ंक्शन है जो हर बार उस मार्ग को कॉल करेगा, और यह स्वागत संदेश के साथ एक शब्दकोश देता है।FastAPI()@app.getGETpublic()
अब जब आपको अपना पहला एंडपॉइंट कोड मिल गया है, तो सर्वर को ऊपर और चलाने के लिए, प्रोजेक्ट की रूट डायरेक्टरी पर निम्न कमांड चलाएँ:
uvicorn application.main:app --reload
आपके सर्वर के चलने के साथ, आप या तो http://127.0.0.1:8000/docs पर जा सकते हैं और पहले एंडपॉइंट के लिए स्वचालित रूप से जेनरेट किए गए दस्तावेज़ों को देख सकते हैं जैसा कि नीचे दी गई छवि में दिखाया गया है:
या आप का उपयोग करके एक नई टर्मिनल विंडो में अपना पहला अनुरोध कर सकते हैं cURL
। ध्यान रखें कि यदि आप ऑपरेटिंग सिस्टम के पुराने संस्करण पर विंडोज उपयोगकर्ता हैं, तो आपको निम्न आदेश चलाने से पहले कर्ल स्थापित करना होगा :
curl -X 'GET' \
--url http://127.0.0.1:8000/api/public
और आपके द्वारा अभी-अभी किए गए अनुरोध के परिणामस्वरूप आपको एक JSON देखना चाहिए:
{
"status": "success",
"msg": "Hello from a public endpoint! You don't need to be authenticated to see this."
}
सादगी के लिए, आप cURL
इस पोस्ट के बाकी हिस्सों के लिए उपयोग करने जा रहे हैं ।
अब जब एक बेस एपीआई सर्वर सेट हो गया है, तो आप अपनी फाइल में एक और एंडपॉइंट जोड़ देंगे । इस एप्लिकेशन में, आपके पास सभी के लिए एक मार्ग उपलब्ध होगा और एक ऐसा मार्ग जिसे केवल आप उस एक्सेस टोकन से एक्सेस कर सकते हैं जो आपको Auth0 से मिलेगा।main.pyGET /api/publicGET /api/private
अब आपको फाइल को अपडेट करने की जरूरत है । यहां बताया गया है कि आपको आयात अनुभाग में क्या बदलना होगा:main.py
Depends
से आयात करने की आवश्यकता है fastapi
, जो कि FastAPI निर्भरता इंजेक्शन प्रणाली है;HTTPBearer
से कक्षा को आयात करने की भी आवश्यकता होगी , वाहक टोकन के साथ प्राधिकरण शीर्षलेखों के लिए एक अंतर्निहित सुरक्षा योजना;fastapi.security
HTTPBearer
। इसका उपयोग Bearer
निजी समापन बिंदु पर किए गए प्रत्येक अनुरोध में टोकन के साथ प्राधिकरण शीर्षलेख की उपस्थिति की गारंटी के लिए किया जाएगा ।टोकन सूचित एपीआई कि टोकन का वाहक अधिकृत किया गया है API तक पहुंच और गुंजाइश है कि प्राधिकरण के दौरान प्रदान की गई थी द्वारा निर्दिष्ट विशिष्ट कार्रवाई करने के लिए।
आयातों को अद्यतन करने के अलावा, आपको निजी समापन बिंदु लागू करने की आवश्यकता है। अंत बिंदु को भी स्वीकार करेंगे अनुरोध, और यहाँ कोड क्या है अब के लिए दिखाई देता है:/api/privateGETmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI # 👈 new imports
from fastapi.security import HTTPBearer # 👈 new imports
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer() # 👈 new code
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
# new code 👇
@app.get("/api/private")
def private(token: str = Depends(token_auth_scheme)):
"""A valid access token is required to access this route"""
result = token.credentials
return result
Depends
वर्ग प्रत्येक अनुरोध है कि किसी भी endpoint एक समारोह, वर्ग या उदाहरण के खिलाफ प्राप्त करता है के मूल्यांकन के लिए जिम्मेदार है। इस मामले में, यह HTTPBearer
योजना के खिलाफ अनुरोधों का मूल्यांकन करेगा जो एक वाहक टोकन के साथ प्राधिकरण शीर्षलेख के अनुरोध की जांच करेगा।
आप इस बारे में अधिक जानकारी प्राप्त कर सकते हैं कि
FastAPI
निर्भरता इंजेक्शन इसके दस्तावेज़ीकरण पर कैसे काम करता है ।
अब आपका निजी समापन बिंदु प्राप्त टोकन लौटाता है। यदि कोई टोकन प्रदान नहीं किया जाता है, तो यह 403 Forbidden
विवरण के साथ एक स्थिति कोड लौटाएगा, जिसमें कहा जाएगा कि आप हैं "Not authenticated"
। चूँकि आपने --reload
अपना सर्वर चलाते समय ध्वज का उपयोग किया था, इसलिए आपको कमांड को फिर से चलाने की आवश्यकता नहीं है; uvicorn
हर बार जब आप अपनी फ़ाइलें सहेजते हैं तो परिवर्तन उठाएंगे और सर्वर को अपडेट करेंगे। अब समापन बिंदु से उसके व्यवहार की जांच करने का अनुरोध करें। सबसे पहले, एक प्राधिकरण शीर्षलेख पारित किए बिना अनुरोध करें :GET /api/private
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private'
# {"detail": "Not authenticated"}
और अब, यदि आप प्राधिकरण शीर्षलेख के साथ अनुरोध करते हैं, लेकिन टोकन मान के रूप में एक यादृच्छिक स्ट्रिंग के साथ, आपको परिणाम के रूप में समान यादृच्छिक मान देखना चाहिए:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer FastAPI is awesome'
# "FastAPI is awesome"
जैसा कि आप देख सकते हैं, आपका समापन बिंदु सुरक्षित नहीं है क्योंकि यह प्राधिकरण शीर्षलेख के मान के रूप में किसी भी स्ट्रिंग को स्वीकार करता है। यह है पर्याप्त नहीं एक प्राधिकरण हैडर प्राप्त करने के लिए; किसी को समापन बिंदु तक पहुंचने देने के लिए आपको वाहक टोकन के मूल्य को भी सत्यापित करना होगा । आइए उस व्यवहार को ठीक करें।
इससे पहले कि आप उस बिंदु पर पहुँचें जहाँ आप अपने समापन बिंदुओं में टोकन को मान्य करने के लिए तैयार हैं, आपको Auth0 में एक एपीआई सेट करने की आवश्यकता है । जब यह API सेट अप किया जाता है, तो आपको Auth0 के लिए आवश्यक कुछ जानकारी तक पहुंच प्राप्त होती है - एक ऑडियंस, क्लाइंट आईडी और क्लाइंट सीक्रेट।
आपको सर्वर के भीतर से उस जानकारी तक पहुंच की भी आवश्यकता है; यहीं से एक कॉन्फ़िगरेशन फ़ाइल चलन में आती है। आपको .config
प्रोजेक्ट की जड़ पर कॉल की गई कॉन्फ़िगरेशन फ़ाइल बनाने की आवश्यकता होगी । यह वही है जो .config
फ़ाइल नीचे दिखनी चाहिए। तदनुसार मूल्यों को अद्यतन करना याद रखें:
# .config
[AUTH0]
DOMAIN = your.domain.auth0.com
API_AUDIENCE = your.api.audience
ALGORITHMS = RS256
ISSUER = https://your.domain.auth0.com/
यह कॉन्फ़िगरेशन टोकन सत्यापन चरण में Auth0 कॉन्फ़िगरेशन सेटिंग्स के लिए जाँच की पहेली का पहला भाग है। पालन करने के लिए एक और अच्छा नियम है कि अपनी कॉन्फ़िगरेशन फ़ाइलों को पर्यावरण चर के साथ स्रोत कोड में कभी भी प्रतिबद्ध न करें। ऐसा होने से रोकने के लिए, आपको .gitignore
प्रोजेक्ट के रूट में एक फ़ाइल बनानी चाहिए और .config
फ़ाइल को एक प्रविष्टि के रूप में जोड़ना चाहिए :
# .gitignore
.config
आपके FastAPI
सर्वर के पास अब एक मार्ग है, लेकिन यह अभी तक सुरक्षित नहीं है। यह केवल जांचता है कि क्या आपके पास अनुरोध में प्राधिकरण शीर्षलेख है, जिसका अर्थ है कि आप इस प्रक्रिया में एक चरण खो रहे हैं: आपको पहुंच टोकन को सत्यापित करने की आवश्यकता है। ऐसा करने के लिए, आपको एक ऐसी वस्तु बनाने की आवश्यकता है जो JWT को मान्य करने के लिए सभी चरणों को पूरा करे क्योंकि Auth0 के एक्सेस टोकन JWT हैं।GET /api/private
रूटिंग परिभाषा से जिम्मेदारियों को अलग करने के लिए, आपको सभी उपयोगिता कोड रखने के लिए फ़ोल्डर के अंदर नामक एक नई फ़ाइल बनानी चाहिए , जैसे एक्सेस टोकन को मान्य करना और कॉन्फ़िगरेशन जानकारी पढ़ना।utils.pyapplication
पायथन os
पुस्तकालय, साथ ही PyJWT
और configparser
पुस्तकालयों को आयात करके प्रारंभ करें । ओएस पुस्तकालय आपको पर्यावरण चरों तक पहुंच प्रदान करता है। जेडब्ल्यूटी पुस्तकालय आपको जेडब्ल्यूटी की जांच और सत्यापन करने के लिए कार्य देता है। ConfigParser
हमनाम पुस्तकालय से वर्ग अजगर में पाया विन्यास सेटिंग्स को पढ़ने के लिए एक तरीका प्रदान करता .config
फ़ाइल आपको पहले बनाए गए। और आयात के बाद आपके पास पहली चीज है जिसे एक फ़ंक्शन कहा जाता है , जिसे आप नीचे देख सकते हैं:set_up()
"""utils.py
"""
import os
import jwt
from configparser import ConfigParser
def set_up():
"""Sets up configuration for the app"""
env = os.getenv("ENV", ".config")
if env == ".config":
config = ConfigParser()
config.read(".config")
config = config["AUTH0"]
else:
config = {
"DOMAIN": os.getenv("DOMAIN", "your.domain.com"),
"API_AUDIENCE": os.getenv("API_AUDIENCE", "your.audience.com"),
"ISSUER": os.getenv("ISSUER", "https://your.domain.com/"),
"ALGORITHMS": os.getenv("ALGORITHMS", "RS256"),
}
return config
समारोह पढ़ने के लिए जिम्मेदार है फाइल और एक विन्यास उद्देश्य यह है कि एक शब्दकोश की तरह काम करता बनाने। चूंकि यह नमूना कोड पर्यावरण चर पर भी चलने के लिए तैयार है, डिफ़ॉल्ट रूप से फ़ंक्शन फ़ाइल को पढ़ने का प्रयास करेगा । आप पर्यावरण चर को किसी अन्य मान पर सेट करके इस व्यवहार को बदल सकते हैं, इस मामले में उपरोक्त खंड के तहत आप देख सकते हैं सभी पर्यावरण चर को पढ़कर एक शब्दकोश बनाया जाएगा ।set_up().configset_up().configENVelse
पहेली का अगला भाग वह है जहाँ जादू होता है। आप VerifyToken
JWT टोकन सत्यापन को संभालने के लिए एक वर्ग बनाएंगे :
# paste the code 👇 after the set_up() function in the utils.py file
class VerifyToken():
"""Does all the token verification using PyJWT"""
def __init__(self, token):
self.token = token
self.config = set_up()
# This gets the JWKS from a given URL and does processing so you can
# use any of the keys available
jwks_url = f'https://{self.config["DOMAIN"]}/.well-known/jwks.json'
self.jwks_client = jwt.PyJWKClient(jwks_url)
def verify(self):
# This gets the 'kid' from the passed token
try:
self.signing_key = self.jwks_client.get_signing_key_from_jwt(
self.token
).key
except jwt.exceptions.PyJWKClientError as error:
return {"status": "error", "msg": error.__str__()}
except jwt.exceptions.DecodeError as error:
return {"status": "error", "msg": error.__str__()}
try:
payload = jwt.decode(
self.token,
self.signing_key,
algorithms=self.config["ALGORITHMS"],
audience=self.config["API_AUDIENCE"],
issuer=self.config["ISSUER"],
)
except Exception as e:
return {"status": "error", "message": str(e)}
return payload
आइए यहां दिए गए चरणों को समझने के लिए इस वर्ग को तोड़ें:
__init__()
token
पैरामीटर को निर्दिष्ट करने के लिए ज़िम्मेदार है जिसकी VerifyToken
कक्षा को आवश्यकता है;set_up()
JWKS
का उपयोग करके फ़ाइल के लिए पथ सेट करता है । एक JSON वेब कुंजी सेट, या संक्षेप में JWKS में एक टोकन हस्ताक्षर को मान्य करने और यह सुनिश्चित करने के लिए आवश्यक जानकारी होती है कि यह एक वैध टोकन है। क्योंकि Auth0 OAuth 2.0 को लागू करता है, इसमें एक "प्रसिद्ध" समापन बिंदु है जिसे आप कॉल कर सकते हैं और टोकन और उसके गुणों को मान्य करने के लिए उपयोग किए जाने वाले अतिरिक्त मेटाडेटा प्राप्त कर सकते हैं।PyJWKClientPyJWT
verify()
kid
टोकन हस्ताक्षर को सत्यापित करने के लिए JWKS से उपयोग की गई कुंजी को हथियाने के लिए यह विधि कुंजी आईडी ( टोकन हेडर में मौजूद दावा) का उपयोग करती है। यदि यह चरण किसी भी संभावित त्रुटि से विफल हो जाता है, तो त्रुटि संदेश वापस आ जाता है;आइए देखें कि आगे के अनुभाग में हमारे निजी समापन बिंदु में कोड के इस टुकड़े का उपयोग कैसे करें।
अंतिम पहेली टुकड़ा उस वर्ग को आयात करना है जिसे आपने अभी फ़ाइल में बनाया है और इसे एंडपॉइंट में उपयोग करें । यहां आपको बदलने की आवश्यकता है:utils.pyGET /api/private
VerifyToken
, फिर अपने समापन बिंदु पर जाएं; आपको Response
कक्षा और status
वस्तु को आयात करने की भी आवश्यकता होगी fastapi
ताकि आप किसी त्रुटि के मामले में विस्तृत प्रतिक्रिया दे सकें;VerifyToken
कक्षा को टोकन पास करके और विधि का परिणाम एक त्रुटि है या नहीं, इसकी जाँच करके समापन बिंदु को समायोजित करने की आवश्यकता होगी ।verify()
यहां बताया गया है कि उपरोक्त सभी परिवर्तनों के साथ आपकी फ़ाइल कैसी दिखनी चाहिए:main.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI, Response, status # 👈 new imports
from fastapi.security import HTTPBearer
from .utils import VerifyToken # 👈 new import
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer()
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
@app.get("/api/private")
def private(response: Response, token: str = Depends(token_auth_scheme)): # 👈 updated code
"""A valid access token is required to access this route"""
result = VerifyToken(token.credentials).verify() # 👈 updated code
# 👇 new code
if result.get("status"):
response.status_code = status.HTTP_400_BAD_REQUEST
return result
# 👆 new code
return result
इस अपडेट के साथ, आप अपने सुरक्षित एंडपॉइंट को ठीक से सेट कर रहे हैं और आपको आवश्यक एक्सेस टोकन के लिए सभी सत्यापन चरण कर रहे हैं। मैं
भले ही आपने अपने सर्वर को --reload
ध्वज के साथ शुरू किया क्योंकि आपको यह सुनिश्चित करने की आवश्यकता है कि कॉन्फ़िगरेशन लोड हो गया है, यह uvicorn
प्रक्रिया को समाप्त करने और फिर सर्वर को पुनरारंभ करने का एक अच्छा समय है । यह .config
फ़ाइल या पर्यावरण चर से कॉन्फ़िगरेशन पैरामीटर के साथ आपके एपीआई की उचित कार्यक्षमता की गारंटी देगा ।
इससे पहले कि आप FastAPI
सर्वर में संरक्षित एंडपॉइंट के लिए अनुरोध कर सकें , आपको Auth0 से एक्सेस टोकन की आवश्यकता है। आप इसे Test
अपने API के टैब में Auth0 डैशबोर्ड से कॉपी करके प्राप्त कर सकते हैं ।
आप एक्सेस टोकन प्राप्त करने POST
के लिए Auth0 के एंडपॉइंट पर कर्ल अनुरोध का उपयोग कर सकते हैं, और आप इस अनुरोध को Auth0 डैशबोर्ड में अपने API के टैब से कॉपी कर सकते हैं । कर्ल अनुरोध इस तरह दिखेगा; आवश्यकतानुसार मानों को भरना याद रखें:oauth/tokenTest
curl -X 'POST' \
--url 'https://<YOUR DOMAIN HERE>/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data 'client_id=<YOUR CLIENT ID HERE>' \
--data client_secret=<YOUR CLIENT SECRET HERE> \
--data audience=<YOUR AUDIENCE HERE>
कमांड लाइन में, आपको अपने वाहक टोकन वाली एक प्रतिक्रिया दिखाई देनी चाहिए, जैसे कि:
{
"access_token": "<YOUR_BEARER_TOKEN>",
"expires_in": 86400,
"token_type": "Bearer"
}
अब आप निजी समापन बिंदु तक पहुँचने के लिए इस एक्सेस टोकन का उपयोग कर सकते हैं:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer <YOUR_BEARER_TOKEN>'
यदि अनुरोध सफल होता है, तो सर्वर एक्सेस टोकन के पेलोड को वापस भेज देगा:
{
"iss": "https://<YOUR_DOMAIN>/",
"sub": "iojadoijawdioWDasdijasoid@clients",
"aud": "http://<YOUR_AUDIENCE>",
"iat": 1630341660,
"exp": 1630428060,
"azp": "ADKASDawdopjaodjwopdAWDdsd",
"gty": "client-credentials"
}
ध्यान रखें कि यदि सत्यापन विफल हो जाता है, तो आपको इसका विवरण देखना चाहिए कि क्या गलत हुआ।
और बस इतना ही - आपने निजी समापन बिंदु की सुरक्षा करना और उसकी सुरक्षा का परीक्षण करना समाप्त कर दिया है।
आपने इस ब्लॉग पोस्ट में काफी कुछ सीखा। शुरू करने के लिए, आपने FastAPI
दो समापन बिंदुओं को लागू करके मूल बातें सीखीं - एक सार्वजनिक, एक निजी। आपने देखा कि इन दोनों अंतिम बिंदुओं के लिए अनुरोध करना कितना आसान है। आपने एक सत्यापन वर्ग बनाया और देखा कि कैसे PyJWT आपको Auth0 एक्सेस टोकन को मान्य करने में मदद करता है, और आपने सीखा कि JWKS क्या है।
आप Auth0 डैशबोर्ड में अपना API बनाने की प्रक्रिया से गुजरे हैं। आपने यह भी सीखा कि निर्भरता इंजेक्शन प्रणाली का लाभ उठाकर अपने एक अंतिम बिंदु को कैसे सुरक्षित किया जाए FastAPI आपको एकीकरण को लागू करने में मदद करने के लिए प्रदान करता है। और आपने यह सब बहुत जल्दी किया।
संक्षेप में, आपने सीखा है कि के साथ उठना और दौड़ना कितना आसान है FastAPI
, साथ ही साथ अपने समापन बिंदुओं की सुरक्षा के लिए Auth0 का उपयोग कैसे करना है।
इस GitHub रेपो में , आपको आज बनाए गए सैंपल एप्लिकेशन का पूरा कोड मिलेगा। यदि आपके कोई प्रश्न हैं, तो उन्हें इस ब्लॉग पोस्ट के लिए सामुदायिक फ़ोरम थ्रेड में पूछें।
#python #auth0 #fastapi
1633745009
FastAPI की मूल बातें जानें, कैसे जल्दी से सर्वर सेट करें और Auth0 के साथ सुरक्षित समापन बिंदु।
FastAPI एक अपेक्षाकृत नया पायथन ढांचा है जो आपको बहुत जल्दी एप्लिकेशन बनाने में सक्षम बनाता है। यह ढांचा आपको अंतर्निहित मॉड्यूल के साथ एपीआई अनुरोध डेटा को मूल रूप से पढ़ने की अनुमति देता है और फ्लास्क का हल्का विकल्प है।
इस लेख में, हम FastAPI
Auth0 का उपयोग करके , एक मूल API सेट अप करने, एक समापन बिंदु की सुरक्षा करने की सुविधाओं पर चर्चा करेंगे, और आप सीखेंगे कि आरंभ करना कितना आसान है।
FastAPI के साथ निर्माण शुरू करने से पहले , आपके पास Python और एक निःशुल्क Auth0 खाता होना चाहिए; आप यहां साइन अप कर सकते हैं ।3.8.2
यदि आपने वह पायथन संस्करण स्थापित किया है और आपका Auth0 खाता है, तो आप एक नया FastAPI
एप्लिकेशन बना सकते हैं । शुरू करने के लिए, भीतर विकसित करने के लिए एक नई निर्देशिका बनाएं। इस उदाहरण के लिए, आप नाम की एक निर्देशिका और नामक एक सबफ़ोल्डर बनाएंगे ; यह सबफ़ोल्डर वह जगह है जहाँ आपका कोड रहेगा।fastapi-exampleapplication
में फ़ोल्डर, निम्न आदेश का उपयोग कर एक आभासी वातावरण बनाने:fastapi-example
python3 -m venv .env
यह एक आभासी वातावरण बनाता है, और यह निर्भरता को आपके कंप्यूटर के बाकी पुस्तकालयों से अलग करता है। दूसरे शब्दों में, आप पुस्तकालयों और निर्भरताओं के साथ वैश्विक नामस्थान को प्रदूषित नहीं करते हैं, जो अन्य पायथन परियोजनाओं को प्रभावित कर सकता है।
वर्चुअल वातावरण बनाने के बाद, आपको इसे सक्रिय करने की आवश्यकता है। यूनिक्स-आधारित ऑपरेटिंग सिस्टम के लिए, यहाँ कमांड है:
source .env/bin/activate
यदि आप किसी अन्य ऑपरेटिंग सिस्टम में हैं, तो आप इस दस्तावेज़ीकरण पृष्ठ पर इस बात की सूची पा सकते हैं कि आप किसी परिवेश को कैसे सक्रिय कर सकते हैं । अपने आभासी वातावरण को सक्रिय करने के बाद, आप उन पैकेजों को स्थापित कर सकते हैं जिनका आप उपयोग करने जा रहे हैं: FastAPI
, uvicorn सर्वर, pyjwt , और अद्यतन pip
:
pip install -U pip
pip install fastapi uvicorn 'pyjwt[crypto]'
अब जब सभी पुस्तकालय स्थापित हो गए हैं, तो आप फ़ोल्डर के अंदर एक फ़ाइल बना सकते हैं ; वहीं आपका एपीआई कोड रहेगा। वसीयत की सामग्री इस तरह दिखेगी:main.pyapplicationmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import FastAPI
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
आइए इसे तोड़ते हैं: - शुरू करने के लिए, आप FastAPI
पुस्तकालय का आयात कर रहे हैं ; - फिर किसी ऑब्जेक्ट को इंस्टेंट करके अपना ऐप बनाना ; - उसके बाद, आप अनुरोधों को संभालने वाले मार्ग को परिभाषित करने के लिए उपयोग करते हैं ; - अंत में, आपके पास पथ संचालन फ़ंक्शन कहा जाता है , जो एक ऐसा फ़ंक्शन है जो हर बार उस मार्ग को कॉल करेगा, और यह स्वागत संदेश के साथ एक शब्दकोश देता है।FastAPI()@app.getGETpublic()
अब जब आपको अपना पहला एंडपॉइंट कोड मिल गया है, तो सर्वर को ऊपर और चलाने के लिए, प्रोजेक्ट की रूट डायरेक्टरी पर निम्न कमांड चलाएँ:
uvicorn application.main:app --reload
आपके सर्वर के चलने के साथ, आप या तो http://127.0.0.1:8000/docs पर जा सकते हैं और पहले एंडपॉइंट के लिए स्वचालित रूप से जेनरेट किए गए दस्तावेज़ों को देख सकते हैं जैसा कि नीचे दी गई छवि में दिखाया गया है:
या आप का उपयोग करके एक नई टर्मिनल विंडो में अपना पहला अनुरोध कर सकते हैं cURL
। ध्यान रखें कि यदि आप ऑपरेटिंग सिस्टम के पुराने संस्करण पर विंडोज उपयोगकर्ता हैं, तो आपको निम्न आदेश चलाने से पहले कर्ल स्थापित करना होगा :
curl -X 'GET' \
--url http://127.0.0.1:8000/api/public
और आपके द्वारा अभी-अभी किए गए अनुरोध के परिणामस्वरूप आपको एक JSON देखना चाहिए:
{
"status": "success",
"msg": "Hello from a public endpoint! You don't need to be authenticated to see this."
}
सादगी के लिए, आप cURL
इस पोस्ट के बाकी हिस्सों के लिए उपयोग करने जा रहे हैं ।
अब जब एक बेस एपीआई सर्वर सेट हो गया है, तो आप अपनी फाइल में एक और एंडपॉइंट जोड़ देंगे । इस एप्लिकेशन में, आपके पास सभी के लिए एक मार्ग उपलब्ध होगा और एक ऐसा मार्ग जिसे केवल आप उस एक्सेस टोकन से एक्सेस कर सकते हैं जो आपको Auth0 से मिलेगा।main.pyGET /api/publicGET /api/private
अब आपको फाइल को अपडेट करने की जरूरत है । यहां बताया गया है कि आपको आयात अनुभाग में क्या बदलना होगा:main.py
Depends
से आयात करने की आवश्यकता है fastapi
, जो कि FastAPI निर्भरता इंजेक्शन प्रणाली है;HTTPBearer
से कक्षा को आयात करने की भी आवश्यकता होगी , वाहक टोकन के साथ प्राधिकरण शीर्षलेखों के लिए एक अंतर्निहित सुरक्षा योजना;fastapi.security
HTTPBearer
। इसका उपयोग Bearer
निजी समापन बिंदु पर किए गए प्रत्येक अनुरोध में टोकन के साथ प्राधिकरण शीर्षलेख की उपस्थिति की गारंटी के लिए किया जाएगा ।टोकन सूचित एपीआई कि टोकन का वाहक अधिकृत किया गया है API तक पहुंच और गुंजाइश है कि प्राधिकरण के दौरान प्रदान की गई थी द्वारा निर्दिष्ट विशिष्ट कार्रवाई करने के लिए।
आयातों को अद्यतन करने के अलावा, आपको निजी समापन बिंदु लागू करने की आवश्यकता है। अंत बिंदु को भी स्वीकार करेंगे अनुरोध, और यहाँ कोड क्या है अब के लिए दिखाई देता है:/api/privateGETmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI # 👈 new imports
from fastapi.security import HTTPBearer # 👈 new imports
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer() # 👈 new code
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
# new code 👇
@app.get("/api/private")
def private(token: str = Depends(token_auth_scheme)):
"""A valid access token is required to access this route"""
result = token.credentials
return result
Depends
वर्ग प्रत्येक अनुरोध है कि किसी भी endpoint एक समारोह, वर्ग या उदाहरण के खिलाफ प्राप्त करता है के मूल्यांकन के लिए जिम्मेदार है। इस मामले में, यह HTTPBearer
योजना के खिलाफ अनुरोधों का मूल्यांकन करेगा जो एक वाहक टोकन के साथ प्राधिकरण शीर्षलेख के अनुरोध की जांच करेगा।
आप इस बारे में अधिक जानकारी प्राप्त कर सकते हैं कि
FastAPI
निर्भरता इंजेक्शन इसके दस्तावेज़ीकरण पर कैसे काम करता है ।
अब आपका निजी समापन बिंदु प्राप्त टोकन लौटाता है। यदि कोई टोकन प्रदान नहीं किया जाता है, तो यह 403 Forbidden
विवरण के साथ एक स्थिति कोड लौटाएगा, जिसमें कहा जाएगा कि आप हैं "Not authenticated"
। चूँकि आपने --reload
अपना सर्वर चलाते समय ध्वज का उपयोग किया था, इसलिए आपको कमांड को फिर से चलाने की आवश्यकता नहीं है; uvicorn
हर बार जब आप अपनी फ़ाइलें सहेजते हैं तो परिवर्तन उठाएंगे और सर्वर को अपडेट करेंगे। अब समापन बिंदु से उसके व्यवहार की जांच करने का अनुरोध करें। सबसे पहले, एक प्राधिकरण शीर्षलेख पारित किए बिना अनुरोध करें :GET /api/private
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private'
# {"detail": "Not authenticated"}
और अब, यदि आप प्राधिकरण शीर्षलेख के साथ अनुरोध करते हैं, लेकिन टोकन मान के रूप में एक यादृच्छिक स्ट्रिंग के साथ, आपको परिणाम के रूप में समान यादृच्छिक मान देखना चाहिए:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer FastAPI is awesome'
# "FastAPI is awesome"
जैसा कि आप देख सकते हैं, आपका समापन बिंदु सुरक्षित नहीं है क्योंकि यह प्राधिकरण शीर्षलेख के मान के रूप में किसी भी स्ट्रिंग को स्वीकार करता है। यह है पर्याप्त नहीं एक प्राधिकरण हैडर प्राप्त करने के लिए; किसी को समापन बिंदु तक पहुंचने देने के लिए आपको वाहक टोकन के मूल्य को भी सत्यापित करना होगा । आइए उस व्यवहार को ठीक करें।
इससे पहले कि आप उस बिंदु पर पहुँचें जहाँ आप अपने समापन बिंदुओं में टोकन को मान्य करने के लिए तैयार हैं, आपको Auth0 में एक एपीआई सेट करने की आवश्यकता है । जब यह API सेट अप किया जाता है, तो आपको Auth0 के लिए आवश्यक कुछ जानकारी तक पहुंच प्राप्त होती है - एक ऑडियंस, क्लाइंट आईडी और क्लाइंट सीक्रेट।
आपको सर्वर के भीतर से उस जानकारी तक पहुंच की भी आवश्यकता है; यहीं से एक कॉन्फ़िगरेशन फ़ाइल चलन में आती है। आपको .config
प्रोजेक्ट की जड़ पर कॉल की गई कॉन्फ़िगरेशन फ़ाइल बनाने की आवश्यकता होगी । यह वही है जो .config
फ़ाइल नीचे दिखनी चाहिए। तदनुसार मूल्यों को अद्यतन करना याद रखें:
# .config
[AUTH0]
DOMAIN = your.domain.auth0.com
API_AUDIENCE = your.api.audience
ALGORITHMS = RS256
ISSUER = https://your.domain.auth0.com/
यह कॉन्फ़िगरेशन टोकन सत्यापन चरण में Auth0 कॉन्फ़िगरेशन सेटिंग्स के लिए जाँच की पहेली का पहला भाग है। पालन करने के लिए एक और अच्छा नियम है कि अपनी कॉन्फ़िगरेशन फ़ाइलों को पर्यावरण चर के साथ स्रोत कोड में कभी भी प्रतिबद्ध न करें। ऐसा होने से रोकने के लिए, आपको .gitignore
प्रोजेक्ट के रूट में एक फ़ाइल बनानी चाहिए और .config
फ़ाइल को एक प्रविष्टि के रूप में जोड़ना चाहिए :
# .gitignore
.config
आपके FastAPI
सर्वर के पास अब एक मार्ग है, लेकिन यह अभी तक सुरक्षित नहीं है। यह केवल जांचता है कि क्या आपके पास अनुरोध में प्राधिकरण शीर्षलेख है, जिसका अर्थ है कि आप इस प्रक्रिया में एक चरण खो रहे हैं: आपको पहुंच टोकन को सत्यापित करने की आवश्यकता है। ऐसा करने के लिए, आपको एक ऐसी वस्तु बनाने की आवश्यकता है जो JWT को मान्य करने के लिए सभी चरणों को पूरा करे क्योंकि Auth0 के एक्सेस टोकन JWT हैं।GET /api/private
रूटिंग परिभाषा से जिम्मेदारियों को अलग करने के लिए, आपको सभी उपयोगिता कोड रखने के लिए फ़ोल्डर के अंदर नामक एक नई फ़ाइल बनानी चाहिए , जैसे एक्सेस टोकन को मान्य करना और कॉन्फ़िगरेशन जानकारी पढ़ना।utils.pyapplication
पायथन os
पुस्तकालय, साथ ही PyJWT
और configparser
पुस्तकालयों को आयात करके प्रारंभ करें । ओएस पुस्तकालय आपको पर्यावरण चरों तक पहुंच प्रदान करता है। जेडब्ल्यूटी पुस्तकालय आपको जेडब्ल्यूटी की जांच और सत्यापन करने के लिए कार्य देता है। ConfigParser
हमनाम पुस्तकालय से वर्ग अजगर में पाया विन्यास सेटिंग्स को पढ़ने के लिए एक तरीका प्रदान करता .config
फ़ाइल आपको पहले बनाए गए। और आयात के बाद आपके पास पहली चीज है जिसे एक फ़ंक्शन कहा जाता है , जिसे आप नीचे देख सकते हैं:set_up()
"""utils.py
"""
import os
import jwt
from configparser import ConfigParser
def set_up():
"""Sets up configuration for the app"""
env = os.getenv("ENV", ".config")
if env == ".config":
config = ConfigParser()
config.read(".config")
config = config["AUTH0"]
else:
config = {
"DOMAIN": os.getenv("DOMAIN", "your.domain.com"),
"API_AUDIENCE": os.getenv("API_AUDIENCE", "your.audience.com"),
"ISSUER": os.getenv("ISSUER", "https://your.domain.com/"),
"ALGORITHMS": os.getenv("ALGORITHMS", "RS256"),
}
return config
समारोह पढ़ने के लिए जिम्मेदार है फाइल और एक विन्यास उद्देश्य यह है कि एक शब्दकोश की तरह काम करता बनाने। चूंकि यह नमूना कोड पर्यावरण चर पर भी चलने के लिए तैयार है, डिफ़ॉल्ट रूप से फ़ंक्शन फ़ाइल को पढ़ने का प्रयास करेगा । आप पर्यावरण चर को किसी अन्य मान पर सेट करके इस व्यवहार को बदल सकते हैं, इस मामले में उपरोक्त खंड के तहत आप देख सकते हैं सभी पर्यावरण चर को पढ़कर एक शब्दकोश बनाया जाएगा ।set_up().configset_up().configENVelse
पहेली का अगला भाग वह है जहाँ जादू होता है। आप VerifyToken
JWT टोकन सत्यापन को संभालने के लिए एक वर्ग बनाएंगे :
# paste the code 👇 after the set_up() function in the utils.py file
class VerifyToken():
"""Does all the token verification using PyJWT"""
def __init__(self, token):
self.token = token
self.config = set_up()
# This gets the JWKS from a given URL and does processing so you can
# use any of the keys available
jwks_url = f'https://{self.config["DOMAIN"]}/.well-known/jwks.json'
self.jwks_client = jwt.PyJWKClient(jwks_url)
def verify(self):
# This gets the 'kid' from the passed token
try:
self.signing_key = self.jwks_client.get_signing_key_from_jwt(
self.token
).key
except jwt.exceptions.PyJWKClientError as error:
return {"status": "error", "msg": error.__str__()}
except jwt.exceptions.DecodeError as error:
return {"status": "error", "msg": error.__str__()}
try:
payload = jwt.decode(
self.token,
self.signing_key,
algorithms=self.config["ALGORITHMS"],
audience=self.config["API_AUDIENCE"],
issuer=self.config["ISSUER"],
)
except Exception as e:
return {"status": "error", "message": str(e)}
return payload
आइए यहां दिए गए चरणों को समझने के लिए इस वर्ग को तोड़ें:
__init__()
token
पैरामीटर को निर्दिष्ट करने के लिए ज़िम्मेदार है जिसकी VerifyToken
कक्षा को आवश्यकता है;set_up()
JWKS
का उपयोग करके फ़ाइल के लिए पथ सेट करता है । एक JSON वेब कुंजी सेट, या संक्षेप में JWKS में एक टोकन हस्ताक्षर को मान्य करने और यह सुनिश्चित करने के लिए आवश्यक जानकारी होती है कि यह एक वैध टोकन है। क्योंकि Auth0 OAuth 2.0 को लागू करता है, इसमें एक "प्रसिद्ध" समापन बिंदु है जिसे आप कॉल कर सकते हैं और टोकन और उसके गुणों को मान्य करने के लिए उपयोग किए जाने वाले अतिरिक्त मेटाडेटा प्राप्त कर सकते हैं।PyJWKClientPyJWT
verify()
kid
टोकन हस्ताक्षर को सत्यापित करने के लिए JWKS से उपयोग की गई कुंजी को हथियाने के लिए यह विधि कुंजी आईडी ( टोकन हेडर में मौजूद दावा) का उपयोग करती है। यदि यह चरण किसी भी संभावित त्रुटि से विफल हो जाता है, तो त्रुटि संदेश वापस आ जाता है;आइए देखें कि आगे के अनुभाग में हमारे निजी समापन बिंदु में कोड के इस टुकड़े का उपयोग कैसे करें।
अंतिम पहेली टुकड़ा उस वर्ग को आयात करना है जिसे आपने अभी फ़ाइल में बनाया है और इसे एंडपॉइंट में उपयोग करें । यहां आपको बदलने की आवश्यकता है:utils.pyGET /api/private
VerifyToken
, फिर अपने समापन बिंदु पर जाएं; आपको Response
कक्षा और status
वस्तु को आयात करने की भी आवश्यकता होगी fastapi
ताकि आप किसी त्रुटि के मामले में विस्तृत प्रतिक्रिया दे सकें;VerifyToken
कक्षा को टोकन पास करके और विधि का परिणाम एक त्रुटि है या नहीं, इसकी जाँच करके समापन बिंदु को समायोजित करने की आवश्यकता होगी ।verify()
यहां बताया गया है कि उपरोक्त सभी परिवर्तनों के साथ आपकी फ़ाइल कैसी दिखनी चाहिए:main.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI, Response, status # 👈 new imports
from fastapi.security import HTTPBearer
from .utils import VerifyToken # 👈 new import
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer()
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
@app.get("/api/private")
def private(response: Response, token: str = Depends(token_auth_scheme)): # 👈 updated code
"""A valid access token is required to access this route"""
result = VerifyToken(token.credentials).verify() # 👈 updated code
# 👇 new code
if result.get("status"):
response.status_code = status.HTTP_400_BAD_REQUEST
return result
# 👆 new code
return result
इस अपडेट के साथ, आप अपने सुरक्षित एंडपॉइंट को ठीक से सेट कर रहे हैं और आपको आवश्यक एक्सेस टोकन के लिए सभी सत्यापन चरण कर रहे हैं। मैं
भले ही आपने अपने सर्वर को --reload
ध्वज के साथ शुरू किया क्योंकि आपको यह सुनिश्चित करने की आवश्यकता है कि कॉन्फ़िगरेशन लोड हो गया है, यह uvicorn
प्रक्रिया को समाप्त करने और फिर सर्वर को पुनरारंभ करने का एक अच्छा समय है । यह .config
फ़ाइल या पर्यावरण चर से कॉन्फ़िगरेशन पैरामीटर के साथ आपके एपीआई की उचित कार्यक्षमता की गारंटी देगा ।
इससे पहले कि आप FastAPI
सर्वर में संरक्षित एंडपॉइंट के लिए अनुरोध कर सकें , आपको Auth0 से एक्सेस टोकन की आवश्यकता है। आप इसे Test
अपने API के टैब में Auth0 डैशबोर्ड से कॉपी करके प्राप्त कर सकते हैं ।
आप एक्सेस टोकन प्राप्त करने POST
के लिए Auth0 के एंडपॉइंट पर कर्ल अनुरोध का उपयोग कर सकते हैं, और आप इस अनुरोध को Auth0 डैशबोर्ड में अपने API के टैब से कॉपी कर सकते हैं । कर्ल अनुरोध इस तरह दिखेगा; आवश्यकतानुसार मानों को भरना याद रखें:oauth/tokenTest
curl -X 'POST' \
--url 'https://<YOUR DOMAIN HERE>/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data 'client_id=<YOUR CLIENT ID HERE>' \
--data client_secret=<YOUR CLIENT SECRET HERE> \
--data audience=<YOUR AUDIENCE HERE>
कमांड लाइन में, आपको अपने वाहक टोकन वाली एक प्रतिक्रिया दिखाई देनी चाहिए, जैसे कि:
{
"access_token": "<YOUR_BEARER_TOKEN>",
"expires_in": 86400,
"token_type": "Bearer"
}
अब आप निजी समापन बिंदु तक पहुँचने के लिए इस एक्सेस टोकन का उपयोग कर सकते हैं:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer <YOUR_BEARER_TOKEN>'
यदि अनुरोध सफल होता है, तो सर्वर एक्सेस टोकन के पेलोड को वापस भेज देगा:
{
"iss": "https://<YOUR_DOMAIN>/",
"sub": "iojadoijawdioWDasdijasoid@clients",
"aud": "http://<YOUR_AUDIENCE>",
"iat": 1630341660,
"exp": 1630428060,
"azp": "ADKASDawdopjaodjwopdAWDdsd",
"gty": "client-credentials"
}
ध्यान रखें कि यदि सत्यापन विफल हो जाता है, तो आपको इसका विवरण देखना चाहिए कि क्या गलत हुआ।
और बस इतना ही - आपने निजी समापन बिंदु की सुरक्षा करना और उसकी सुरक्षा का परीक्षण करना समाप्त कर दिया है।
आपने इस ब्लॉग पोस्ट में काफी कुछ सीखा। शुरू करने के लिए, आपने FastAPI
दो समापन बिंदुओं को लागू करके मूल बातें सीखीं - एक सार्वजनिक, एक निजी। आपने देखा कि इन दोनों अंतिम बिंदुओं के लिए अनुरोध करना कितना आसान है। आपने एक सत्यापन वर्ग बनाया और देखा कि कैसे PyJWT आपको Auth0 एक्सेस टोकन को मान्य करने में मदद करता है, और आपने सीखा कि JWKS क्या है।
आप Auth0 डैशबोर्ड में अपना API बनाने की प्रक्रिया से गुजरे हैं। आपने यह भी सीखा कि निर्भरता इंजेक्शन प्रणाली का लाभ उठाकर अपने एक अंतिम बिंदु को कैसे सुरक्षित किया जाए FastAPI आपको एकीकरण को लागू करने में मदद करने के लिए प्रदान करता है। और आपने यह सब बहुत जल्दी किया।
संक्षेप में, आपने सीखा है कि के साथ उठना और दौड़ना कितना आसान है FastAPI
, साथ ही साथ अपने समापन बिंदुओं की सुरक्षा के लिए Auth0 का उपयोग कैसे करना है।
इस GitHub रेपो में , आपको आज बनाए गए सैंपल एप्लिकेशन का पूरा कोड मिलेगा। यदि आपके कोई प्रश्न हैं, तो उन्हें इस ब्लॉग पोस्ट के लिए सामुदायिक फ़ोरम थ्रेड में पूछें।
#python #auth0 #fastapi
1633743973
Protecting your API can be a hard task but if you use Auth0 you can do it in a few easy steps!
In this video you will learn how to leverage the FastAPI dependency injection system to integrate your API with Auth0 and protect your endpoints.
You'll see how that affects your API documentation and how you can use code we provided to verify your Auth0 access token
Chapters:
00:00 Intro
1:22 Running the Example Project
3:33 Dependency Injection System in FastAPI
5:09 Configuring an API in Auth0
7:10 Protecting the Endpoint
16:16 Making Protected Requests
24:54 Outro
Links:
- Code sample: https://github.com/jtemporal/fastapi-and-auth0
- Securing a FastAPI server with Auth0 by Mark Halpin: http://auth0.com/blog/build-and-secure-fastapi-server-with-auth0
- A very complete blog post on "How to Handle JWTs in Python": https://auth0.com/blog/how-to-handle-jwt-in-python/
- Auth0's page on JWTs: https://auth0.com/learn/json-web-tokens/
- Auth0's free ebook on JWTs: https://auth0.com/resources/ebooks/jwt-handbook
- Documentation on Python virtual environments: https://docs.python.org/3/library/venv.html#creating-virtual-environments
#api #auth0 #fastapi #python
1673419474
Chapters:
00:00 Intro
1:22 Running the Example Project
3:33 Dependency Injection System in FastAPI
5:09 Configuring an API in Auth0
7:10 Protecting the Endpoint
16:16 Making Protected Requests
24:54 Outro
Links:
- Code sample: https://github.com/jtemporal/fastapi-and-auth0
#api #fastapi #auth0
1633745377
Aprenda los conceptos básicos de FastAPI, cómo configurar rápidamente un servidor y proteger los puntos finales con Auth0.
FastAPI es un marco Python relativamente nuevo que le permite crear aplicaciones muy rápidamente. Este marco le permite leer datos de solicitud de API sin problemas con módulos integrados y es una alternativa ligera a Flask.
En este artículo, FastAPI
repasaremos las características de , configuraremos una API básica, protegeremos un endpoint usando Auth0 y aprenderá lo simple que es comenzar.
Antes de comenzar a compilar con FastAPI , debe tener Python y una cuenta Auth0 gratuita; puedes registrarte aquí .3.8.2
Si tiene instalada esa versión de Python y su cuenta Auth0, puede crear una nueva FastAPI
aplicación. Para comenzar, cree un nuevo directorio para desarrollar. Para este ejemplo, creará un directorio llamado y una subcarpeta llamada ; esta subcarpeta es donde vivirá su código.fastapi-exampleapplication
En la carpeta, cree un entorno virtual con el siguiente comando:fastapi-example
python3 -m venv .env
Esto crea un entorno virtual y separa las dependencias del resto de las bibliotecas de su computadora. En otras palabras, no contamina el espacio de nombres global con bibliotecas y dependencias, lo que podría afectar a otros proyectos de Python.
Después de crear el entorno virtual, debe activarlo. Para los sistemas operativos basados en Unix, aquí está el comando:
source .env/bin/activate
Si está en otro sistema operativo, puede encontrar una lista de cómo puede activar un entorno en esta página de documentación . Después de la activación de su entorno virtual, puede instalar los paquetes que se van a usar: FastAPI
, uvicorn servidor, pyjwt y actualización pip
:
pip install -U pip
pip install fastapi uvicorn 'pyjwt[crypto]'
Ahora que todas las bibliotecas están instaladas, puede crear un archivo dentro de la carpeta; ahí es donde vivirá su código API. El contenido del se verá así:main.pyapplicationmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import FastAPI
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
Analicemos esto: - Para empezar, está importando la FastAPI
biblioteca; - Luego, cree su aplicación creando una instancia de un objeto; - Después de eso, se usa para definir una ruta que maneja las solicitudes; - Finalmente, tiene la función de operación de ruta llamada , que es una función que se ejecutará cada vez que se llame a esa ruta, y devuelve un diccionario con el mensaje de bienvenida.FastAPI()@app.getGETpublic()
Ahora que tiene su primer código de punto final, para que el servidor esté en funcionamiento, ejecute el siguiente comando en el directorio raíz del proyecto:
uvicorn application.main:app --reload
Con su servidor en ejecución, puede ir a http://127.0.0.1:8000/docs para ver la documentación generada automáticamente para el primer punto final como se muestra en la siguiente imagen:
O puede realizar su primera solicitud en una nueva ventana de terminal usando cURL
. Tenga en cuenta que si es un usuario de Windows en una versión anterior del sistema operativo, tendrá que instalar curl antes de ejecutar el siguiente comando:
curl -X 'GET' \
--url http://127.0.0.1:8000/api/public
Y debería ver un JSON como resultado de la solicitud que acaba de hacer similar a esto:
{
"status": "success",
"msg": "Hello from a public endpoint! You don't need to be authenticated to see this."
}
En aras de la simplicidad, usará el cURL
para el resto de esta publicación.
Ahora que está configurado un servidor API base, agregará un punto final más a su archivo. En esta aplicación, tendrás una ruta disponible para todos y una ruta a la que solo tú puedes acceder con el token de acceso que obtendrás de Auth0.main.pyGET /api/publicGET /api/private
Ahora necesitas actualizar el archivo. Esto es lo que necesitará cambiar en la sección de importaciones:main.py
Depends
desde el fastapi
módulo, ese es el sistema de inyección de dependencia FastAPI;HTTPBearer
clase del módulo, un esquema de seguridad integrado para encabezados de autorización con tokens de portador;fastapi.security
HTTPBearer
. Esto se utilizará para garantizar la presencia del encabezado de autorización con el Bearer
token en cada solicitud realizada al punto final privado.El token informa a la API que el portador del token ha sido autorizado para acceder a la API y realizar acciones específicas especificadas por el alcance que se otorgó durante la autorización.
Además de actualizar las importaciones, debe implementar el punto final privado. El punto final también aceptará solicitudes, y así es como se ve el código por ahora:/api/privateGETmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI # 👈 new imports
from fastapi.security import HTTPBearer # 👈 new imports
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer() # 👈 new code
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
# new code 👇
@app.get("/api/private")
def private(token: str = Depends(token_auth_scheme)):
"""A valid access token is required to access this route"""
result = token.credentials
return result
La Depends
clase es responsable de evaluar cada solicitud que recibe un punto final determinado frente a una función, clase o instancia. En este caso, evaluará las solicitudes contra el HTTPBearer
esquema que verificará la solicitud de un encabezado de autorización con un token de portador.
Puede encontrar más detalles sobre cómo
FastAPI
funciona la inyección de dependencia en su documentación .
Ahora su punto final privado devuelve el token recibido. Si no se proporciona ningún token, devolverá un 403 Forbidden
código de estado con el detalle que dice que sí "Not authenticated"
. Debido a que usó la --reload
bandera mientras ejecutaba su servidor, no necesita volver a ejecutar el comando; uvicorn
recogerá los cambios y actualizará el servidor cada vez que guarde sus archivos. Ahora haga una solicitud al punto final para verificar su comportamiento. Primero, hagamos una solicitud sin pasar un encabezado de autorización:GET /api/private
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private'
# {"detail": "Not authenticated"}
Y ahora, si realiza una solicitud con el encabezado de autorización, pero con una cadena aleatoria como valor de token, debería ver el mismo valor aleatorio como resultado:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer FastAPI is awesome'
# "FastAPI is awesome"
Como puede ver, su punto final no está protegido, ya que acepta cualquier cadena como valor para el encabezado de autorización. No es suficiente recibir un encabezado de autorización; también debe verificar el valor del token de portador para permitir que alguien acceda al punto final. Arreglemos ese comportamiento.
Antes de llegar al punto en el que esté listo para validar tokens en sus puntos finales, debe configurar una API en Auth0 . Cuando se configura esta API, obtiene acceso a algunos datos que Auth0 requiere: una audiencia, una ID de cliente y un secreto de cliente.
También necesita tener acceso a esa información desde el servidor; ahí es donde entra en juego un archivo de configuración. Deberá crear un archivo de configuración llamado .config
en la raíz del proyecto. Así es como .config
debería verse el archivo a continuación. Recuerde actualizar los valores en consecuencia:
# .config
[AUTH0]
DOMAIN = your.domain.auth0.com
API_AUDIENCE = your.api.audience
ALGORITHMS = RS256
ISSUER = https://your.domain.auth0.com/
Esta configuración es la primera pieza del rompecabezas para verificar los valores de configuración de Auth0 en la etapa de validación del token. Otra buena regla a seguir es nunca enviar sus archivos de configuración con variables de entorno al código fuente. Para evitar que esto suceda, debe crear un .gitignore
archivo en la raíz del proyecto y agregar el .config
archivo como una entrada:
# .gitignore
.config
Su FastAPI
servidor ahora tiene una ruta, pero aún no está protegida. Solo verifica si tiene un encabezado de autorización en la solicitud, lo que significa que le falta un paso en el proceso: debe validar el token de acceso. Para hacer eso, necesita crear un objeto que realice todos los pasos para validar un JWT porque los tokens de acceso de Auth0 son JWT.GET /api/private
Para separar las responsabilidades de la definición de enrutamiento, debe crear un nuevo archivo llamado dentro de la carpeta para contener todo el código de la utilidad, como validar el token de acceso y leer la información de configuración.utils.pyapplication
Comience importando la os
biblioteca de Python , así como las bibliotecas PyJWT
y configparser
. La biblioteca del sistema operativo le da acceso a las variables de entorno. La biblioteca JWT le brinda funciones para verificar y validar un JWT. La ConfigParser
clase de la biblioteca homónima proporciona una forma para que Python lea los ajustes de configuración que se encuentran en el .config
archivo que creó anteriormente. Y lo primero que tienes después de las importaciones es una función llamada , que puedes ver a continuación:set_up()
"""utils.py
"""
import os
import jwt
from configparser import ConfigParser
def set_up():
"""Sets up configuration for the app"""
env = os.getenv("ENV", ".config")
if env == ".config":
config = ConfigParser()
config.read(".config")
config = config["AUTH0"]
else:
config = {
"DOMAIN": os.getenv("DOMAIN", "your.domain.com"),
"API_AUDIENCE": os.getenv("API_AUDIENCE", "your.audience.com"),
"ISSUER": os.getenv("ISSUER", "https://your.domain.com/"),
"ALGORITHMS": os.getenv("ALGORITHMS", "RS256"),
}
return config
La función se encarga de leer el archivo y crear un objeto de configuración que funciona como un diccionario. Debido a que este código de muestra está preparado para ejecutarse también en variables de entorno, la función por defecto intentará leer el archivo. Puede cambiar este comportamiento estableciendo la variable de entorno en cualquier otro valor, en cuyo caso se creará un diccionario leyendo todas las variables de entorno que puede ver en la cláusula anterior.set_up().configset_up().configENVelse
La siguiente pieza del rompecabezas es donde ocurre la magia. Creará una VerifyToken
clase para manejar la validación del token JWT:
# paste the code 👇 after the set_up() function in the utils.py file
class VerifyToken():
"""Does all the token verification using PyJWT"""
def __init__(self, token):
self.token = token
self.config = set_up()
# This gets the JWKS from a given URL and does processing so you can
# use any of the keys available
jwks_url = f'https://{self.config["DOMAIN"]}/.well-known/jwks.json'
self.jwks_client = jwt.PyJWKClient(jwks_url)
def verify(self):
# This gets the 'kid' from the passed token
try:
self.signing_key = self.jwks_client.get_signing_key_from_jwt(
self.token
).key
except jwt.exceptions.PyJWKClientError as error:
return {"status": "error", "msg": error.__str__()}
except jwt.exceptions.DecodeError as error:
return {"status": "error", "msg": error.__str__()}
try:
payload = jwt.decode(
self.token,
self.signing_key,
algorithms=self.config["ALGORITHMS"],
audience=self.config["API_AUDIENCE"],
issuer=self.config["ISSUER"],
)
except Exception as e:
return {"status": "error", "message": str(e)}
return payload
Analicemos esta clase para comprender los pasos aquí:
__init__()
token
parámetro que VerifyToken
necesita la clase;set_up()
JWKS
archivo usando el PyJWKClient
del PyJWT
paquete. Un conjunto de claves web JSON, o JWKS para abreviar, contiene la información necesaria para validar una firma de token y asegurarse de que sea un token válido. Debido a que Auth0 implementa OAuth 2.0, tiene un punto final "conocido" al que puede llamar y obtener los metadatos adicionales utilizados para validar el token y sus propiedades.verify()
kid
reclamo presente en el encabezado del token) para tomar la clave utilizada del JWKS para verificar la firma del token. Si este paso falla por alguno de los posibles errores, se devuelve el mensaje de error;Veamos cómo usar este fragmento de código en nuestro punto final privado en la sección siguiente.
La pieza final del rompecabezas es importar la clase que acaba de crear en el archivo y usarla en el punto final. Esto es lo que necesita cambiar:utils.pyGET /api/private
VerifyToken
, luego diríjase a su punto final; también necesitará importar la Response
clase y el status
objeto desde fastapi
para que pueda dar una respuesta detallada en caso de error;VerifyToken
clase y verificando si el resultado del método es un error.verify()
Así es como debería verse su archivo con todos los cambios anteriores:main.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI, Response, status # 👈 new imports
from fastapi.security import HTTPBearer
from .utils import VerifyToken # 👈 new import
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer()
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
@app.get("/api/private")
def private(response: Response, token: str = Depends(token_auth_scheme)): # 👈 updated code
"""A valid access token is required to access this route"""
result = VerifyToken(token.credentials).verify() # 👈 updated code
# 👇 new code
if result.get("status"):
response.status_code = status.HTTP_400_BAD_REQUEST
return result
# 👆 new code
return result
Con esta actualización, está configurando correctamente su punto final protegido y realizando todos los pasos de verificación para los tokens de acceso que necesita. 🎉
Aunque inició su servidor con la --reload
bandera porque necesita asegurarse de que la configuración esté cargada, es un buen momento para terminar el uvicorn
proceso y luego reiniciar el servidor. Eso garantizará la correcta funcionalidad de su API con los parámetros de configuración del .config
archivo o variables de entorno.
Antes de poder realizar solicitudes al punto final protegido en el FastAPI
servidor, necesita el token de acceso de Auth0. Puede obtenerlo copiándolo desde el panel de Auth0 en la Test
pestaña de su API.
También puede usar una POST
solicitud curl al punto final de Auth0 para obtener el token de acceso, y puede copiar esta solicitud desde la pestaña de su API en el panel de Auth0. La solicitud de curl se verá así; recuerde completar los valores según sea necesario:oauth/tokenTest
curl -X 'POST' \
--url 'https://<YOUR DOMAIN HERE>/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data 'client_id=<YOUR CLIENT ID HERE>' \
--data client_secret=<YOUR CLIENT SECRET HERE> \
--data audience=<YOUR AUDIENCE HERE>
En la línea de comando, debería ver una respuesta que contiene su token de portador, como esta:
{
"access_token": "<YOUR_BEARER_TOKEN>",
"expires_in": 86400,
"token_type": "Bearer"
}
Ahora puede usar este token de acceso para acceder al punto final privado:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer <YOUR_BEARER_TOKEN>'
Si la solicitud tiene éxito, el servidor devolverá la carga útil del token de acceso:
{
"iss": "https://<YOUR_DOMAIN>/",
"sub": "iojadoijawdioWDasdijasoid@clients",
"aud": "http://<YOUR_AUDIENCE>",
"iat": 1630341660,
"exp": 1630428060,
"azp": "ADKASDawdopjaodjwopdAWDdsd",
"gty": "client-credentials"
}
Tenga en cuenta que si la validación falla, debería ver los detalles de lo que salió mal.
Y eso es todo: ha terminado de proteger el punto final privado y de probar su protección.
Aprendiste bastantes cosas en esta publicación de blog. Para empezar, aprendió los conceptos básicos de la FastAPI
implementación de dos puntos finales: uno público y otro privado. Viste lo simple que es realizar solicitudes a estos dos puntos finales. Creó una clase de verificación y vio cómo PyJWT lo ayuda a validar un token de acceso Auth0, y aprendió qué es JWKS.
Pasó por el proceso de creación de su API en el panel de Auth0. También aprendió cómo proteger uno de sus puntos finales aprovechando el sistema de inyección de dependencia que proporciona FastAPI para ayudarlo a implementar integraciones. E hiciste todo esto muy rápido.
En resumen, ha aprendido lo fácil que es ponerse en marcha y FastAPI
cómo utilizar Auth0 para proteger sus puntos finales.
En este repositorio de GitHub , encontrará el código completo de la aplicación de muestra que creó hoy. Si tiene alguna pregunta, hágala en el hilo del foro de la comunidad para esta publicación de blog.
Enlace: https://auth0.com
#pythom #fastapi #auth0
1633744445
Tìm hiểu kiến thức cơ bản về FastAPI, cách nhanh chóng thiết lập máy chủ và bảo mật điểm cuối với Auth0.
FastAPI là một khung Python tương đối mới cho phép bạn tạo các ứng dụng rất nhanh chóng. Khuôn khổ này cho phép bạn đọc dữ liệu yêu cầu API một cách liền mạch với các mô-đun tích hợp sẵn và là một giải pháp thay thế nhẹ cho Flask.
Trong bài viết này, chúng ta sẽ xem xét các tính năng của FastAPI
, thiết lập một API cơ bản, bảo vệ một điểm cuối bằng Auth0 và bạn sẽ biết cách bắt đầu đơn giản như thế nào.
Trước khi bắt đầu xây dựng với FastAPI , bạn cần có Python và tài khoản Auth0 miễn phí; bạn có thể đăng ký tại đây .3.8.2
Nếu bạn đã cài đặt phiên bản Python đó và tài khoản Auth0 của mình, bạn có thể tạo một FastAPI
ứng dụng mới . Để bắt đầu, hãy tạo một thư mục mới để phát triển bên trong. Đối với ví dụ này, bạn sẽ tạo một thư mục được gọi và một thư mục con được gọi là ; thư mục con này là nơi mã của bạn sẽ tồn tại.fastapi-exampleapplication
Trong thư mục, tạo một môi trường ảo bằng lệnh sau:fastapi-example
python3 -m venv .env
Điều này tạo ra một môi trường ảo và nó phân tách các phần phụ thuộc khỏi phần còn lại của các thư viện máy tính của bạn. Nói cách khác, bạn không làm ô nhiễm không gian tên chung với các thư viện và phần phụ thuộc, điều này có thể ảnh hưởng đến các dự án Python khác.
Sau khi tạo môi trường ảo, bạn cần kích hoạt nó. Đối với hệ điều hành dựa trên Unix, đây là lệnh:
source .env/bin/activate
Nếu bạn đang sử dụng hệ điều hành khác, bạn có thể tìm thấy danh sách cách bạn có thể kích hoạt một môi trường trên trang tài liệu này . Sau khi kích hoạt môi trường ảo của mình, bạn có thể cài đặt các gói bạn sẽ sử dụng : FastAPI
, uvicorn server, pyjwt và cập nhật pip
:
pip install -U pip
pip install fastapi uvicorn 'pyjwt[crypto]'
Bây giờ tất cả các thư viện đã được cài đặt, bạn có thể tạo một tệp bên trong thư mục; đó là nơi mã API của bạn sẽ tồn tại. Nội dung của di chúc như sau:main.pyapplicationmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import FastAPI
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
Hãy chia nhỏ điều này: - Để bắt đầu, bạn đang nhập FastAPI
thư viện; - Sau đó, tạo ứng dụng của bạn bằng cách khởi tạo một đối tượng; - Sau đó, bạn sử dụng để xác định một tuyến xử lý các yêu cầu; - Cuối cùng, bạn có chức năng hoạt động đường dẫn được gọi , đây là một chức năng sẽ chạy mỗi khi tuyến đường đó được gọi và nó trả về một từ điển với thông báo chào mừng.FastAPI()@app.getGETpublic()
Bây giờ bạn đã có mã điểm cuối đầu tiên của mình, để khởi động và chạy máy chủ, hãy chạy lệnh sau trên thư mục gốc của dự án:
uvicorn application.main:app --reload
Khi máy chủ của bạn đang chạy, bạn có thể truy cập http://127.0.0.1:8000/docs để xem tài liệu được tạo tự động cho điểm cuối đầu tiên như được hiển thị trong hình ảnh bên dưới:
Hoặc bạn có thể thực hiện yêu cầu đầu tiên của mình trong một cửa sổ đầu cuối mới bằng cách sử dụng cURL
. Hãy nhớ rằng nếu bạn là người dùng Windows trên phiên bản hệ điều hành cũ hơn, bạn sẽ phải cài đặt curl trước khi chạy lệnh sau:
curl -X 'GET' \
--url http://127.0.0.1:8000/api/public
Và bạn sẽ thấy một JSON là kết quả của yêu cầu bạn vừa thực hiện tương tự như sau:
{
"status": "success",
"msg": "Hello from a public endpoint! You don't need to be authenticated to see this."
}
Vì mục đích đơn giản, bạn sẽ sử dụng cURL
phần còn lại của bài đăng này.
Bây giờ một máy chủ API cơ sở đã được thiết lập, bạn sẽ thêm một điểm cuối nữa vào tệp của mình . Trong ứng dụng này, bạn sẽ có sẵn một tuyến đường cho mọi người và một tuyến đường mà chỉ bạn mới có thể truy cập bằng mã thông báo truy cập mà bạn sẽ nhận được từ Auth0.main.pyGET /api/publicGET /api/private
Bây giờ bạn cần cập nhật tệp. Đây là những gì bạn cần thay đổi đối với phần nhập:main.py
Depends
từ fastapi
mô-đun, đó là hệ thống tiêm phụ thuộc FastAPI;HTTPBearer
lớp từ mô-đun, một sơ đồ bảo mật được tích hợp sẵn cho các tiêu đề ủy quyền có mã thông báo mang;fastapi.security
HTTPBearer
. Điều này sẽ được sử dụng để đảm bảo sự hiện diện của tiêu đề ủy quyền với Bearer
mã thông báo trong mỗi yêu cầu được thực hiện tới điểm cuối riêng tư.Mã thông báo cho API biết rằng người mang mã thông báo đã được ủy quyền để truy cập API và thực hiện các hành động cụ thể được chỉ định theo phạm vi đã được cấp trong quá trình ủy quyền.
Ngoài việc cập nhật các lần nhập, bạn cần triển khai điểm cuối riêng. Điểm cuối cũng sẽ chấp nhận các yêu cầu và đây là mã trông như thế nào bây giờ:/api/privateGETmain.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI # 👈 new imports
from fastapi.security import HTTPBearer # 👈 new imports
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer() # 👈 new code
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
# new code 👇
@app.get("/api/private")
def private(token: str = Depends(token_auth_scheme)):
"""A valid access token is required to access this route"""
result = token.credentials
return result
Các Depends
lớp có trách nhiệm đánh giá từng yêu cầu rằng một thiết bị đầu cuối được nhận chống lại một chức năng, lớp, hoặc ví dụ. Trong trường hợp này, nó sẽ đánh giá các yêu cầu so với HTTPBearer
lược đồ sẽ kiểm tra yêu cầu đối với tiêu đề ủy quyền với mã thông báo mang.
Bạn có thể tìm thêm chi tiết về cách
FastAPI
hoạt động của việc tiêm phụ thuộc trên tài liệu của nó .
Bây giờ điểm cuối riêng tư của bạn trả về mã thông báo đã nhận. Nếu không có mã thông báo nào được cung cấp, nó sẽ trả về 403 Forbidden
mã trạng thái với thông tin chi tiết cho biết bạn là ai "Not authenticated"
. Bởi vì bạn đã sử dụng --reload
cờ trong khi chạy máy chủ của mình, bạn không cần phải chạy lại lệnh; uvicorn
sẽ tiếp nhận các thay đổi và cập nhật máy chủ mỗi khi bạn lưu tệp của mình. Bây giờ hãy thực hiện một yêu cầu tới điểm cuối để kiểm tra hành vi của nó. Trước tiên, hãy thực hiện yêu cầu mà không cần chuyển tiêu đề ủy quyền:GET /api/private
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private'
# {"detail": "Not authenticated"}
Và bây giờ, nếu bạn thực hiện một yêu cầu với tiêu đề ủy quyền, nhưng với một chuỗi ngẫu nhiên làm giá trị mã thông báo, bạn sẽ thấy cùng một giá trị ngẫu nhiên như một kết quả:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer FastAPI is awesome'
# "FastAPI is awesome"
Như bạn có thể thấy, điểm cuối của bạn không được bảo vệ vì nó chấp nhận bất kỳ chuỗi nào làm giá trị cho tiêu đề ủy quyền. Nó là không đủ để nhận được một tiêu đề ủy quyền; bạn cũng phải xác minh giá trị của mã thông báo mang tên để cho phép ai đó truy cập vào điểm cuối. Hãy sửa hành vi đó.
Trước khi đến thời điểm bạn đã sẵn sàng xác thực mã thông báo trong các điểm cuối của mình, bạn cần thiết lập một API trong Auth0 . Khi API này được thiết lập, bạn có quyền truy cập vào một vài thông tin mà Auth0 yêu cầu - đối tượng, ID khách hàng và bí mật của ứng dụng khách.
Bạn cũng cần có quyền truy cập vào thông tin đó từ bên trong máy chủ; đó là nơi một tệp cấu hình phát huy tác dụng. Bạn sẽ cần tạo một tệp cấu hình được gọi .config
ở gốc của dự án. Đây là những gì .config
tệp sẽ giống như bên dưới. Hãy nhớ cập nhật các giá trị cho phù hợp:
# .config
[AUTH0]
DOMAIN = your.domain.auth0.com
API_AUDIENCE = your.api.audience
ALGORITHMS = RS256
ISSUER = https://your.domain.auth0.com/
Cấu hình này là phần đầu tiên của câu đố kiểm tra cài đặt cấu hình Auth0 trong giai đoạn xác thực mã thông báo. Một quy tắc tốt khác cần tuân theo là không bao giờ gán các tệp cấu hình của bạn với các biến môi trường thành mã nguồn. Để ngăn điều này xảy ra, bạn nên tạo một .gitignore
tệp trong thư mục gốc của dự án và thêm .config
tệp dưới dạng mục nhập:
# .gitignore
.config
FastAPI
Máy chủ của bạn hiện có một tuyến, nhưng nó chưa được bảo vệ. Nó chỉ kiểm tra xem bạn có tiêu đề ủy quyền trong yêu cầu hay không, có nghĩa là bạn đang thiếu một bước trong quy trình: bạn cần xác thực mã thông báo truy cập. Để làm điều đó, bạn cần tạo một đối tượng thực hiện tất cả các bước để xác thực JWT vì mã thông báo truy cập của Auth0 là JWT.GET /api/private
Để tách các trách nhiệm khỏi định nghĩa định tuyến, bạn nên tạo một tệp mới được gọi là bên trong thư mục để chứa tất cả mã tiện ích, như xác thực mã thông báo truy cập và đọc thông tin cấu hình.utils.pyapplication
Bắt đầu bằng cách nhập os
thư viện Python , cũng như các thư viện PyJWT
và configparser
. Thư viện hệ điều hành cung cấp cho bạn quyền truy cập vào các biến môi trường. Thư viện JWT cung cấp cho bạn các hàm để kiểm tra và xác thực JWT. Các ConfigParser
lớp từ thư viện trùng tên cung cấp một cách cho Python đọc cài đặt cấu hình tìm thấy trong các .config
tập tin mà bạn đã tạo trước đó. Và điều đầu tiên bạn có sau khi nhập là một hàm được gọi , bạn có thể thấy bên dưới:set_up()
"""utils.py
"""
import os
import jwt
from configparser import ConfigParser
def set_up():
"""Sets up configuration for the app"""
env = os.getenv("ENV", ".config")
if env == ".config":
config = ConfigParser()
config.read(".config")
config = config["AUTH0"]
else:
config = {
"DOMAIN": os.getenv("DOMAIN", "your.domain.com"),
"API_AUDIENCE": os.getenv("API_AUDIENCE", "your.audience.com"),
"ISSUER": os.getenv("ISSUER", "https://your.domain.com/"),
"ALGORITHMS": os.getenv("ALGORITHMS", "RS256"),
}
return config
Các chức năng có trách nhiệm đọc tập tin và tạo ra một đối tượng cấu hình mà hoạt động giống như một cuốn từ điển. Bởi vì mã mẫu này cũng được chuẩn bị để chạy trên các biến môi trường, theo mặc định , hàm sẽ cố gắng đọc tệp. Bạn có thể thay đổi hành vi này bằng cách đặt biến môi trường thành bất kỳ giá trị nào khác, trong trường hợp đó, một từ điển sẽ được tạo bằng cách đọc tất cả các biến môi trường mà bạn có thể thấy trong mệnh đề trên.set_up().configset_up().configENVelse
Phần tiếp theo của câu đố là nơi điều kỳ diệu xảy ra. Bạn sẽ tạo một VerifyToken
lớp để xử lý xác thực mã thông báo JWT:
# paste the code 👇 after the set_up() function in the utils.py file
class VerifyToken():
"""Does all the token verification using PyJWT"""
def __init__(self, token):
self.token = token
self.config = set_up()
# This gets the JWKS from a given URL and does processing so you can
# use any of the keys available
jwks_url = f'https://{self.config["DOMAIN"]}/.well-known/jwks.json'
self.jwks_client = jwt.PyJWKClient(jwks_url)
def verify(self):
# This gets the 'kid' from the passed token
try:
self.signing_key = self.jwks_client.get_signing_key_from_jwt(
self.token
).key
except jwt.exceptions.PyJWKClientError as error:
return {"status": "error", "msg": error.__str__()}
except jwt.exceptions.DecodeError as error:
return {"status": "error", "msg": error.__str__()}
try:
payload = jwt.decode(
self.token,
self.signing_key,
algorithms=self.config["ALGORITHMS"],
audience=self.config["API_AUDIENCE"],
issuer=self.config["ISSUER"],
)
except Exception as e:
return {"status": "error", "message": str(e)}
return payload
Hãy chia nhỏ lớp này để hiểu các bước ở đây:
__init__()
token
tham số mà VerifyToken
lớp cần;set_up()
JWKS
tập tin bằng cách sử dụng PyJWKClient
từ PyJWT
gói. Bộ khóa web JSON, viết tắt là JWKS chứa thông tin cần thiết để xác thực chữ ký mã thông báo và đảm bảo rằng đó là mã thông báo hợp lệ. Vì Auth0 triển khai OAuth 2.0 nên nó có một điểm cuối "nổi tiếng" mà bạn có thể gọi và lấy siêu dữ liệu bổ sung được sử dụng để xác thực mã thông báo và các thuộc tính của nó.verify()
kid
xác nhận quyền sở hữu có trong tiêu đề mã thông báo) để lấy khóa được sử dụng từ JWKS để xác minh chữ ký mã thông báo. Nếu bước này không thành công bởi bất kỳ lỗi nào có thể xảy ra, thông báo lỗi sẽ được trả về;Hãy xem cách sử dụng đoạn mã này trong điểm cuối riêng tư của chúng tôi trong phần phía trước.
Mảnh ghép cuối cùng là nhập lớp bạn vừa tạo vào tệp và sử dụng nó trong điểm cuối. Đây là những gì bạn cần thay đổi:utils.pyGET /api/private
VerifyToken
, sau đó đi đến điểm cuối của bạn; bạn cũng sẽ cần nhập Response
lớp và status
đối tượng từ fastapi
đó để bạn có thể đưa ra phản hồi chi tiết trong trường hợp có lỗi;VerifyToken
lớp và kiểm tra xem kết quả của phương thức có phải là lỗi hay không.verify()
Đây là tệp của bạn sẽ trông như thế nào với tất cả các thay đổi ở trên:main.py
"""main.py
Python FastAPI Auth0 integration example
"""
from fastapi import Depends, FastAPI, Response, status # 👈 new imports
from fastapi.security import HTTPBearer
from .utils import VerifyToken # 👈 new import
# Scheme for the Authorization header
token_auth_scheme = HTTPBearer()
# Creates app instance
app = FastAPI()
@app.get("/api/public")
def public():
"""No access token required to access this route"""
result = {
"status": "success",
"msg": ("Hello from a public endpoint! You don't need to be "
"authenticated to see this.")
}
return result
@app.get("/api/private")
def private(response: Response, token: str = Depends(token_auth_scheme)): # 👈 updated code
"""A valid access token is required to access this route"""
result = VerifyToken(token.credentials).verify() # 👈 updated code
# 👇 new code
if result.get("status"):
response.status_code = status.HTTP_400_BAD_REQUEST
return result
# 👆 new code
return result
Với bản cập nhật này, bạn đang thiết lập đúng điểm cuối được bảo vệ của mình và thực hiện tất cả các bước xác minh cho mã thông báo truy cập mà bạn cần. 🎉
Mặc dù bạn đã khởi động máy chủ của mình bằng --reload
cờ vì bạn cần đảm bảo cấu hình được tải, nhưng đây là thời điểm tốt để kết thúc uvicorn
quá trình và sau đó khởi động lại máy chủ. Điều đó sẽ đảm bảo chức năng thích hợp của API của bạn với các tham số cấu hình từ .config
tệp hoặc biến môi trường.
Trước khi bạn có thể thực hiện các yêu cầu đến điểm cuối được bảo vệ trong FastAPI
máy chủ, bạn cần mã thông báo truy cập từ Auth0. Bạn có thể lấy nó bằng cách sao chép nó từ bảng điều khiển Auth0 trong Test
tab API của bạn.
Bạn cũng có thể sử dụng POST
yêu cầu curl tới điểm cuối của Auth0 để lấy mã thông báo truy cập và bạn có thể sao chép yêu cầu này từ tab API của mình trong bảng điều khiển Auth0. Yêu cầu cuộn tròn sẽ như thế này; nhớ điền các giá trị nếu cần:oauth/tokenTest
curl -X 'POST' \
--url 'https://<YOUR DOMAIN HERE>/oauth/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data 'client_id=<YOUR CLIENT ID HERE>' \
--data client_secret=<YOUR CLIENT SECRET HERE> \
--data audience=<YOUR AUDIENCE HERE>
Trong dòng lệnh, bạn sẽ thấy một phản hồi có chứa mã thông báo mang của bạn, như sau:
{
"access_token": "<YOUR_BEARER_TOKEN>",
"expires_in": 86400,
"token_type": "Bearer"
}
Bây giờ bạn có thể sử dụng mã thông báo truy cập này để truy cập điểm cuối riêng tư:
curl -X 'GET' \
--url 'http://127.0.0.1:8000/api/private' \
--header 'Authorization: Bearer <YOUR_BEARER_TOKEN>'
Nếu yêu cầu thành công, máy chủ sẽ gửi lại trọng tải của mã thông báo truy cập:
{
"iss": "https://<YOUR_DOMAIN>/",
"sub": "iojadoijawdioWDasdijasoid@clients",
"aud": "http://<YOUR_AUDIENCE>",
"iat": 1630341660,
"exp": 1630428060,
"azp": "ADKASDawdopjaodjwopdAWDdsd",
"gty": "client-credentials"
}
Hãy nhớ rằng nếu xác thực không thành công, bạn sẽ xem chi tiết về những gì đã xảy ra.
Vậy là xong - bạn đã hoàn thành việc bảo vệ điểm cuối riêng tư và kiểm tra khả năng bảo vệ của nó.
Bạn đã học được khá nhiều điều trong bài đăng trên blog này. Để bắt đầu, bạn đã học những kiến thức cơ bản về FastAPI
việc triển khai hai điểm cuối - một công khai, một riêng tư. Bạn đã thấy việc thực hiện yêu cầu đến cả hai điểm cuối này đơn giản như thế nào. Bạn đã tạo một lớp xác minh và xem cách PyJWT giúp bạn xác thực mã thông báo truy cập Auth0 và bạn đã biết JWKS là gì.
Bạn đã trải qua quá trình tạo API của mình trong bảng điều khiển Auth0. Bạn cũng đã học cách bảo mật một trong những điểm cuối của mình bằng cách tận dụng hệ thống tiêm phụ thuộc mà FastAPI cung cấp để giúp bạn triển khai tích hợp. Và bạn đã làm tất cả những điều này rất nhanh chóng.
Tóm lại, bạn đã học được cách dễ dàng thiết lập và chạy FastAPI
, cũng như cách sử dụng Auth0 để bảo vệ các điểm cuối của bạn.
Trong repo GitHub này , bạn sẽ tìm thấy mã đầy đủ cho ứng dụng mẫu mà bạn đã tạo hôm nay. Nếu bạn có bất kỳ câu hỏi nào, hãy hỏi họ trong chuỗi diễn đàn cộng đồng cho bài đăng trên blog này.
Nguồn: https://auth0.com
#fastapi #python #auth0