-
Notifications
You must be signed in to change notification settings - Fork 137
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
GoogleLogin and useGoogleLogin are not returning the same response #12
Comments
Authenticating the user involves obtaining an ID token and validating it. ID tokens are a standardized feature of OpenID Connect designed for use in sharing identity assertions on the Internet. You can get id_token (JWT) if you are using the personalized button for authentication. and useGoogleLogin hook is wrapping the Authorization part in new Google SDK const googleLogin = useGoogleLogin({
onSuccess: async tokenResponse => {
console.log(tokenResponse);
// fetching userinfo can be done on the client or the server
const userInfo = await axios
.get('https://www.googleapis.com/oauth2/v3/userinfo', {
headers: { Authorization: `Bearer ${tokenResponse.access_token}` },
})
.then(res => res.data);
console.log(userInfo);
},
// flow: 'implicit', // implicit is the default
}); But my recommendation for you as you have a backend, go with
Client const googleLogin = useGoogleLogin({
onSuccess: async ({ code }) => {
const tokens = await axios.post('http://localhost:3001/auth/google', { // http://localhost:3001/auth/google backend that will exchange the code
code,
});
console.log(tokens);
},
flow: 'auth-code',
}); Backend using express require('dotenv').config();
const express = require('express');
const {
OAuth2Client,
} = require('google-auth-library');
const cors = require('cors');
const app = express();
app.use(cors());
app.use(express.json());
const oAuth2Client = new OAuth2Client(
process.env.CLIENT_ID,
process.env.CLIENT_SECRET,
'postmessage',
);
app.post('/auth/google', async (req, res) => {
const { tokens } = await oAuth2Client.getToken(req.body.code); // exchange code for tokens
console.log(tokens);
res.json(tokens);
});
app.post('/auth/google/refresh-token', async (req, res) => {
const user = new UserRefreshClient(
clientId,
clientSecret,
req.body.refreshToken,
);
const { credentials } = await user.refreshAccessToken(); // optain new tokens
res.json(credentials);
})
app.listen(3001, () => console.log(`server is running`)); |
Thanks @MomenSherif for the details. I could make it work with your code snippet. Thanks for this package. it's very clean. |
@eakl Most welcome ❤ you can set a timer to refresh the token with a new one before expiration, the timer can be set after user login, or the app initialized with a refresh token available another implementation is to setup an interceptor for your requests to validate token expiration time, and if it will expire soon it will fire a request to refresh the token. Any approach of them makes sense and is easy to implement for you, Go ahead with it 🎉 |
@MomenSherif, thanks for the explanation above. And thanks for this library. I'm certainly inclined to use it. Having said what you said, would you still consider adding an option for the Use case would be something like:
Or maybe there are other ways to style the |
@gusaiani unfortunately customizing the personalized button is very limited because Google renders it in an iframe and allows only certain options to be customizable through known props because they want the same look and feel across all applications. All pops are listed here Returning credential in custom hook, will be difficult as google doesn't expose it implicitly,
const googleLogin = useGoogleLogin({
onSuccess: async tokenResponse => {
console.log(tokenResponse);
// fetching userinfo can be done on the client or the server
const userInfo = await axios
.get('https://www.googleapis.com/oauth2/v3/userinfo', {
headers: { Authorization: `Bearer ${tokenResponse.access_token}` },
})
.then(res => res.data);
console.log(userInfo);
},
// flow: 'implicit', // implicit is the default
}); just wanted the package to be a small wrapper around the new SDK, with the same behaviors google gives us, and it's upon the consumer to use it as his application wants. if you need refresh token, or for some reason you need to get you can tweak authorization flow to exchange code on the client side and ignore backend, but you will expose your client secret for any hackers. |
Thank you very much, @MomenSherif. |
@gusaiani Most welcome 😃 |
Thank you so much for this example. I just recently moved from react-google-login and the setup has been a breeze. I noticed you're using |
@kharithomas If you just need user's token you can use Or if you need custom button you can use |
A bit late to replying to this, sorry.
|
@MomenSherif Thanks for your reply - realized I didn't see this. I was able to implement a solution as you mentioned. @Toxocious Thanks for providing this alternate example. |
Thank you so much for the authorization code flow example, @MomenSherif ! 🙇 It has been invaluable for a migration from the old Google Sign-in Library to Google Identity Services. Just in case this saves anyone some of the headaches I have suffered debugging this: follow the example exactly as it is written! I thought I was being smart by inserting my app's redirect URI in the backend snippet, but instead I spent an entire night searching online to try and understand why my app "doesn't comply with Google's OAuth 2.0 policy" or why I was getting a 🚨 In the backend OAuth2Client, the 3rd param (
|
@mistryrn there's a special place in hell for developers of this api, right next to recaptcha creators this absolutely HAS to be in the doc, spent like 5 hours figuring out, messaging support etc |
useGoogleLogin was giving us accessToken(Bearer type) with flow: 'auth-code' and it is giving us code without flow: auth-code, can somebody tell me how will i get credential which was send to onsuccess function with GoogleLogin |
Needed this for my Django backend. Here's the code I got working for the views: from django.http import JsonResponse
import requests
import core.settings as settings
def login(request):
auth_code = request.GET['code']
data = {
'code': auth_code,
'client_id': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY, # client ID
'client_secret': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET, # client secret
'redirect_uri': 'postmessage',
'grant_type': 'authorization_code'
}
response = requests.post('https://oauth2.googleapis.com/token', data=data)
return JsonResponse(response.json(), status=200)
def refresh(request):
refresh_token = request.GET['refresh_token']
data = {
'refresh_token': refresh_token,
'client_id': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_KEY, # client ID
'client_secret': settings.SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET, # client secret
'grant_type': 'refresh_token'
}
response = requests.post('https://oauth2.googleapis.com/token', data=data)
return JsonResponse(response.json(), status=200) Of course this is not production ready (needs validation, remove hardcoded values, etc.), but it demonstrates the API calls to Google's OAuth2 service. |
I followed all the steps in @MomenSherif's post exactly but I am still ending up with an error related to an unauthorized client. Basically I'm taking the code from the user from the frontend and sending to the backend, from where it's supposed to exchange the code for an accesstoken using google's api, but I keep getting an error 401: unauthorized_client, but I have enabled the calendar API on my project. I'm not sure what is going wrong. Here's the frontend code: const googleLogin = useGoogleLogin({
flow: "auth-code",
onSuccess: async codeResponse => {
console.log(codeResponse);
const tokens = await axios.post("http://localhost:3001/auth/google/", {
code: codeResponse.code
});
console.log(tokens);
}
}) and here's the backend: app.post('/auth/google', async (req, res) => {
console.log("got request!")
console.log(req.body.code)
const tokens = await axios.post("https://oauth2.googleapis.com/token", {
'code': req.body.code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': 'postmessage',
'grant_type': 'authorization_code'
});
console.log(tokens);
res.json(tokens);
}); Stack overflow link: AHh never mind I solved it - I was using a different oauth client ID for frontend/backend. After using the same IDs it worked. |
Thanks man! |
I am continuously running into an error when doing it this way.
However, on the frontend, this is what my code looks like.
And on the backend
As you can see, it's exactly the same as yours. How did you get past the redirect URI error? EDIT: wtf, scroll up guys, I don't understand why either, but it really is just replacing your redirect_uri on backend with 'postmessage'. wtf google seriously?? |
Hi @MomenSherif Thank you so much for posting the solution, I have been scratching my head for this implicit-flow and auth-flow for quite a few hours and finally got the required solution. Thanks Again!!! |
Please could any one help with I get a error every time the popup window appears (Cross-Origin-Opener-Policy policy would block the window.closed call) |
If someone use dj-rest-auth and django-allauth, and encounter error you can see this comment class GoogleLogin(
SocialLoginView
): # if you want to use Authorization Code Grant, use this
adapter_class = GoogleOAuth2Adapter
callback_url = "postmessage"
client_class = OAuth2Client |
"postmessage" is only for auth code retrieved from popup methods. If using redirect, pass the redirect_uri used for retrieving auth code. |
After successful login from redirect mode, Google redirects back to your URL and attaches authorization code in as query string the URL as I can remember |
Can you please elaborate. How to get that url? |
For anyone who is using NestJS, PUT CLIENT IN THE CONTROLLERotherwise, you will get an Correct code:
|
i want to convert the access_token to id_token in the frontend but i don't know if there's any security issue that can arise by exposing client_secret to the frontend |
ok, got my answer here https://stackoverflow.com/questions/53622075/ |
This works perfectly if you follow as it is. But, I want to make some tweaks to this. Like, decoding the id_token JWT string, extracting some things and storing them in the database. For some reason, even when the slightest changes are made, it throws an 404 error. |
is this ok to have this kind of error and when i try this in typescript react there's an error in
}); do i have need anything like in header authorization something |
I have the same issue among other things. |
Can anyone help me to have resources to continue this google oauth. I already get the access_token: what is next after this thanks |
For who that using .net to build back-end, follow this guide to get access_token as JWT from access_token which return from Google |
How can I use a custom login button? GoogleLogin component and useGoogleLogin aren't returning the same response
With GoogleLogin the response is:
With useGoogleLogin, the response is:
The hook isn't supposed to return the credential key/value as the component does?
I am sending the credential key/value to my server which verifies it to send me back the user profile.
The text was updated successfully, but these errors were encountered: