From 4203cf517a1bbe3180ad39a4029f6a8409725f54 Mon Sep 17 00:00:00 2001 From: sosokker Date: Sat, 28 Oct 2023 22:41:33 +0700 Subject: [PATCH] Fix 400 google OAuth api call --- backend/core/settings.py | 18 ++++++++- backend/users/adapter.py | 23 +++++++++++ backend/users/views.py | 8 +++- frontend/package.json | 2 + frontend/pnpm-lock.yaml | 21 ++++++++++ frontend/src/api/axiosapi.jsx | 8 +++- frontend/src/components/IconSideNav.jsx | 52 ++++++------------------- frontend/src/components/login.jsx | 28 ++++++------- frontend/src/main.jsx | 8 +++- 9 files changed, 108 insertions(+), 60 deletions(-) create mode 100644 backend/users/adapter.py diff --git a/backend/core/settings.py b/backend/core/settings.py index fa98958..2c6afa9 100644 --- a/backend/core/settings.py +++ b/backend/core/settings.py @@ -83,10 +83,18 @@ SOCIALACCOUNT_PROVIDERS = { 'client_id': config('GOOGLE_CLIENT_ID'), 'secret': config('GOOGLE_CLIENT_SECRET'), 'key': '' + }, + "SCOPE": [ + "profile", + "email", + ], + "AUTH_PARAMS": { + "access_type": "online", } } } + CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_ALL_ORIGINS = False CORS_ALLOWED_ORIGINS = [ @@ -95,6 +103,10 @@ CORS_ALLOWED_ORIGINS = [ "http://localhost:5173", ] +CSRF_TRUSTED_ORIGINS = ["http://*"] + +CORS_ORIGIN_WHITELIST = ["*"] + MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', @@ -104,7 +116,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - "allauth.account.middleware.AccountMiddleware", + # "allauth.account.middleware.AccountMiddleware", ] ROOT_URLCONF = 'core.urls' @@ -195,4 +207,6 @@ SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [ LOGIN_REDIRECT_URL = '/' LOGOUT_REDIRECT_URL = '/' -AUTH_USER_MODEL = "users.CustomUser" \ No newline at end of file +AUTH_USER_MODEL = "users.CustomUser" + +ACCOUNT_EMAIL_REQUIRED = True \ No newline at end of file diff --git a/backend/users/adapter.py b/backend/users/adapter.py new file mode 100644 index 0000000..fbcc5e4 --- /dev/null +++ b/backend/users/adapter.py @@ -0,0 +1,23 @@ +from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter +from allauth.socialaccount.providers.oauth2.client import OAuth2Error +import jwt + + +class CustomGoogleOAuth2Adapter(GoogleOAuth2Adapter): + def complete_login(self, request, app, token, response, **kwargs): + try: + identity_data = jwt.decode( + response["id_token"], #another nested id_token was returned + options={ + "verify_signature": False, + "verify_iss": True, + "verify_aud": True, + "verify_exp": True, + }, + issuer=self.id_token_issuer, + audience=app.client_id, + ) + except jwt.PyJWTError as e: + raise OAuth2Error("Invalid id_token") from e + login = self.get_provider().sociallogin_from_response(request, identity_data) + return login \ No newline at end of file diff --git a/backend/users/views.py b/backend/users/views.py index 4d032e4..fd20a19 100644 --- a/backend/users/views.py +++ b/backend/users/views.py @@ -5,10 +5,12 @@ from rest_framework import status from rest_framework.permissions import IsAuthenticated, AllowAny from rest_framework.response import Response from rest_framework.views import APIView -from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter from dj_rest_auth.registration.views import SocialLoginView +from allauth.socialaccount.providers.oauth2.client import OAuth2Client +from .adapter import CustomGoogleOAuth2Adapter from .serializers import MyTokenObtainPairSerializer, CustomUserSerializer +from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter class ObtainTokenPairWithCustomView(APIView): """ @@ -74,5 +76,7 @@ class GoogleLogin(SocialLoginView): Google Login View. Handles Google OAuth2 authentication. """ - permission_classes = (AllowAny,) + # permission_classes = (AllowAny,) adapter_class = GoogleOAuth2Adapter + client_class = OAuth2Client + # callback_url = 'http://localhost:8000/accounts/google/login/callback/' \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index a817531..98acb6d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,11 +16,13 @@ "@material-ui/icons": "^4.11.3", "@mui/icons-material": "^5.14.15", "@mui/material": "^5.14.15", + "@react-oauth/google": "^0.11.1", "axios": "^1.5.1", "bootstrap": "^5.3.2", "dotenv": "^16.3.1", "framer-motion": "^10.16.4", "gapi-script": "^1.2.0", + "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-bootstrap": "^2.9.1", "react-dom": "^18.2.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 0b550af..d085dbb 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -23,6 +23,9 @@ dependencies: '@mui/material': specifier: ^5.14.15 version: 5.14.15(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@react-oauth/google': + specifier: ^0.11.1 + version: 0.11.1(react-dom@18.2.0)(react@18.2.0) axios: specifier: ^1.5.1 version: 1.5.1 @@ -38,6 +41,9 @@ dependencies: gapi-script: specifier: ^1.2.0 version: 1.2.0 + jwt-decode: + specifier: ^4.0.0 + version: 4.0.0 react: specifier: ^18.2.0 version: 18.2.0 @@ -1115,6 +1121,16 @@ packages: react: 18.2.0 dev: false + /@react-oauth/google@0.11.1(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-tywZisXbsdaRBVbEu0VX6dRbOSL2I6DgY97woq5NMOOOz+xtDsm418vqq+Vx10KMtra3kdHMRMf0hXLWrk2RMg==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@remix-run/router@1.10.0: resolution: {integrity: sha512-Lm+fYpMfZoEucJ7cMxgt4dYt8jLfbpwRCzAjm9UgSLOkmlqo9gupxt6YX3DY0Fk155NT9l17d/ydi+964uS9Lw==} engines: {node: '>=14.0.0'} @@ -2584,6 +2600,11 @@ packages: object.values: 1.1.7 dev: true + /jwt-decode@4.0.0: + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} + dev: false + /keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: diff --git a/frontend/src/api/axiosapi.jsx b/frontend/src/api/axiosapi.jsx index 849ce09..a96be14 100644 --- a/frontend/src/api/axiosapi.jsx +++ b/frontend/src/api/axiosapi.jsx @@ -62,16 +62,20 @@ const apiUserLogout = () => { } // Function for Google login -const googleLogin = async (accessToken) => { +const googleLogin = async (accesstoken) => { + axios.defaults.withCredentials = true let res = await axios.post( "http://localhost:8000/api/dj-rest-auth/google/", { - access_token: accessToken, + access_token: accesstoken, + id_token: accesstoken, } ); + // console.log('service google login res: ', res); return await res; }; + // Function to get 'hello' data const getGreeting = () => { return axiosInstance diff --git a/frontend/src/components/IconSideNav.jsx b/frontend/src/components/IconSideNav.jsx index 3b91b5a..4ed357c 100644 --- a/frontend/src/components/IconSideNav.jsx +++ b/frontend/src/components/IconSideNav.jsx @@ -1,19 +1,20 @@ -import { AnimatePresence, motion } from "framer-motion"; import { useState } from "react"; -import { - SiFramer, - SiTailwindcss, - SiReact, - SiJavascript, - SiCss3, -} from "react-icons/si"; - +import { AnimatePresence, motion } from "framer-motion"; +import { SiFramer, SiTailwindcss, SiReact, SiJavascript, SiCss3 } from "react-icons/si"; import homeLogo from "../assets/home.png"; import calendarLogo from "../assets/calendar.png"; import planLogo from "../assets/planning.png"; import pieLogo from "../assets/pie-chart.png"; import plusLogo from "../assets/plus.png"; +const menuItems = [ + { id: 0, icon: , logo: homeLogo }, + { id: 1, icon: , logo: calendarLogo }, + { id: 2, icon: , logo: planLogo }, + { id: 3, icon: , logo: pieLogo }, + { id: 4, icon: , logo: plusLogo }, +]; + const IconSideNav = () => { return (
@@ -26,34 +27,6 @@ const IconSideNav = () => { const SideNav = () => { const [selected, setSelected] = useState(0); - const menuItems = [ - { - id: 0, - icon: , - logo: homeLogo, - }, - { - id: 1, - icon: , - logo: calendarLogo, - }, - { - id: 2, - icon: , - logo: planLogo, - }, - { - id: 3, - icon: , - logo: pieLogo, - }, - { - id: 4, - icon: , - logo: plusLogo, - }, - ]; - return (
); diff --git a/frontend/src/main.jsx b/frontend/src/main.jsx index 1b1eea5..3b3dc61 100644 --- a/frontend/src/main.jsx +++ b/frontend/src/main.jsx @@ -1,7 +1,13 @@ import React from "react"; -import ReactDOM from "react-dom"; +import ReactDOM from "react-dom/client"; import App from "./App"; +import { GoogleLogin, GoogleOAuthProvider} from '@react-oauth/google'; + +const GOOGLE_CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID + ReactDOM.createRoot(document.getElementById("root")).render( + + ); \ No newline at end of file