diff --git a/packages/react/src/auth/index.ts b/packages/react/src/auth/index.ts
index 632083b7..7ae03693 100644
--- a/packages/react/src/auth/index.ts
+++ b/packages/react/src/auth/index.ts
@@ -15,7 +15,7 @@
// useCreateUserWithEmailAndPasswordMutation
// useFetchSignInMethodsForEmailQuery
// useGetRedirectResultQuery
-// useRevokeAccessTokenMutation
+export { useRevokeAccessTokenMutation } from "./useRevokeAccessTokenMutation";
// useSendPasswordResetEmailMutation
// useSendSignInLinkToEmailMutation
export { useSignInAnonymouslyMutation } from "./useSignInAnonymouslyMutation";
@@ -46,4 +46,3 @@ export { useSignInAnonymouslyMutation } from "./useSignInAnonymouslyMutation";
// useUpdatePasswordMutation
// useUpdateProfileMutation
// useVerifyBeforeUpdateEmailMutation
-
diff --git a/packages/react/src/auth/useRevokeAccessTokenMutation.test.tsx b/packages/react/src/auth/useRevokeAccessTokenMutation.test.tsx
new file mode 100644
index 00000000..aac3d1ea
--- /dev/null
+++ b/packages/react/src/auth/useRevokeAccessTokenMutation.test.tsx
@@ -0,0 +1,51 @@
+import React from "react";
+import { describe, expect, test, beforeEach, afterEach } from "vitest";
+import { renderHook, act, waitFor } from "@testing-library/react";
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { useRevokeAccessTokenMutation } from "./useRevokeAccessTokenMutation";
+import {
+ OAuthProvider,
+ signInWithPopup,
+ type UserCredential,
+} from "firebase/auth";
+import { auth, wipeAuth } from "~/testing-utils";
+
+const queryClient = new QueryClient({
+ defaultOptions: {
+ queries: { retry: false },
+ mutations: { retry: false },
+ },
+});
+
+const wrapper = ({ children }: { children: React.ReactNode }) => (
+ {children}
+);
+
+describe("useRevokeAccessTokenMutation", () => {
+ let userCredential: UserCredential;
+
+ beforeEach(async () => {
+ const provider = new OAuthProvider("apple.com");
+ userCredential = await signInWithPopup(auth, provider);
+ });
+
+ afterEach(async () => {
+ queryClient.clear();
+ await auth.signOut();
+ await wipeAuth();
+ });
+
+ test("successfully revokes access token", async () => {
+ const { result } = renderHook(() => useRevokeAccessTokenMutation(auth), {
+ wrapper,
+ });
+
+ const oauthAccessToken = await userCredential.user.getIdToken();
+
+ act(() => {
+ result.current.mutate({ token: oauthAccessToken });
+ });
+
+ await waitFor(() => expect(result.current.isSuccess).toBe(true));
+ });
+});
diff --git a/packages/react/src/auth/useRevokeAccessTokenMutation.ts b/packages/react/src/auth/useRevokeAccessTokenMutation.ts
new file mode 100644
index 00000000..bb466561
--- /dev/null
+++ b/packages/react/src/auth/useRevokeAccessTokenMutation.ts
@@ -0,0 +1,22 @@
+import { useMutation, type UseMutationOptions } from "@tanstack/react-query";
+import { type Auth, AuthError, revokeAccessToken } from "firebase/auth";
+
+type RevokeAccessTokenParams = {
+ token: string;
+};
+
+type AuthUseMutationOptions<
+ TData = unknown,
+ TError = Error,
+ TVariables = void
+> = Omit, "mutationFn">;
+
+export function useRevokeAccessTokenMutation(
+ auth: Auth,
+ options?: AuthUseMutationOptions
+) {
+ return useMutation({
+ ...options,
+ mutationFn: ({ token }) => revokeAccessToken(auth, token),
+ });
+}