Skip to content

Commit

Permalink
Add back google authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
is2ac2 committed Jun 3, 2024
1 parent 129cd27 commit ce65ca4
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 14 deletions.
6 changes: 3 additions & 3 deletions frontend/src/components/auth/GoogleAuthComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const GoogleAuthComponentInner = () => {
const [credential, setCredential] = useState<string | null>(null);
const [disableButton, setDisableButton] = useState(false);

const { setRefreshToken, api } = useAuthentication();
const { setApiKey, api } = useAuthentication();
const { addAlert } = useAlertQueue();

useEffect(() => {
Expand All @@ -28,15 +28,15 @@ const GoogleAuthComponentInner = () => {
const response = await api.post<UserLoginResponse>("/users/google", {
token: credential,
});
setRefreshToken(response.data.token);
setApiKey(response.data.token);
} catch (error) {
addAlert(humanReadableError(error), "error");
} finally {
setCredential(null);
}
}
})();
}, [credential, setRefreshToken, api, addAlert]);
}, [credential, setApiKey, api, addAlert]);

const login = useGoogleLogin({
onSuccess: (tokenResponse) => {
Expand Down
68 changes: 57 additions & 11 deletions store/app/api/routers/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from email.utils import parseaddr as parse_email_address
from typing import Annotated

import aiohttp
from fastapi import APIRouter, Depends, HTTPException, Request, Response, status
from fastapi.security.utils import get_authorization_scheme_param
from pydantic.main import BaseModel
Expand Down Expand Up @@ -88,24 +89,20 @@ class UserLoginResponse(BaseModel):
api_key: str


@users_router.post("/otp", response_model=UserLoginResponse)
async def otp_endpoint(
data: OneTimePass,
crud: Annotated[Crud, Depends(Crud.get)],
) -> UserLoginResponse:
"""Takes the one-time password and returns an API key.
async def get_login_response(email: str, crud: Crud) -> UserLoginResponse:
"""Takes the user email and returns an API key.
This function gets a user API key for an email which has been validated,
either through an OTP or through Google OAuth.
Args:
data: The one-time password payload.
email: The validated email of the user.
crud: The database CRUD object.
Returns:
The API key if the one-time password is valid.
The API key for the user.
"""
payload = OneTimePassPayload.decode(data.payload)

# If the user doesn't exist, then create a new user.
email = payload.email
user_obj = await crud.get_user_from_email(email)
if user_obj is None:
await crud.add_user(User(user_id=str(get_new_user_id()), email=email))
Expand All @@ -120,6 +117,55 @@ async def otp_endpoint(
return UserLoginResponse(api_key=str(api_key))


@users_router.post("/otp", response_model=UserLoginResponse)
async def otp_endpoint(
data: OneTimePass,
crud: Annotated[Crud, Depends(Crud.get)],
) -> UserLoginResponse:
"""Takes the one-time password and returns an API key.
Args:
data: The one-time password payload.
crud: The database CRUD object.
Returns:
The API key if the one-time password is valid.
"""
payload = OneTimePassPayload.decode(data.payload)
return await get_login_response(payload.email, crud)


async def get_google_user_info(token: str) -> dict:
async with aiohttp.ClientSession() as session:
response = await session.get(
"https://www.googleapis.com/oauth2/v3/userinfo",
params={"access_token": token},
)
if response.status != 200:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid Google token")
return await response.json()


class GoogleLogin(BaseModel):
token: str # This is the token that Google gives us for authenticated users.


@users_router.post("/google")
async def google_login_endpoint(
data: GoogleLogin,
crud: Annotated[Crud, Depends(Crud.get)],
) -> UserLoginResponse:
try:
idinfo = await get_google_user_info(data.token)
email = idinfo["email"]
except ValueError:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid Google token")
if idinfo.get("email_verified") is not True:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Google email not verified")

return await get_login_response(email, crud)


class UserInfoResponse(BaseModel):
email: str

Expand Down

0 comments on commit ce65ca4

Please sign in to comment.