async def test_write_token(jwt_strategy: JWTStrategy, user):
    token = await jwt_strategy.write_token(user)

    decoded = decode_jwt(token,
                         jwt_strategy.secret,
                         audience=jwt_strategy.token_audience)
    assert decoded["user_id"] == str(user.id)
Ejemplo n.º 2
0
def test_generate_decode_jwt(secret: SecretType):
    audience = "TEST_AUDIENCE"
    data = {"foo": "bar", "aud": audience}

    jwt = generate_jwt(data, secret, 3600)
    decoded = decode_jwt(jwt, secret, [audience])

    assert decoded["foo"] == "bar"
    assert decoded["aud"] == audience
Ejemplo n.º 3
0
    async def verify(self, token: str, request: Optional[Request] = None) -> models.UD:
        """
        Validate a verification request.

        Changes the is_verified flag of the user to True.

        Triggers the on_after_verify handler on success.

        :param token: The verification token generated by request_verify.
        :param request: Optional FastAPI request that
        triggered the operation, defaults to None.
        :raises InvalidVerifyToken: The token is invalid or expired.
        :raises UserAlreadyVerified: The user is already verified.
        :return: The verified user.
        """
        try:
            data = decode_jwt(
                token,
                self.verification_token_secret,
                [self.verification_token_audience],
            )
        except jwt.PyJWTError:
            raise InvalidVerifyToken()

        try:
            user_id = data["user_id"]
            email = data["email"]
        except KeyError:
            raise InvalidVerifyToken()

        try:
            user = await self.get_by_email(email)
        except UserNotExists:
            raise InvalidVerifyToken()

        try:
            user_uuid = UUID4(user_id)
        except ValueError:
            raise InvalidVerifyToken()

        if user_uuid != user.id:
            raise InvalidVerifyToken()

        if user.is_verified:
            raise UserAlreadyVerified()

        verified_user = await self._update(user, {"is_verified": True})

        await self.on_after_verify(verified_user, request)

        return verified_user
Ejemplo n.º 4
0
    async def callback(
        request: Request,
        response: Response,
        access_token_state: Tuple[OAuth2Token, str] = Depends(
            oauth2_authorize_callback
        ),
        user_manager: BaseUserManager[models.UC, models.UD] = Depends(get_user_manager),
        strategy: Strategy[models.UC, models.UD] = Depends(backend.get_strategy),
    ):
        token, state = access_token_state
        account_id, account_email = await oauth_client.get_id_email(
            token["access_token"]
        )

        try:
            decode_jwt(state, state_secret, [STATE_TOKEN_AUDIENCE])
        except jwt.DecodeError:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)

        new_oauth_account = models.BaseOAuthAccount(
            oauth_name=oauth_client.name,
            access_token=token["access_token"],
            expires_at=token.get("expires_at"),
            refresh_token=token.get("refresh_token"),
            account_id=account_id,
            account_email=account_email,
        )

        user = await user_manager.oauth_callback(new_oauth_account, request)

        if not user.is_active:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=ErrorCode.LOGIN_BAD_CREDENTIALS,
            )

        # Authenticate
        return await backend.login(strategy, user, response)
Ejemplo n.º 5
0
    async def test_user_active(self, user_manager: UserManagerMock,
                               user: UserDB):
        await user_manager.forgot_password(user)
        assert user_manager.on_after_forgot_password.called is True

        actual_user = user_manager.on_after_forgot_password.call_args[0][0]
        actual_token = user_manager.on_after_forgot_password.call_args[0][1]

        assert actual_user.id == user.id
        decoded_token = decode_jwt(
            actual_token,
            user_manager.reset_password_token_secret,
            audience=[user_manager.reset_password_token_audience],
        )
        assert decoded_token["user_id"] == str(user.id)
Ejemplo n.º 6
0
    async def test_user_active_not_verified(self,
                                            user_manager: UserManagerMock,
                                            user: UserDB):
        await user_manager.request_verify(user)
        assert user_manager.on_after_request_verify.called is True

        actual_user = user_manager.on_after_request_verify.call_args[0][0]
        actual_token = user_manager.on_after_request_verify.call_args[0][1]

        assert actual_user.id == user.id
        decoded_token = decode_jwt(
            actual_token,
            user_manager.verification_token_secret,
            audience=[user_manager.verification_token_audience],
        )
        assert decoded_token["user_id"] == str(user.id)
        assert decoded_token["email"] == str(user.email)
Ejemplo n.º 7
0
    async def reset_password(
        self, token: str, password: str, request: Optional[Request] = None
    ) -> models.UD:
        """
        Reset the password of a user.

        Triggers the on_after_reset_password handler on success.

        :param token: The token generated by forgot_password.
        :param password: The new password to set.
        :param request: Optional FastAPI request that
        triggered the operation, defaults to None.
        :raises InvalidResetPasswordToken: The token is invalid or expired.
        :raises UserInactive: The user is inactive.
        :raises InvalidPasswordException: The password is invalid.
        :return: The user with updated password.
        """
        try:
            data = decode_jwt(
                token,
                self.reset_password_token_secret,
                [self.reset_password_token_audience],
            )
        except jwt.PyJWTError:
            raise InvalidResetPasswordToken()

        try:
            user_id = data["user_id"]
        except KeyError:
            raise InvalidResetPasswordToken()

        try:
            user_uuid = UUID4(user_id)
        except ValueError:
            raise InvalidResetPasswordToken()

        user = await self.get(user_uuid)

        if not user.is_active:
            raise UserInactive()

        updated_user = await self._update(user, {"password": password})

        await self.on_after_reset_password(user, request)

        return updated_user
Ejemplo n.º 8
0
    async def read_token(
        self, token: Optional[str], user_manager: BaseUserManager[models.UC,
                                                                  models.UD]
    ) -> Optional[models.UD]:
        if token is None:
            return None

        try:
            data = decode_jwt(token, self.secret, self.token_audience)
            user_id = data.get("user_id")
            if user_id is None:
                return None
        except jwt.PyJWTError:
            return None

        try:
            user_uiid = UUID4(user_id)
            return await user_manager.get(user_uiid)
        except ValueError:
            return None
        except UserNotExists:
            return None