tokusumi / fastapi-cloudauth

Simple integration between FastAPI and cloud authentication services (AWS Cognito, Auth0, Firebase Authentication).
MIT License
323 stars 35 forks source link

Add ability to specify `user_info` as an extra parameter when instantiating `UserInfoAuth` derived classes #66

Closed tivaliy closed 2 years ago

tivaliy commented 2 years ago

Hi, thank you for you great work. I have a question/feature request.

Currently, there is no straightforward way to pass user_info into a respective UserInfoAuth derived class (eg. CognitoCurrentUser) before the instantinaion and only inheritance will work. So it'll be great to have something like this:

current_user_auth = CognitoCurrentUser(
        region=settings.aws_region,
        userPoolId=settings.userpool_id,
        client_id=settings.app_client_id,
        user_info=settings.user_info_class      <---- here
    )

The current implementation of CognitoCurrentUser doesn't allow to do this.

It will be nice to have something like this:

class CognitoCurrentUser(UserInfoAuth):
    """
    Verify ID token and get user info of AWS Cognito
    """

    user_info = CognitoClaims

    def __init__(
        self,
        region: str,
        userPoolId: str,
        client_id: str,
        *args: Any,
        **kwargs: Any,
    ):
        url = f"https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json"
        jwks = JWKS(url=url)
        user_info = kwargs.get("user_info") or self.user_info           <----- new code
        super().__init__(
            jwks,
            user_info=user_info,   <---- changes
            audience=client_id,
            issuer=f"https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
            extra=CognitoExtraVerifier(
                client_id=client_id,
                issuer=f"https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
                token_use={"id"},
            ),
            *args,
            **kwargs,
        )

or be more explicit and add user_info as a paramter to CognitoCurrentUser __init__ method

tivaliy commented 2 years ago

Let's close this "issue". Currently, I followed up with the following implementation (using dependecy):

async def get_current_user(
    settings: AppSettings = Depends(get_app_settings),
    http_auth: Optional[HTTPAuthorizationCredentials] = Depends(HTTPBearer(auto_error=False)),
) -> CognitoCurrentUser:
    current_user_auth = CognitoCurrentUser(
        region=settings.aws_region,
        userPoolId=settings.userpool_id,
        client_id=settings.app_client_id,
    )
    # Set custom Cognito claims class with extra attributes
    current_user_auth.user_info = settings.user_info_class
    return await current_user_auth(http_auth)