Skip to content

Catch errors in debug token exchange logic #8792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tough-kiwis-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@firebase/app-check': patch
---

Fixed a bug that caused an error to be thrown when the debug exchange failed.
23 changes: 23 additions & 0 deletions packages/app-check/src/internal-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,29 @@ describe('internal api', () => {
errorStub.restore();
});

it('resolves with a dummy token and an error if failed to get a token in debug mode', async () => {
const errorStub = stub(console, 'error');
window.FIREBASE_APPCHECK_DEBUG_TOKEN = true;
const appCheck = initializeAppCheck(app, {
provider: new ReCaptchaV3Provider(FAKE_SITE_KEY)
});

const error = new Error('oops, something went wrong');
stub(client, 'exchangeToken').returns(Promise.reject(error));

const token = await getToken(appCheck as AppCheckService);

expect(token).to.deep.equal({
token: formatDummyToken(defaultTokenErrorData),
error
});
expect(errorStub.args[0][1].message).to.include(
'oops, something went wrong'
);
delete window.FIREBASE_APPCHECK_DEBUG_TOKEN;
errorStub.restore();
});

it('resolves with a dummy token and an error if recaptcha failed', async () => {
const errorStub = stub(console, 'error');
const appCheck = initializeAppCheck(app, {
Expand Down
46 changes: 29 additions & 17 deletions packages/app-check/src/internal-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,24 +116,36 @@ export async function getToken(
* Check token using the debug token, and return it directly.
*/
if (isDebugMode()) {
// Avoid making another call to the exchange endpoint if one is in flight.
if (!state.exchangeTokenPromise) {
state.exchangeTokenPromise = exchangeToken(
getExchangeDebugTokenRequest(app, await getDebugToken()),
appCheck.heartbeatServiceProvider
).finally(() => {
// Clear promise when settled - either resolved or rejected.
state.exchangeTokenPromise = undefined;
});
shouldCallListeners = true;
try {
// Avoid making another call to the exchange endpoint if one is in flight.
if (!state.exchangeTokenPromise) {
state.exchangeTokenPromise = exchangeToken(
getExchangeDebugTokenRequest(app, await getDebugToken()),
appCheck.heartbeatServiceProvider
).finally(() => {
// Clear promise when settled - either resolved or rejected.
state.exchangeTokenPromise = undefined;
});
shouldCallListeners = true;
}
const tokenFromDebugExchange: AppCheckTokenInternal =
await state.exchangeTokenPromise;
// Write debug token to indexedDB.
await writeTokenToStorage(app, tokenFromDebugExchange);
// Write debug token to state.
state.token = tokenFromDebugExchange;
return { token: tokenFromDebugExchange.token };
} catch (e) {
if ((e as FirebaseError).code === `appCheck/${AppCheckError.THROTTLED}`) {
// Warn if throttled, but do not treat it as an error.
logger.warn((e as FirebaseError).message);
} else {
// `getToken()` should never throw, but logging error text to console will aid debugging.
logger.error(e);
}
// Return dummy token and error
return makeDummyTokenResult(e as FirebaseError);
}
const tokenFromDebugExchange: AppCheckTokenInternal =
await state.exchangeTokenPromise;
// Write debug token to indexedDB.
await writeTokenToStorage(app, tokenFromDebugExchange);
// Write debug token to state.
state.token = tokenFromDebugExchange;
return { token: tokenFromDebugExchange.token };
}

/**
Expand Down
Loading