diff --git a/.changeset/shiny-yaks-wave.md b/.changeset/shiny-yaks-wave.md
new file mode 100644
index 0000000000..7d5810ee13
--- /dev/null
+++ b/.changeset/shiny-yaks-wave.md
@@ -0,0 +1,53 @@
+---
+'@clerk/clerk-js': minor
+'@clerk/nextjs': minor
+'@clerk/clerk-react': minor
+'@clerk/types': minor
+---
+
+Add support for GoogleOneTap. New APIs listed:
+### React component
+- ``
+
+Customize the UX of the prompt
+
+```tsx
+
+```
+
+### Use the component from with Vanilla JS
+- `Clerk.openGoogleOneTap(props: GoogleOneTapProps)`
+- `Clerk.closeGoogleOneTap()`
+### Low level APIs for custom flows
+- `await Clerk.authenticateWithGoogleOneTap({ token: 'xxxx'})`
+- `await Clerk.handleGoogleOneTapCallback()`
+
+We recommend using this two methods together in order and let Clerk to perform the correct redirections.
+```tsx
+google.accounts.id.initialize({
+ callback: async response => {
+ const signInOrUp = await Clerk.authenticateWithGoogleOneTap({ token: response.credential})
+ await Clerk.handleGoogleOneTapCallback(signInOrUp, {
+ signInForceRedirectUrl: window.location.href,
+ })
+ },
+});
+```
+
+In case you want to handle the redirection and session management yourself you can do so like this
+```tsx
+google.accounts.id.initialize({
+ callback: async response => {
+ const signInOrUp = await Clerk.authenticateWithGoogleOneTap({ token: response.credential})
+ if(signInOrUp.status === 'complete') {
+ await Clerk.setActive({
+ session: signInOrUp.createdSessionId
+ })
+ }
+ },
+});
+```
diff --git a/packages/chrome-extension/src/__tests__/__snapshots__/exports.test.ts.snap b/packages/chrome-extension/src/__tests__/__snapshots__/exports.test.ts.snap
index 07232140a1..5926a52cb7 100644
--- a/packages/chrome-extension/src/__tests__/__snapshots__/exports.test.ts.snap
+++ b/packages/chrome-extension/src/__tests__/__snapshots__/exports.test.ts.snap
@@ -7,6 +7,7 @@ exports[`public exports should not include a breaking change 1`] = `
"ClerkLoading",
"ClerkProvider",
"CreateOrganization",
+ "GoogleOneTap",
"OrganizationList",
"OrganizationProfile",
"OrganizationSwitcher",
@@ -26,7 +27,6 @@ exports[`public exports should not include a breaking change 1`] = `
"SignedOut",
"UserButton",
"UserProfile",
- "__experimental_GoogleOneTap",
"useAuth",
"useClerk",
"useEmailLink",
diff --git a/packages/clerk-js/src/core/clerk.ts b/packages/clerk-js/src/core/clerk.ts
index ecbe51f7a0..2982f17faf 100644
--- a/packages/clerk-js/src/core/clerk.ts
+++ b/packages/clerk-js/src/core/clerk.ts
@@ -16,8 +16,8 @@ import {
} from '@clerk/shared';
import { eventPrebuiltComponentMounted, TelemetryCollector } from '@clerk/shared/telemetry';
import type {
- __experimental_AuthenticateWithGoogleOneTapParams,
ActiveSessionResource,
+ AuthenticateWithGoogleOneTapParams,
AuthenticateWithMetamaskParams,
Clerk as ClerkInterface,
ClerkAPIError,
@@ -28,12 +28,12 @@ import type {
DomainOrProxyUrl,
EnvironmentJSON,
EnvironmentResource,
+ GoogleOneTapProps,
HandleEmailLinkVerificationParams,
HandleOAuthCallbackParams,
InstanceType,
ListenerCallback,
NavigateOptions,
- OneTapProps,
OrganizationListProps,
OrganizationProfileProps,
OrganizationResource,
@@ -330,14 +330,14 @@ export class Clerk implements ClerkInterface {
}
};
- public __experimental_openGoogleOneTap = (props?: OneTapProps): void => {
+ public openGoogleOneTap = (props?: GoogleOneTapProps): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls
- .ensureMounted({ preloadHint: 'OneTap' })
+ .ensureMounted({ preloadHint: 'GoogleOneTap' })
.then(controls => controls.openModal('googleOneTap', props || {}));
};
- public __experimental_closeGoogleOneTap = (): void => {
+ public closeGoogleOneTap = (): void => {
this.assertComponentsReady(this.#componentControls);
void this.#componentControls.ensureMounted().then(controls => controls.closeModal('googleOneTap'));
};
@@ -1003,7 +1003,7 @@ export class Clerk implements ClerkInterface {
return null;
};
- public __experimental_handleGoogleOneTapCallback = async (
+ public handleGoogleOneTapCallback = async (
signInOrUp: SignInResource | SignUpResource,
params: HandleOAuthCallbackParams,
customNavigate?: (to: string) => Promise,
@@ -1263,23 +1263,19 @@ export class Clerk implements ClerkInterface {
return this.setActive({ session: null });
};
- public __experimental_authenticateWithGoogleOneTap = async (
- params: __experimental_AuthenticateWithGoogleOneTapParams,
+ public authenticateWithGoogleOneTap = async (
+ params: AuthenticateWithGoogleOneTapParams,
): Promise => {
return this.client?.signIn
.create({
- // TODO-ONETAP: Add new types when feature is ready for public beta
- // @ts-expect-error
strategy: 'google_one_tap',
- googleOneTapToken: params.token,
+ token: params.token,
})
.catch(err => {
if (isClerkAPIResponseError(err) && err.errors[0].code === 'external_account_not_found') {
return this.client?.signUp.create({
- // TODO-ONETAP: Add new types when feature is ready for public beta
- // @ts-expect-error
strategy: 'google_one_tap',
- googleOneTapToken: params.token,
+ token: params.token,
});
}
throw err;
diff --git a/packages/clerk-js/src/core/resources/SignIn.ts b/packages/clerk-js/src/core/resources/SignIn.ts
index c989de0ac1..62d099bdfd 100644
--- a/packages/clerk-js/src/core/resources/SignIn.ts
+++ b/packages/clerk-js/src/core/resources/SignIn.ts
@@ -1,6 +1,5 @@
-import { deepSnakeToCamel, isClerkAPIResponseError, Poller } from '@clerk/shared';
+import { deepSnakeToCamel, Poller } from '@clerk/shared';
import type {
- __experimental_AuthenticateWithGoogleOneTapParams,
AttemptFirstFactorParams,
AttemptSecondFactorParams,
AuthenticateWithPasskeyParams,
@@ -26,7 +25,6 @@ import type {
SignInSecondFactor,
SignInStartEmailLinkFlowParams,
SignInStatus,
- SignUpResource,
VerificationResource,
Web3SignatureConfig,
Web3SignatureFactor,
@@ -225,27 +223,6 @@ export class SignIn extends BaseResource implements SignInResource {
}
};
- public __experimental_authenticateWithGoogleOneTap = async (
- params: __experimental_AuthenticateWithGoogleOneTapParams,
- ): Promise => {
- return this.create({
- // TODO-ONETAP: Add new types when feature is ready for public beta
- // @ts-expect-error
- strategy: 'google_one_tap',
- googleOneTapToken: params.token,
- }).catch(err => {
- if (isClerkAPIResponseError(err) && err.errors[0].code === 'external_account_not_found') {
- return SignIn.clerk.client?.signUp.create({
- // TODO-ONETAP: Add new types when feature is ready for public beta
- // @ts-expect-error
- strategy: 'google_one_tap',
- googleOneTapToken: params.token,
- });
- }
- throw err;
- }) as Promise;
- };
-
public authenticateWithWeb3 = async (params: AuthenticateWithWeb3Params): Promise => {
const { identifier, generateSignature } = params || {};
if (!(typeof generateSignature === 'function')) {
diff --git a/packages/clerk-js/src/ui/Components.tsx b/packages/clerk-js/src/ui/Components.tsx
index 15678e9de0..2b94fa63e5 100644
--- a/packages/clerk-js/src/ui/Components.tsx
+++ b/packages/clerk-js/src/ui/Components.tsx
@@ -6,7 +6,7 @@ import type {
ClerkOptions,
CreateOrganizationProps,
EnvironmentResource,
- OneTapProps,
+ GoogleOneTapProps,
OrganizationProfileProps,
SignInProps,
SignUpProps,
@@ -84,7 +84,7 @@ interface ComponentsProps {
interface ComponentsState {
appearance: Appearance | undefined;
options: ClerkOptions | undefined;
- googleOneTapModal: null | OneTapProps;
+ googleOneTapModal: null | GoogleOneTapProps;
signInModal: null | SignInProps;
signUpModal: null | SignUpProps;
userProfileModal: null | UserProfileProps;
diff --git a/packages/clerk-js/src/ui/components/GoogleOneTap/index.tsx b/packages/clerk-js/src/ui/components/GoogleOneTap/index.tsx
index 28c1756432..3a755535db 100644
--- a/packages/clerk-js/src/ui/components/GoogleOneTap/index.tsx
+++ b/packages/clerk-js/src/ui/components/GoogleOneTap/index.tsx
@@ -1,4 +1,4 @@
-import type { OneTapProps } from '@clerk/types';
+import type { GoogleOneTapProps } from '@clerk/types';
import React from 'react';
import { withCoreSessionSwitchGuard } from '../../contexts';
@@ -22,4 +22,4 @@ function OneTapRoutes(): JSX.Element {
OneTapRoutes.displayName = 'OneTap';
-export const OneTap: React.ComponentType = withCoreSessionSwitchGuard(OneTapRoutes);
+export const OneTap: React.ComponentType = withCoreSessionSwitchGuard(OneTapRoutes);
diff --git a/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx b/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx
index 715553d4ae..2217882187 100644
--- a/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx
+++ b/packages/clerk-js/src/ui/components/GoogleOneTap/one-tap-start.tsx
@@ -29,10 +29,10 @@ function _OneTapStart(): JSX.Element | null {
async function oneTapCallback(response: GISCredentialResponse) {
isPromptedRef.current = false;
try {
- const res = await clerk.__experimental_authenticateWithGoogleOneTap({
+ const res = await clerk.authenticateWithGoogleOneTap({
token: response.credential,
});
- await clerk.__experimental_handleGoogleOneTapCallback(
+ await clerk.handleGoogleOneTapCallback(
res,
{
signInUrl,
@@ -80,7 +80,7 @@ function _OneTapStart(): JSX.Element | null {
// Close the modal, when the user clicks outside the prompt or cancels
if (notification.getMomentType() === 'skipped') {
// Unmounts the component will cause the useEffect cleanup function from below to be called
- clerk.__experimental_closeGoogleOneTap();
+ clerk.closeGoogleOneTap();
}
});
isPromptedRef.current = true;
diff --git a/packages/clerk-js/src/ui/contexts/ClerkUIComponentsContext.tsx b/packages/clerk-js/src/ui/contexts/ClerkUIComponentsContext.tsx
index bf6f623383..fa0cc67619 100644
--- a/packages/clerk-js/src/ui/contexts/ClerkUIComponentsContext.tsx
+++ b/packages/clerk-js/src/ui/contexts/ClerkUIComponentsContext.tsx
@@ -14,7 +14,7 @@ import { useRouter } from '../router';
import type {
AvailableComponentCtx,
CreateOrganizationCtx,
- OneTapCtx,
+ GoogleOneTapCtx,
OrganizationListCtx,
OrganizationProfileCtx,
OrganizationSwitcherCtx,
@@ -497,12 +497,12 @@ export const useCreateOrganizationContext = () => {
};
export const useGoogleOneTapContext = () => {
- const { componentName, ...ctx } = (React.useContext(ComponentContext) || {}) as OneTapCtx;
+ const { componentName, ...ctx } = (React.useContext(ComponentContext) || {}) as GoogleOneTapCtx;
const options = useOptions();
const { displayConfig } = useEnvironment();
const { queryParams } = useRouter();
- if (componentName !== 'OneTap') {
+ if (componentName !== 'GoogleOneTap') {
throw new Error('Clerk: useGoogleOneTapContext called outside GoogleOneTap.');
}
diff --git a/packages/clerk-js/src/ui/lazyModules/components.ts b/packages/clerk-js/src/ui/lazyModules/components.ts
index ed3cf52935..5cac14588f 100644
--- a/packages/clerk-js/src/ui/lazyModules/components.ts
+++ b/packages/clerk-js/src/ui/lazyModules/components.ts
@@ -12,13 +12,15 @@ const componentImportPaths = {
import(/* webpackChunkName: "organizationswitcher" */ './../components/OrganizationSwitcher'),
OrganizationList: () => import(/* webpackChunkName: "organizationlist" */ './../components/OrganizationList'),
ImpersonationFab: () => import(/* webpackChunkName: "impersonationfab" */ './../components/ImpersonationFab'),
- OneTap: () => import(/* webpackChunkName: "oneTap" */ './../components/GoogleOneTap'),
+ GoogleOneTap: () => import(/* webpackChunkName: "oneTap" */ './../components/GoogleOneTap'),
} as const;
export const SignIn = lazy(() => componentImportPaths.SignIn().then(module => ({ default: module.SignIn })));
export const SignInModal = lazy(() => componentImportPaths.SignIn().then(module => ({ default: module.SignInModal })));
-export const OneTap = lazy(() => componentImportPaths.OneTap().then(module => ({ default: module.OneTap })));
+export const GoogleOneTap = lazy(() =>
+ componentImportPaths.GoogleOneTap().then(module => ({ default: module.OneTap })),
+);
export const SignUp = lazy(() => componentImportPaths.SignUp().then(module => ({ default: module.SignUp })));
@@ -79,7 +81,7 @@ export const ClerkComponents = {
UserProfileModal,
OrganizationProfileModal,
CreateOrganizationModal,
- OneTap,
+ GoogleOneTap,
};
export type ClerkComponentName = keyof typeof ClerkComponents;
diff --git a/packages/clerk-js/src/ui/lazyModules/providers.tsx b/packages/clerk-js/src/ui/lazyModules/providers.tsx
index df472b1930..e1f63635e5 100644
--- a/packages/clerk-js/src/ui/lazyModules/providers.tsx
+++ b/packages/clerk-js/src/ui/lazyModules/providers.tsx
@@ -146,9 +146,9 @@ export const LazyOneTapRenderer = (props: LazyOneTapRendererProps) => {
>
);
diff --git a/packages/clerk-js/src/ui/types.ts b/packages/clerk-js/src/ui/types.ts
index fa9ee82c3a..ce03e28c09 100644
--- a/packages/clerk-js/src/ui/types.ts
+++ b/packages/clerk-js/src/ui/types.ts
@@ -1,6 +1,6 @@
import type {
CreateOrganizationProps,
- OneTapProps,
+ GoogleOneTapProps,
OrganizationListProps,
OrganizationProfileProps,
OrganizationSwitcherProps,
@@ -11,7 +11,7 @@ import type {
} from '@clerk/types';
export type {
- OneTapProps,
+ GoogleOneTapProps,
SignInProps,
SignUpProps,
UserButtonProps,
@@ -74,8 +74,8 @@ export type OrganizationListCtx = OrganizationListProps & {
mode?: ComponentMode;
};
-export type OneTapCtx = OneTapProps & {
- componentName: 'OneTap';
+export type GoogleOneTapCtx = GoogleOneTapProps & {
+ componentName: 'GoogleOneTap';
};
export type AvailableComponentCtx =
@@ -87,4 +87,4 @@ export type AvailableComponentCtx =
| CreateOrganizationCtx
| OrganizationSwitcherCtx
| OrganizationListCtx
- | OneTapCtx;
+ | GoogleOneTapCtx;
diff --git a/packages/nextjs/src/client-boundary/uiComponents.tsx b/packages/nextjs/src/client-boundary/uiComponents.tsx
index d0451cdee0..50599e5df8 100644
--- a/packages/nextjs/src/client-boundary/uiComponents.tsx
+++ b/packages/nextjs/src/client-boundary/uiComponents.tsx
@@ -26,7 +26,7 @@ export {
SignOutButton,
SignUpButton,
UserButton,
- __experimental_GoogleOneTap,
+ GoogleOneTap,
} from '@clerk/clerk-react';
// The assignment of UserProfile with BaseUserProfile props is used
diff --git a/packages/nextjs/src/index.ts b/packages/nextjs/src/index.ts
index c921e52551..8a7e7513fe 100644
--- a/packages/nextjs/src/index.ts
+++ b/packages/nextjs/src/index.ts
@@ -30,7 +30,7 @@ export {
SignUpButton,
UserButton,
UserProfile,
- __experimental_GoogleOneTap,
+ GoogleOneTap,
} from './client-boundary/uiComponents';
/**
diff --git a/packages/react/src/components/index.ts b/packages/react/src/components/index.ts
index 64fde71b88..39b52fdda1 100644
--- a/packages/react/src/components/index.ts
+++ b/packages/react/src/components/index.ts
@@ -7,7 +7,7 @@ export {
OrganizationProfile,
CreateOrganization,
OrganizationList,
- __experimental_GoogleOneTap,
+ GoogleOneTap,
} from './uiComponents';
export {
diff --git a/packages/react/src/components/uiComponents.tsx b/packages/react/src/components/uiComponents.tsx
index 3ed6416700..f5c17e2866 100644
--- a/packages/react/src/components/uiComponents.tsx
+++ b/packages/react/src/components/uiComponents.tsx
@@ -2,7 +2,7 @@ import { logErrorInDevMode, without } from '@clerk/shared';
import { isDeeplyEqual } from '@clerk/shared/react';
import type {
CreateOrganizationProps,
- OneTapProps,
+ GoogleOneTapProps,
OrganizationListProps,
OrganizationProfileProps,
OrganizationSwitcherProps,
@@ -301,12 +301,12 @@ export const OrganizationList = withClerk(({ clerk, ...props }: WithClerkProp) => {
+export const GoogleOneTap = withClerk(({ clerk, ...props }: WithClerkProp) => {
return (
);
-}, 'OneTap');
+}, 'GoogleOneTap');
diff --git a/packages/react/src/isomorphicClerk.ts b/packages/react/src/isomorphicClerk.ts
index a56728226e..82e66cc491 100644
--- a/packages/react/src/isomorphicClerk.ts
+++ b/packages/react/src/isomorphicClerk.ts
@@ -3,18 +3,19 @@ import { handleValueOrFn } from '@clerk/shared/handleValueOrFn';
import type { TelemetryCollector } from '@clerk/shared/telemetry';
import type {
ActiveSessionResource,
+ AuthenticateWithGoogleOneTapParams,
AuthenticateWithMetamaskParams,
Clerk,
ClientResource,
CreateOrganizationParams,
CreateOrganizationProps,
DomainOrProxyUrl,
+ GoogleOneTapProps,
HandleEmailLinkVerificationParams,
HandleOAuthCallbackParams,
InstanceType,
ListenerCallback,
LoadedClerk,
- OneTapProps,
OrganizationListProps,
OrganizationProfileProps,
OrganizationResource,
@@ -24,11 +25,13 @@ import type {
SetActiveParams,
SignInProps,
SignInRedirectOptions,
+ SignInResource,
SignOut,
SignOutCallback,
SignOutOptions,
SignUpProps,
SignUpRedirectOptions,
+ SignUpResource,
UnsubscribeCallback,
UserButtonProps,
UserProfileProps,
@@ -83,8 +86,10 @@ type IsomorphicLoadedClerk = Without<
| 'buildAfterSignOutUrl'
| 'buildUrlWithAuth'
| 'handleRedirectCallback'
+ | 'handleGoogleOneTapCallback'
| 'handleUnauthenticated'
| 'authenticateWithMetamask'
+ | 'authenticateWithGoogleOneTap'
| 'createOrganization'
| 'getOrganization'
| 'mountUserButton'
@@ -99,9 +104,13 @@ type IsomorphicLoadedClerk = Without<
> & {
// TODO: Align return type and parms
handleRedirectCallback: (params: HandleOAuthCallbackParams) => void;
+ handleGoogleOneTapCallback: (signInOrUp: SignInResource | SignUpResource, params: HandleOAuthCallbackParams) => void;
handleUnauthenticated: () => void;
// TODO: Align Promise unknown
authenticateWithMetamask: (params: AuthenticateWithMetamaskParams) => Promise;
+ authenticateWithGoogleOneTap: (
+ params: AuthenticateWithGoogleOneTapParams,
+ ) => Promise;
// TODO: Align return type (maybe not possible or correct)
createOrganization: (params: CreateOrganizationParams) => Promise;
// TODO: Align return type (maybe not possible or correct)
@@ -140,7 +149,7 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
private readonly options: IsomorphicClerkOptions;
private readonly Clerk: ClerkProp;
private clerkjs: BrowserClerk | HeadlessBrowserClerk | null = null;
- private preopenOneTap?: null | OneTapProps = null;
+ private preopenOneTap?: null | GoogleOneTapProps = null;
private preopenSignIn?: null | SignInProps = null;
private preopenSignUp?: null | SignUpProps = null;
private preopenUserProfile?: null | UserProfileProps = null;
@@ -345,6 +354,15 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
}
};
+ #waitForClerkJS(): Promise {
+ return new Promise(resolve => {
+ if (this.#loaded) {
+ resolve(this.clerkjs!);
+ }
+ this.addOnLoaded(() => resolve(this.clerkjs!));
+ });
+ }
+
async loadClerkJS(): Promise {
if (this.mode !== 'browser' || this.#loaded) {
return;
@@ -462,7 +480,7 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
}
if (this.preopenOneTap !== null) {
- clerkjs.__experimental_openGoogleOneTap(this.preopenOneTap);
+ clerkjs.openGoogleOneTap(this.preopenOneTap);
}
if (this.preopenOrganizationProfile !== null) {
@@ -597,17 +615,17 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
}
};
- __experimental_openGoogleOneTap = (props?: OneTapProps): void => {
+ openGoogleOneTap = (props?: GoogleOneTapProps): void => {
if (this.clerkjs && this.#loaded) {
- this.clerkjs.__experimental_openGoogleOneTap(props);
+ this.clerkjs.openGoogleOneTap(props);
} else {
this.preopenOneTap = props;
}
};
- __experimental_closeGoogleOneTap = (): void => {
+ closeGoogleOneTap = (): void => {
if (this.clerkjs && this.#loaded) {
- this.clerkjs.__experimental_closeGoogleOneTap();
+ this.clerkjs.closeGoogleOneTap();
} else {
this.preopenOneTap = null;
}
@@ -929,6 +947,26 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
}
};
+ handleGoogleOneTapCallback = (
+ signInOrUp: SignInResource | SignUpResource,
+ params: HandleOAuthCallbackParams,
+ ): void => {
+ const callback = () => this.clerkjs?.handleGoogleOneTapCallback(signInOrUp, params);
+ if (this.clerkjs && this.#loaded) {
+ void callback()?.catch(() => {
+ // This error is caused when the host app is using React18
+ // and strictMode is enabled. This useEffects runs twice because
+ // the clerk-react ui components mounts, unmounts and mounts again
+ // so the clerk-js component loses its state because of the custom
+ // unmount callback we're using.
+ // This needs to be solved by tweaking the logic in uiComponents.tsx
+ // or by making handleRedirectCallback idempotent
+ });
+ } else {
+ this.premountMethodCalls.set('handleGoogleOneTapCallback', callback);
+ }
+ };
+
handleEmailLinkVerification = async (params: HandleEmailLinkVerificationParams): Promise => {
const callback = () => this.clerkjs?.handleEmailLinkVerification(params);
if (this.clerkjs && this.#loaded) {
@@ -947,6 +985,13 @@ export class IsomorphicClerk implements IsomorphicLoadedClerk {
}
};
+ authenticateWithGoogleOneTap = async (
+ params: AuthenticateWithGoogleOneTapParams,
+ ): Promise => {
+ const clerkjs = await this.#waitForClerkJS();
+ return clerkjs.authenticateWithGoogleOneTap(params);
+ };
+
createOrganization = async (params: CreateOrganizationParams): Promise => {
const callback = () => this.clerkjs?.createOrganization(params);
if (this.clerkjs && this.#loaded) {
diff --git a/packages/types/src/clerk.ts b/packages/types/src/clerk.ts
index 4d8ad598c6..5f43f9ccd2 100644
--- a/packages/types/src/clerk.ts
+++ b/packages/types/src/clerk.ts
@@ -140,17 +140,15 @@ export interface Clerk {
/**
* Opens the Google One Tap component.
- * @experimental
* @param props Optional props that will be passed to the GoogleOneTap component.
*/
- __experimental_openGoogleOneTap: (props?: OneTapProps) => void;
+ openGoogleOneTap: (props?: GoogleOneTapProps) => void;
/**
* Opens the Google One Tap component.
* If the component is not already open, results in a noop.
- * @experimental
*/
- __experimental_closeGoogleOneTap: () => void;
+ closeGoogleOneTap: () => void;
/**
* Opens the Clerk SignUp component in a modal.
@@ -442,10 +440,10 @@ export interface Clerk {
redirectToAfterSignOut: () => void;
/**
- * Completes an Google One Tap redirection flow started by
- * {@link Clerk.__experimental_authenticateWithGoogleOneTap}
+ * Completes a Google One Tap redirection flow started by
+ * {@link Clerk.authenticateWithGoogleOneTap}
*/
- __experimental_handleGoogleOneTapCallback: (
+ handleGoogleOneTapCallback: (
signInOrUp: SignInResource | SignUpResource,
params: HandleOAuthCallbackParams,
customNavigate?: (to: string) => Promise,
@@ -474,11 +472,10 @@ export interface Clerk {
authenticateWithMetamask: (params?: AuthenticateWithMetamaskParams) => Promise;
/**
- * @experimental
- * Authenticates user using a google token generated from google identity services.
+ * Authenticates user using a Google token generated from Google identity services.
*/
- __experimental_authenticateWithGoogleOneTap: (
- params: __experimental_AuthenticateWithGoogleOneTapParams,
+ authenticateWithGoogleOneTap: (
+ params: AuthenticateWithGoogleOneTapParams,
) => Promise;
/**
@@ -731,9 +728,9 @@ export type SignInProps = RoutingOptions & {
export type SignInModalProps = WithoutRouting;
-type OneTapRedirectUrlProps = SignInForceRedirectUrl & SignUpForceRedirectUrl;
+type GoogleOneTapRedirectUrlProps = SignInForceRedirectUrl & SignUpForceRedirectUrl;
-export type OneTapProps = OneTapRedirectUrlProps & {
+export type GoogleOneTapProps = GoogleOneTapRedirectUrlProps & {
/**
* Whether to cancel the Google One Tap request if a user clicks outside the prompt.
* @default true
@@ -1076,7 +1073,7 @@ export interface AuthenticateWithMetamaskParams {
unsafeMetadata?: SignUpUnsafeMetadata;
}
-export interface __experimental_AuthenticateWithGoogleOneTapParams {
+export interface AuthenticateWithGoogleOneTapParams {
token: string;
}
diff --git a/packages/types/src/signIn.ts b/packages/types/src/signIn.ts
index 52c203207b..9158bee4af 100644
--- a/packages/types/src/signIn.ts
+++ b/packages/types/src/signIn.ts
@@ -1,4 +1,3 @@
-import type { __experimental_AuthenticateWithGoogleOneTapParams } from './clerk';
import type {
BackupCodeAttempt,
BackupCodeFactor,
@@ -48,11 +47,11 @@ import type {
import type { ValidatePasswordCallbacks } from './passwords';
import type { AuthenticateWithRedirectParams } from './redirects';
import type { ClerkResource } from './resource';
-import type { SignUpResource } from './signUp';
import type {
BackupCodeStrategy,
EmailCodeStrategy,
EmailLinkStrategy,
+ GoogleOneTapStrategy,
OAuthStrategy,
PasskeyStrategy,
PasswordStrategy,
@@ -101,13 +100,6 @@ export interface SignInResource extends ClerkResource {
authenticateWithPasskey: (params?: AuthenticateWithPasskeyParams) => Promise;
- /**
- * @deprecated Use `Clerk.__experimental_authenticateWithGoogleOneTap`
- */
- __experimental_authenticateWithGoogleOneTap: (
- params: __experimental_AuthenticateWithGoogleOneTapParams,
- ) => Promise;
-
createEmailLinkFlow: () => CreateEmailLinkFlowReturn;
validatePassword: (password: string, callbacks?: ValidatePasswordCallbacks) => void;
@@ -184,6 +176,10 @@ export type SignInCreateParams = (
strategy: TicketStrategy;
ticket: string;
}
+ | {
+ strategy: GoogleOneTapStrategy;
+ token: string;
+ }
| {
strategy: PasswordStrategy;
password: string;
diff --git a/packages/types/src/signUp.ts b/packages/types/src/signUp.ts
index f833d2dd14..8dc35b8339 100644
--- a/packages/types/src/signUp.ts
+++ b/packages/types/src/signUp.ts
@@ -14,6 +14,7 @@ import type { ClerkResource } from './resource';
import type {
EmailCodeStrategy,
EmailLinkStrategy,
+ GoogleOneTapStrategy,
OAuthStrategy,
PhoneCodeStrategy,
SamlStrategy,
@@ -148,12 +149,13 @@ export type SignUpCreateParams = Partial<
externalAccountStrategy: string;
externalAccountRedirectUrl: string;
externalAccountActionCompleteRedirectUrl: string;
- strategy: OAuthStrategy | SamlStrategy | TicketStrategy;
+ strategy: OAuthStrategy | SamlStrategy | TicketStrategy | GoogleOneTapStrategy;
redirectUrl: string;
actionCompleteRedirectUrl: string;
transfer: boolean;
unsafeMetadata: SignUpUnsafeMetadata;
ticket: string;
+ token: string;
} & SnakeToCamel>
>;
diff --git a/packages/types/src/strategies.ts b/packages/types/src/strategies.ts
index 3d72e79dcb..ce2457dc61 100644
--- a/packages/types/src/strategies.ts
+++ b/packages/types/src/strategies.ts
@@ -1,6 +1,7 @@
import type { OAuthProvider } from './oauth';
import type { Web3Provider } from './web3';
+export type GoogleOneTapStrategy = 'google_one_tap';
export type PasskeyStrategy = 'passkey';
export type PasswordStrategy = 'password';
export type PhoneCodeStrategy = 'phone_code';