Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API supabase #593

Merged
merged 25 commits into from
Feb 18, 2025
Merged

API supabase #593

merged 25 commits into from
Feb 18, 2025

Conversation

dejima-shikou
Copy link
Collaborator

@dejima-shikou dejima-shikou commented Feb 7, 2025

PR の目的

  • APIの認証機能を、firebaseとsupabaseで切り替え可能とする
    • 環境変数AUTH_SERVICEにFIREBASEまたはSUPABASEを指定することで切り替わる
      • AUTH_SERVICEは、.envでなく、cocker-composeファイルに定義する
    • firebaseとsupabaseの共通ベースクラスAuthModuleにインタフェースを定義することで、差異隠蔽する
  • docker-compose-test-supabase.ymlにより、APIの自動テストをsupabaseから実行可能にする
    • テスト開始時にテスト用ユーザーを登録する仕組みを別タスクで実施するため、本PRではユーザーを手動で登録して動作確認した
    • CIは未対応のため、Firebaseで動く
  • gitがsupabaseのDBデータの変更に反応していたため、無視させる
  • scriptsについて、vulnrichment2tc.pyで動作確認したところ、Firebaseは正常に動作した。Supabaseはエラーとなるが、優先度が低いため本PRでは対処しない

経緯・意図・意思決定

  • HTTPAuthorizationCredentials.credentialsを取得する際、
    token: HTTPAuthorizationCredentials = Depends(HTTPBearer))
    のようにして取得するが、このDependsはルーター関数のDepends、またはそのDependsから呼び出されるDepends、でないとエラーとなる

参考文献

公式 Python Client Library
https://supabase.com/docs/reference/python/introduction

Copy link
Collaborator

@mshim03 mshim03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

大筋は問題ないと思います。細かい点だけコメントしました

Comment on lines 7 to 8
def get_credentials(token: HTTPAuthorizationCredentials = Depends(token_scheme)):
return token.credentials
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

利用していないので、この処理は不要かも?



def get_current_user(
token: HTTPAuthorizationCredentials = Depends(token_scheme),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTPBearer 以外のtoken scheme を使う予定もなさそうなので、DependsでなくてHTTP Bearer決め内でもいいかもしれません

api/app/main.py Outdated

# Dependency injection as needed
app.dependency_overrides[get_firebase_credentials] = lambda: cred
app.dependency_overrides[get_auth_module] = override_get_auth_module
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

以下でもいいかもしれません (わかりにくければ元の方でもいいかなと)

Suggested change
app.dependency_overrides[get_auth_module] = override_get_auth_module
app.dependency_overrides[get_auth_module] = lambda: auth_module

@dejima-shikou
Copy link
Collaborator Author

@mshim03
指摘の通り修正しました。

@dejima-shikou dejima-shikou changed the title change firebase authentication to class API supabase Feb 17, 2025
@dejima-shikou dejima-shikou marked this pull request as ready for review February 18, 2025 06:00
Copy link
Collaborator

@mshim03 mshim03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTPExceptionを返す場所を制限したいので、authmoduleの中で実行するのは避けて欲しいです

Comment on lines +21 to +30
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="No such user",
)
if user.disabled:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Inactive user",
)
Copy link
Collaborator

@mshim03 mshim03 Feb 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

router以外で、HTTPExceptionはできれば避けたいが、現状HTTPBearerからトークンを取得して認証するので、HTTP専用の関数となっている。一旦このままでも問題なさそう


# Dependency injection as needed
app.dependency_overrides[get_firebase_credentials] = lambda: cred
app.dependency_overrides[get_auth_module] = lambda: auth_module
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

firebaseのdependency injectionの仕組みを利用

Comment on lines 43 to 57
except requests.exceptions.Timeout as firebase_timeout:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
) from firebase_timeout

data = resp.json()
if not resp.ok:
error_message = data["error"]["message"]
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=error_message if error_message else "Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここではHTTPExceptionでなく、Exceptionを発出し、router関数の中 (/token) でHTTPExceptionを返すようにして欲しいです (どこでHTTPExceptionを発行しているのかがわからなくなる)

Comment on lines 85 to 98
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Could not refresh token",
headers={"WWW-Authenticate": "Bearer"},
) from firebase_timeout

data: dict = resp.json()
if not resp.ok:
error_message: str = data["error"]["message"]
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=error_message if error_message else "Could not refresh token",
headers={"WWW-Authenticate": "Bearer"},
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらも同様に、HTTPException をここで発出するのを避けて欲しいです

Comment on lines 110 to 135
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token has expired",
) from error
except auth.RevokedIdTokenError as error:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token has revoked",
) from error
except auth.CertificateFetchError as error:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
detail="Failed to obtain required credentials",
) from error
except auth.UserDisabledError as error:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Disabled user",
) from error
except (auth.InvalidIdTokenError, ValueError) as error:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
) from error

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTPExceptionについて同様

@dejima-shikou
Copy link
Collaborator Author

@mshim03
auth層ではAuthExceptionを投げ、routers層でHTTPExceptionに変換する方式としました

Copy link
Collaborator

@mshim03 mshim03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typoの修正とディレクトリの変更お願いいたします

Comment on lines 1 to 21
from fastapi import HTTPException, status

from app.auth.auth_exception import AuthErrorType, AuthException


def get_status_code(error_type: AuthErrorType):
match error_type:
case AuthErrorType.UNAUTHORIZED:
return status.HTTP_401_UNAUTHORIZED
case AuthErrorType.INTERNAL_SERVER_ERROR:
return status.HTTP_500_INTERNAL_SERVER_ERROR
case AuthErrorType.SERVICE_UNAVAILABLE:
return status.HTTP_503_SERVICE_UNAVAILABLE


def create_http_excption(auth_exception: AuthException) -> HTTPException:
return HTTPException(
status_code=get_status_code(auth_exception.error_type),
detail=auth_exception.message,
headers={"WWW-Authenticate": "Bearer"},
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ルーティングよう関数と同じディレクトリになっているので、 validators 同様に utils/ など別フォルダに入れていただけると助かります

return status.HTTP_503_SERVICE_UNAVAILABLE


def create_http_excption(auth_exception: AuthException) -> HTTPException:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create_http_exception のtypoのようです

@dejima-shikou
Copy link
Collaborator Author

@mshim03
指摘の2件を修正しました。

Copy link
Collaborator

@mshim03 mshim03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mshim03 mshim03 merged commit 3e80e6b into main Feb 18, 2025
7 checks passed
@mshim03 mshim03 deleted the topic/api-supabase branch February 18, 2025 09:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants