MomenSherif / react-oauth

Google OAuth2 using the new Google Identity Services SDK for React 🚀
https://www.npmjs.com/package/@react-oauth/google
MIT License
1.07k stars 136 forks source link

App_name wants additional access to your Google Account #226

Open hoka-san opened 1 year ago

hoka-san commented 1 year ago

I get this dialog each time i login even though I have already granted all permissions.

image

I use auth-code with useGoogleLogin. My scope is 'https://www.googleapis.com/auth/classroom.rosters.readonly', 'https://www.googleapis.com/auth/classroom.profile.emails',

If I change to implicit the dialog is not shown. I need auth-code though....

Anyone else seen this? How do I get rid of it?

Thanks, Håkan

MomenSherif commented 1 year ago

It will be shown every time until you submit your application to google to review and they approve it

hoka-san commented 1 year ago

It will be shown every time until you submit your application to google to review and they approve it

Hm I dont think thats it. image

If that was the issue, would I not get the same dialog with "implicit"?

hoka-san commented 1 year ago

I found this thread discussing the same dialog, they mention something about force creating a new refreshToken. https://github.com/CodetrixStudio/CapacitorGoogleAuth/issues/140

I have noticed that I always get a new refresh token when I do : await oAuth2Client.getToken(code);

Im migrating from react-google-login if that helps.

heyheyjc commented 1 year ago

May not be your problem, but this happens when you set the 'prompt' to anything except an empty string ''

hoka-san commented 1 year ago

May not be your problem, but this happens when you set the 'prompt' to anything except an empty string ''

Thanks for trying to help, but that wasn't my problem :(

jcayabyab commented 1 year ago

I'm also getting the same issue. This actually might be intrinsic to the auth-code flow in Google. Upon further inspection of the OAuth query string that is generated after pressing the button, we can see that it sends prompt=select_account%20consent or prompt=consent depending on whether or not select_account is enabled, which I'm assuming means that the consent screen is always shown. In the implicit flow the default value for prompt is select_account, which may be why it works with the implicit flow. This seems intrinsic to how the initCodeClient method is designed, which I'm not sure there's a trivial way to override fully (you can see the config options here). Not sure the best way to proceed.

hoka-san commented 1 year ago

If I could choose "none" that would work for me I think.

image
hoka-san commented 1 year ago

I don't really understand the code here, but it seems like you cant override the prompt when using auth-code flow. OverridableTokenClientConfig contains the prompt option.

`declare function useGoogleLogin(options: UseGoogleLoginOptionsImplicitFlow): (overrideConfig?: OverridableTokenClientConfig) => void;

declare function useGoogleLogin(options: UseGoogleLoginOptionsAuthCodeFlow): () => void; `

jcayabyab commented 1 year ago

I was able to get rid of the prompt by setting include_granted_scopes to false in the config. This isn't fully supported by this library so you'd get type-checking issues in TS, but it will work correctly. I'm not sure if this would create issues downstream if you're iteratively granting other permissions to the user.

It looks like the issue is with the actual Google 3P Authorization JS Library and not this library. Ideally, the prompt parameter should be available on auth-code as well, but that's in Google's hands to update :(

MomenSherif commented 1 year ago

Feel free to open PR

hayksaryan commented 1 year ago

Setting include_granted_scopes to false didn't fix the authorization code flow though. Any idea how that should be handled? Still seeing the additional access request window every time.

mrnx2004 commented 1 year ago

include_granted_scopes: false It's work for me.

Mhal007 commented 11 months ago

Did you find any solution @hayksaryan?

hayksaryan commented 11 months ago

Our team was working on this months ago so I apologize if the solution below is incomplete, I might not recollect every detail.

The solution was not requesting any scopes on initial authentication, and then adding a button for incremental authorization which only requests feature-related scopes on feature pages.

Say I need to display the user's calendar events in the dashboard. I require the user to click a Google incremental authorization button, which only requests that specific scope scopes: {[https://www.googleapis.com/auth/calendar.events.readonly]}. The include_granted_scopes is set to be true. We also pass in the hint which is the email of authenticated user.

We have also wrapped Google button with a GoogleOAuthProvider (imported from @react-oauth/google) which I think is required when you use a custom button (?).

Initial Authentication params

{
    onSuccess: () => {}, // your handler here
    onError: () => {}, // your handler here
    include_granted_scopes: false,
}

Incremental Authorization params

{
    onSuccess: () => {}, // your handler here
    onError: () => {}, // your handler here,
    hint: "master.of.partial.arts@pretender.com",
    scopes: {[https://www.googleapis.com/auth/calendar.events.readonly]}
};

The above parameters are passed down to our GoogleButton component by the page that's using it. And then those are passed to useGoogleLogin hook.

Once the user accepts new permission request (onSuccess) we get a new auth code (onSuccess={(code) => { // do something }})) using which we get the new refresh token in back-end by re-authenticating the user under the hood

Mhal007 commented 11 months ago

Hey @hayksaryan, thank you for a detailed answer.

Your solution looks good, but I think our use case is a bit different. We need to fetch user information coming from Google API right after he's logged in - it is needed to display the initial content, so we can't use any additional buttons to request additional scopes. Also, isn't it like in your case the consent screen is just moved to a different screen? When the user logs out, then logs in again, and enters the feature page, isn't it like he sees the consent screen again? The goal was to never show the consent screen again after it's been done once. If I'm missing something, please let me know.

In general, I think both @jcayabyab and @hoka-san are right. It's just not possible to omit the consent screen in the auth code flow. Maybe that is on purpose? Because with the implicit flow you only receive a token that is active for 1 hour (access_token), whereas in the auth code flow you receive a token (refresh_token, among others) that is active forever (with exceptions).

Probably best would be to use the 'auth code' flow only once and store the refresh token for a given user for all future Google API calls, whereas using a separate method for deciding whether the user is logged to your app or not (jwt, cookie, whatever suits you), just like with the standard login with google approach where you would use the 'implicit' flow.