Skip to content

Commit

Permalink
feat: add support for use_fedcm_for_prompt for fedcm migration (#316)
Browse files Browse the repository at this point in the history
  • Loading branch information
MomenSherif authored Nov 18, 2023
1 parent cc7c908 commit 9c23c44
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 17 deletions.
6 changes: 6 additions & 0 deletions .changeset/brown-actors-return.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@react-oauth/google': minor
---

- add support for use_fedcm_for_prompt for fedcm migration
- export `useGoogleOAuth` returns { scriptLoadedSuccessfully: boolean; clientId: string }
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,7 @@ const login = useGoogleLogin({
onSuccess: tokenResponse => console.log(tokenResponse),
});

<MyCustomButton onClick={() => login()}>
Sign in with Google 🚀{' '}
</MyCustomButton>;
<MyCustomButton onClick={() => login()}>Sign in with Google 🚀</MyCustomButton>;
```

#### Authorization code flow
Expand All @@ -157,9 +155,7 @@ const login = useGoogleLogin({
flow: 'auth-code',
});

<MyCustomButton onClick={() => login()}>
Sign in with Google 🚀{' '}
</MyCustomButton>;
<MyCustomButton onClick={() => login()}>Sign in with Google 🚀</MyCustomButton>;
```

#### Checks if the user granted all the specified scope or scopes
Expand All @@ -186,6 +182,8 @@ const hasAccess = hasGrantedAnyScopeGoogle(
);
```

#### [Content Security Policy (if needed)](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid#content_security_policy)

## API

### GoogleOAuthProvider
Expand Down Expand Up @@ -227,6 +225,7 @@ const hasAccess = hasGrantedAnyScopeGoogle(
| | intermediate_iframe_close_callback | `function` | Overrides the default intermediate iframe behavior when users manually close One Tap |
| | itp_support | `boolean` | Enables upgraded One Tap UX on ITP browsers |
| | hosted_domain | `string` | If your application knows the Workspace domain the user belongs to, use this to provide a hint to Google. For more information, see the [hd](https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters) field in the OpenID Connect docs |
| | use_fedcm_for_prompt | `boolean` | Allow the browser to control user sign-in prompts and mediate the sign-in flow between your website and Google. |

### useGoogleLogin (Both implicit & authorization code flow)

Expand Down Expand Up @@ -267,3 +266,4 @@ const hasAccess = hasGrantedAnyScopeGoogle(
| | cancel_on_tap_outside | `boolean` | Controls whether to cancel the prompt if the user clicks outside of the prompt |
| | hosted_domain | `string` | If your application knows the Workspace domain the user belongs to, use this to provide a hint to Google. For more information, see the [hd](https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters) field in the OpenID Connect docs |
| | disabled | `boolean` | Controls whether to cancel the popup in cases such as when the user is already logged in |
| | use_fedcm_for_prompt | `boolean` | Allow the browser to control user sign-in prompts and mediate the sign-in flow between your website and Google. |
16 changes: 9 additions & 7 deletions packages/@react-oauth/google/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $ npm install @react-oauth/google@latest
$ yarn add @react-oauth/google@latest
```

## Demo
## Demo & How to use to fetch user details

https://react-oauth.vercel.app/

Expand Down Expand Up @@ -140,9 +140,7 @@ const login = useGoogleLogin({
onSuccess: tokenResponse => console.log(tokenResponse),
});

<MyCustomButton onClick={() => login()}>
Sign in with Google 🚀{' '}
</MyCustomButton>;
<MyCustomButton onClick={() => login()}>Sign in with Google 🚀</MyCustomButton>;
```

#### Authorization code flow
Expand All @@ -157,9 +155,7 @@ const login = useGoogleLogin({
flow: 'auth-code',
});

<MyCustomButton onClick={() => login()}>
Sign in with Google 🚀{' '}
</MyCustomButton>;
<MyCustomButton onClick={() => login()}>Sign in with Google 🚀</MyCustomButton>;
```

#### Checks if the user granted all the specified scope or scopes
Expand All @@ -186,13 +182,16 @@ const hasAccess = hasGrantedAnyScopeGoogle(
);
```

#### [Content Security Policy (if needed)](https://developers.google.com/identity/gsi/web/guides/get-google-api-clientid#content_security_policy)

## API

### GoogleOAuthProvider

| Required | Prop | Type | Description |
| :------: | ------------------- | ---------- | --------------------------------------------------------------------------- |
|| clientId | `string` | [**Google API client ID**](https://console.cloud.google.com/apis/dashboard) |
| | nonce | `string` | Nonce applied to GSI script tag. Propagates to GSI's inline style tag |
| | onScriptLoadSuccess | `function` | Callback fires on load gsi script success |
| | onScriptLoadError | `function` | Callback fires on load gsi script failure |

Expand Down Expand Up @@ -226,6 +225,7 @@ const hasAccess = hasGrantedAnyScopeGoogle(
| | intermediate_iframe_close_callback | `function` | Overrides the default intermediate iframe behavior when users manually close One Tap |
| | itp_support | `boolean` | Enables upgraded One Tap UX on ITP browsers |
| | hosted_domain | `string` | If your application knows the Workspace domain the user belongs to, use this to provide a hint to Google. For more information, see the [hd](https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters) field in the OpenID Connect docs |
| | use_fedcm_for_prompt | `boolean` | Allow the browser to control user sign-in prompts and mediate the sign-in flow between your website and Google. |

### useGoogleLogin (Both implicit & authorization code flow)

Expand Down Expand Up @@ -265,3 +265,5 @@ const hasAccess = hasGrantedAnyScopeGoogle(
| | promptMomentNotification | `(notification: PromptMomentNotification) => void` | [PromptMomentNotification](https://developers.google.com/identity/gsi/web/reference/js-reference) methods and description |
| | cancel_on_tap_outside | `boolean` | Controls whether to cancel the prompt if the user clicks outside of the prompt |
| | hosted_domain | `string` | If your application knows the Workspace domain the user belongs to, use this to provide a hint to Google. For more information, see the [hd](https://developers.google.com/identity/protocols/oauth2/openid-connect#authenticationuriparameters) field in the OpenID Connect docs |
| | disabled | `boolean` | Controls whether to cancel the popup in cases such as when the user is already logged in |
| | use_fedcm_for_prompt | `boolean` | Allow the browser to control user sign-in prompts and mediate the sign-in flow between your website and Google. |
2 changes: 1 addition & 1 deletion packages/@react-oauth/google/src/hooks/useGoogleLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ export default function useGoogleLogin({
const clientMethod =
flow === 'implicit' ? 'initTokenClient' : 'initCodeClient';

const client = window?.google?.accounts.oauth2[clientMethod]({
const client = window?.google?.accounts?.oauth2[clientMethod]({
client_id: clientId,
scope: overrideScope ? scope : `openid profile email ${scope}`,
callback: (response: TokenResponse | CodeResponse) => {
Expand Down
11 changes: 10 additions & 1 deletion packages/@react-oauth/google/src/hooks/useGoogleOneTapLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { useEffect, useRef } from 'react';

import { useGoogleOAuth } from '../GoogleOAuthProvider';
import { extractClientId } from '../utils';
import {
import type {
CredentialResponse,
GoogleCredentialResponse,
IdConfiguration,
MomentListener,
} from '../types';

Expand All @@ -17,6 +18,8 @@ interface UseGoogleOneTapLoginOptions {
state_cookie_domain?: string;
hosted_domain?: string;
disabled?: boolean;
use_fedcm_for_prompt?: IdConfiguration['use_fedcm_for_prompt'];
auto_select?: boolean;
}

export default function useGoogleOneTapLogin({
Expand All @@ -27,7 +30,9 @@ export default function useGoogleOneTapLogin({
prompt_parent_id,
state_cookie_domain,
hosted_domain,
use_fedcm_for_prompt = false,
disabled,
auto_select,
}: UseGoogleOneTapLoginOptions): void {
const { clientId, scriptLoadedSuccessfully } = useGoogleOAuth();

Expand Down Expand Up @@ -66,6 +71,8 @@ export default function useGoogleOneTapLogin({
cancel_on_tap_outside,
prompt_parent_id,
state_cookie_domain,
use_fedcm_for_prompt,
auto_select,
});

window?.google?.accounts?.id?.prompt(promptMomentNotificationRef.current);
Expand All @@ -80,6 +87,8 @@ export default function useGoogleOneTapLogin({
prompt_parent_id,
state_cookie_domain,
hosted_domain,
use_fedcm_for_prompt,
disabled,
auto_select,
]);
}
5 changes: 4 additions & 1 deletion packages/@react-oauth/google/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
export { default as GoogleOAuthProvider } from './GoogleOAuthProvider';
export {
default as GoogleOAuthProvider,
useGoogleOAuth,
} from './GoogleOAuthProvider';
export { default as GoogleLogin } from './GoogleLogin';
export type { GoogleLoginProps } from './GoogleLogin';
export { default as googleLogout } from './googleLogout';
Expand Down
11 changes: 10 additions & 1 deletion packages/@react-oauth/google/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export interface IdConfiguration {
* field in the OpenID Connect docs.
*/
hosted_domain?: string;
/**
* Allow the browser to control user sign-in prompts and mediate the sign-in flow between your website and Google.
* @default false
*/
use_fedcm_for_prompt?: boolean;
}

export interface CredentialResponse {
Expand Down Expand Up @@ -99,7 +104,11 @@ export interface PromptMomentNotification {
isDisplayed: () => boolean;
/** Is this notification for a display moment, and the UI isn't displayed? */
isNotDisplayed: () => boolean;
/** The detailed reason why the UI isn't displayed */
/**
* The detailed reason why the UI isn't displayed
* Avoid using `opt_out_or_no_session`. When FedCM is enabled,
* this value is not supported. See Migrate to FedCM page for more information.
* */
getNotDisplayedReason: () =>
| 'browser_not_supported'
| 'invalid_client'
Expand Down

1 comment on commit 9c23c44

@vercel
Copy link

@vercel vercel bot commented on 9c23c44 Nov 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

react-oauth – ./

react-oauth-momensherif.vercel.app
react-oauth.vercel.app
react-oauth-git-master-momensherif.vercel.app

Please sign in to comment.