react-native-firebase icon indicating copy to clipboard operation
react-native-firebase copied to clipboard

[📚] Documentation Issue - Revoke Access Token

Open victoriomolina opened this issue 5 months ago • 6 comments

URL: https://rnfirebase.io/auth/social-auth#apple

Problem

In the "Revoke token" section, the documentation references a revokeToken method, which no longer exists in the latest version of the library.

Instead, the current API exposes the following method:

/**
 * Revoke the given access token. Currently only supports Apple OAuth access tokens.
 * @param auth
 * @param token
 */
export declare function revokeAccessToken(auth: Auth, token: string): Promise<void>;

Suggested Fix

The docs should be updated to reflect the correct method name (revokeAccessToken).

import { getAuth, revokeAccessToken } from '@react-native-firebase/auth';
import { appleAuth } from '@invertase/react-native-apple-authentication';

async function revokeSignInWithAppleToken() {
  // Request a refresh (authorizationCode) from Apple
  const { authorizationCode } = await appleAuth.performRequest({
    requestedOperation: appleAuth.Operation.REFRESH,
  });

  if (!authorizationCode) {
    throw new Error('Apple revocation failed — no authorizationCode returned');
  }

  // Revoke the token
  return revokeAccessToken(getAuth(), authorizationCode);
}

victoriomolina avatar Sep 19 '25 06:09 victoriomolina

revokeToken is accessible using the declerative API.

The modular API (using revokeAccessToken) throws an error (only supported in Web).

This is my current implementation (working on iOS devices).

import {
  AppleAuthProvider as AppleProvider,
  signInWithCredential,
} from "@react-native-firebase/auth";
import {
  AppleAuthenticationScope,
  signInAsync as signInWithApple,
  refreshAsync,
} from "expo-apple-authentication";

...

/**
 * Authentication provider for Apple sign-in.
 */
class AppleAuthProvider extends BaseAuthProvider implements IRevokableAuthProvider {
  /**
   * The type of this authentication provider.
   */
  readonly type = ProviderType.APPLE;

  /**
   * Signs in the user using Apple authentication.
   *
   * @async
   * @returns {Promise<UserCredential>} Promise that resolves to the
   *   authenticated user's credentials.
   * @throws Apple sign-in failed.
   */
  async signIn(): Promise<UserCredential> {
    try {
      const nonce = await generateNonce();

      // Start the sign-in request
      const { identityToken } = await signInWithApple({
        requestedScopes: [
          AppleAuthenticationScope.EMAIL,
          AppleAuthenticationScope.FULL_NAME,
        ],
        nonce: nonce.hashed,
      });

      if (!identityToken) {
        throw new AuthError("No identify token returned");
      }

      // Create a Firebase credential from the response
      const appleCredential = AppleProvider.credential(identityToken, nonce.raw);

      return signInWithCredential(this.auth, appleCredential);
    } catch (err: unknown) {
      throw new AuthError(
        `Apple sign-in failed: ${(err as Error).message}`
      );
    }
  }

  /**
   * Permanently revokes the user's access token with Apple and Firebase.
   * After revocation, the user will need to re-authenticate completely.
   * 
   * This is useful for account deletion or when users want to fully disconnect
   * their Apple ID from the app.
   * 
   * @async
   * @returns {Promise<void>}
   * @throws Apple token revocation failed.
   */
  async revokeToken(): Promise<void> {
    try {
      const appleId = this._getAppleId();

      // Get an authorization code from Apple
      const { authorizationCode } = await refreshAsync({ user: appleId });

      // Ensure Apple returned an authorization code
      if (!authorizationCode) {
        throw new AuthError("No authorization code returned");
      }

      // Revoke the token
      return this.auth.revokeToken(authorizationCode);
    } catch (err: unknown) {
      throw new AuthError(
        `Apple revocation failed: ${(err as Error).message}`
      );
    }
  }

  /**
   * Extracts the Apple ID from the current user.
   *
   * @returns {string}
   * @throws No Apple ID found for the current user.
   */
  private _getAppleId(): string {
    const providers = this.auth.currentUser?.providerData;

    const appleProvider = providers?.find(
      ({ providerId }) => providerId === "apple.com"
    );

    const appleId = appleProvider?.uid;

    if (!appleId) {
      throw new AuthError("No Apple ID found for the current user");
    }

    return appleId;
  }
}

export default AppleAuthProvider;

victoriomolina avatar Sep 19 '25 15:09 victoriomolina

revokeToken and revokeAccessToken are both different methods. revokeToken (which is what you want and are using on the deprecated API accepts an authorization code whilst revokeAccessToken is web only and accepts the access token. Neither methods are implemented on the Modular API but will look into getting them setup.

MichaelVerdon avatar Sep 22 '25 13:09 MichaelVerdon

yep, docs are a little confusing regarding token revokation.

victoriomolina avatar Sep 25 '25 18:09 victoriomolina

yep, docs are a little confusing regarding token revokation.

Will make sure this is addressed upon the release of our newer docs page thanks for submitting this and here in the meantime.

MichaelVerdon avatar Sep 29 '25 07:09 MichaelVerdon

Hello 👋, to help manage issues we automatically close stale issues.

This issue has been automatically marked as stale because it has not had activity for quite some time.Has this issue been fixed, or does it still require attention?

This issue will be closed in 15 days if no further activity occurs.

Thank you for your contributions.

github-actions[bot] avatar Oct 27 '25 07:10 github-actions[bot]

Just checking if there's any traction on this. Running into issues making revokeToken work and came across this when trying to rule out any problems that weren't on my side. I saw that the related pull request has been pending for a while.

edyhu avatar Dec 03 '25 22:12 edyhu