react-oauth: GoogleLogin and useGoogleLogin are not returning the same response
How can I use a custom login button? GoogleLogin component and useGoogleLogin aren’t returning the same response
With GoogleLogin the response is:
{
clientId: 'XXXXXX,
credential: 'credential_token',
select_by: 'btn'
}
With useGoogleLogin, the response is:
{
access_token: "xxxxxxxxx",
authuser: "0",
expires_in: 3599,
hd: "domain.com"
prompt: "none"
scope: "email profile openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"
token_type: "Bearer"
}
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.
import { OAuth2Client } from 'google-auth-library'
// ...
const userProfile = googleClient.verifyIdToken({
idToken: req.body.credentials,
audience: req.body.clientId,
})
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 4
- Comments: 28 (6 by maintainers)
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 if you are using it in implicit flow like that, it will return
access_token
to be used for fetching data from google APIs for exampleBut my recommendation for you as you have a backend, go with
Authorization code flow
, which will returncode
that you will exchange with your backend to obtainaccess_token
(to talk with google APIs)refresh_token
(to refresh user’s token)id_token
(JWT contains all user’s info)Client
Backend using express
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
redirect_uri_mismatch
error 🙃🚨 In the backend OAuth2Client, the 3rd param (
redirectUri
) must be'postmessage'
! 🚨Do not, I repeat, DO NOT try to be smart and add your app’s redirect URI there. It will cause a very unhelpful
invalid_request
errorYou can't sign in to this app because it doesn't comply with Google's OAuth 2.0 policy for keeping apps secure. You can let the app developer know that this app doesn't comply with one or more Google validation rules.
or a slightly more helpful but still unclearredirect_uri_mismatch
error.Here’s the snippet in question from the example:
As far as an actual explanation for why it must be
'postmessage'
(or why Google’s docs neglect to mention it), all I’ve really found have been StackOverflow answers referencing an old Google+ platform sign-in doc:Needed this for my Django backend. Here’s the code I got working for the views:
Of course this is not production ready (needs validation, remove hardcoded values, etc.), but it demonstrates the API calls to Google’s OAuth2 service.
@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
@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,
access_token
google gave us to fetch certain data from themjust 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
id_token
(google’s JWT) from custom button, you will need the authorization code flow as mentioned above in the example.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.
A bit late to replying to this, sorry.
UserRefreshClient
is included in the ‘google-auth-library’ package, so just import it viaimport { UserRefreshClient } from 'google-auth-library';
.@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
useGoogleLogin
hook to have the request returncredential
?Use case would be something like:
Or maybe there are other ways to style the
GoogleLogin
component?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
UserRefreshClient
in the code snippet - where does this come from?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??
If someone use dj-rest-auth and django-allauth, and encounter error
redirect uri mismatch
you can see this comment https://github.com/iMerica/dj-rest-auth/issues/525#issuecomment-1675885190 which set
callback_url = "postmessage"
manuallyThanks man!
Thank you very much, @MomenSherif.
Thanks @MomenSherif for the details. I could make it work with your code snippet. Just curious, When should I call the refresh token endpoint for Google auth? At every new session?
Thanks for this package. it’s very clean.
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:
and here’s the backend:
Stack overflow link: https://stackoverflow.com/questions/74132586/accessing-google-calendar-api-using-service-account
AHh never mind I solved it - I was using a different oauth client ID for frontend/backend. After using the same IDs it worked.
@kharithomas It’s on backend side (express server in this example) if you want to use refresh token
If you just need user’s token you can use
<GoogleLogin />
it’s straight forwardOr if you need custom button you can use
useGoogleLogin
, and check demo website in the Readme, will show you how to get user info step by step@gusaiani Most welcome 😃
@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 🎉