간단한 FastAPI 및 Auth0 인증

11240 단어 apiauth0python
이 작업을 수행하는 방법에 대한 예를 살펴보고 있었는데 생각했던 간단한 응용 프로그램에 비해 모든 것이 너무 복잡하거나 길었습니다. 이것은 필요한 것을 빌드할 수 있는 베어본 예제입니다.

Auth0 부분부터 시작하겠습니다. 계정에 로그인하고 애플리케이션 > API로 이동한 다음 API 생성을 클릭합니다. 이름과 식별자를 입력하세요. 제안된 대로 식별자는 프로젝트의 URL이 될 수 있지만 실제로는 사용되지 않습니다.



다음으로 생성된 API 및 애플리케이션의 세부 정보를 가져옵니다. 애플리케이션으로 이동하여 생성한 애플리케이션 옆에 있는 메뉴를 열고 "설정"을 엽니다. 도메인, 클라이언트 ID 및 클라이언트 암호를 모두 복사해야 합니다.



다음 코드. 나는 프로젝트 설정을 거치지 않을 것입니다. 자세한 내용을 원하면 the example repo을 확인하십시오. 보안을 유지하려면 엔드포인트가 필요합니다. 다음을 수행합니다.


@app.get("/")
def get():
    return {"message": "This is private"}



요청 헤더에 도착하는 유효한 jwt 토큰을 요구하여 끝점을 보호합니다.

{"authorization": "Bearer <token>"


인증을 추가하려면 두 부분이 필요합니다. 즉, 토큰의 유효성을 검사하는 부분과 FastAPI의 종속성을 사용하여 인증 코드를 프라이빗 엔드포인트에 주입하는 방법입니다. 우선 검증:

import jwt

def verify_token(token: str, domain: str, audience: str) -> dict[str, Any]:
    """
    Use the pyjwt jwkclient to get a signing key, then decode the supplied token
    """
    jwks_client = jwt.PyJWKClient(f"https://{domain}/.well-known/jwks.json")
    signing_key = jwks_client.get_signing_key_from_jwt(token).key
    return jwt.decode(
        token,
        signing_key,
        algorithms=["RS256"],
        audience=audience,
        issuer=f"https://{domain}/",
    )

verify_token 함수는 도메인 및 대상 값과 함께 토큰을 가져와 토큰을 디코딩합니다. 타사 인증 공급자를 사용하고 있으므로 두 단계가 필요합니다.
  • PyJWKClient를 사용하여 서명 키 가져오기
  • 해당 서명 키를 사용하여 토큰을 디코딩합니다
  • .

    끝점에 주입하기 위해 다음을 사용할 수 있습니다.

    from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
    from fastapi import Depends, HTTPException
    
    security = HTTPBearer()
    
    async def has_access(credentials: HTTPAuthorizationCredentials = Depends(security)):
        """
        Function that is used to validate the token in the case that it requires it
        """
        try:
            verify_token(credentials.credentials, AUTH0_DOMAIN, AUTH0_AUDIENCE)
        except jwt.PyJWTError as e:
            raise HTTPException(status_code=401, detail=str(e))
    

    Depends(security)는 인증 헤더가 있는지 확인하고(누락된 경우 Unauthorized 오류가 발생함) 토큰에 대한 액세스 권한을 credentials.credentials로 부여합니다. 모든 인증 오류는 PyJWTError 오류이므로 이를 포착하고 토큰이 실패하면 API 사용자에게 메시지를 반환할 수 있습니다.

    이제 이를 엔드포인트에 추가하여 보호합니다.

    from fastapi import FastAPI, Depends
    
    import auth
    
    app = FastAPI()
    
    
    @app.get("/", dependencies=[Depends(auth.has_access)])
    def get():
        return {"message": "This is private"}
    


    끝점을 테스트하는 것은 어떻습니까? requests 라이브러리를 사용하여 토큰을 얻고 인증 헤더에 추가할 수 있습니다.

    import requests
    
    payload = {
        "client_id": "<CLIENT_ID>",
        "client_secret": "<CLIENT_SECRET>",
        "audience": "<AUDIENCE>",
        "grant_type": "client_credentials",
    }
    r = requests.post("https://<your-domain>.auth0.com/oauth/token", json=payload)
    # Returns {'access_token': '<very-long-token>', 'expires_in': 86400, 'token_type': 'Bearer'}
    
    auth_header = {"authorization": f"Bearer {r['access_token']}"}
    r = requests.get("http://127.0.0.1:8000/", headers=auth_header)
    print(r.json())
    


    이것은 의도적으로 최소한의 구현입니다. 기능을 추가하고 싶을 것입니다. 보다 표현적인 오류 처리가 한 가지 일 수 있습니다.

    기계 대 기계 인증을 구현하는 경우 만료될 때까지 토큰을 재사용하는 논리를 포함하고 싶을 것입니다. Auth0 속도는 요청된 토큰을 기반으로 합니다.

    다른 권한 수준을 사용하는 경우 범위 유효성 검사를 추가할 수 있습니다. 올바른 방향으로 이동하려면 여기를 살펴보십시오. https://auth0.com/docs/quickstart/backend/python/01-authorization#validate-scopes

    전체 예를 보려면 저장소를 살펴보십시오. https://github.com/kipparker/fastapi-auth0

    참조:
  • Auth0 문서: Python API: 권한 부여https://auth0.com/docs/quickstart/backend/python/01-authorization
  • JWT 토큰 기반 인증으로 FastAPI 보호https://testdriven.io/blog/fastapi-jwt-auth/
  • 좋은 웹페이지 즐겨찾기