Skip to content

Commit

Permalink
Cache App Check debug token (#5055)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsubox76 committed Jun 29, 2021
1 parent 56a6a9d commit 5d31e21
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 185 deletions.
5 changes: 5 additions & 0 deletions .changeset/loud-lamps-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@firebase/app-check': patch
---

Fix an error causing App Check to log `HTTP status 429` errors in debug mode.
44 changes: 21 additions & 23 deletions packages/app-check/src/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
getFakeApp,
getFakeCustomTokenProvider,
getFakePlatformLoggingProvider,
getFakeGreCAPTCHA,
removegreCAPTCHAScriptsOnPage
} from '../test/util';
import { clearState, getState } from './state';
Expand All @@ -37,8 +38,12 @@ import * as internalApi from './internal-api';
import * as client from './client';
import * as storage from './storage';
import * as logger from './logger';
import * as util from './util';

describe('api', () => {
beforeEach(() => {
stub(util, 'getRecaptcha').returns(getFakeGreCAPTCHA());
});
describe('activate()', () => {
let app: FirebaseApp;

Expand Down Expand Up @@ -126,25 +131,29 @@ describe('api', () => {
});
});
describe('onTokenChanged()', () => {
const fakePlatformLoggingProvider = getFakePlatformLoggingProvider();
const fakeRecaptchaToken = 'fake-recaptcha-token';
const fakeRecaptchaAppCheckToken = {
token: 'fake-recaptcha-app-check-token',
expireTimeMillis: Date.now() + 60000,
issuedAtTimeMillis: 0
};

beforeEach(() => {
stub(storage, 'readTokenFromStorage').resolves(undefined);
stub(storage, 'writeTokenToStorage');
});
afterEach(() => {
clearState();
removegreCAPTCHAScriptsOnPage();
});
it('Listeners work when using top-level parameters pattern', async () => {
const app = getFakeApp({ automaticDataCollectionEnabled: true });
activate(app, FAKE_SITE_KEY, true);
const fakePlatformLoggingProvider = getFakePlatformLoggingProvider();
const fakeRecaptchaToken = 'fake-recaptcha-token';
const fakeRecaptchaAppCheckToken = {
token: 'fake-recaptcha-app-check-token',
expireTimeMillis: 123,
issuedAtTimeMillis: 0
};
const app = getFakeApp();
activate(app, FAKE_SITE_KEY, false);
stub(reCAPTCHA, 'getToken').returns(Promise.resolve(fakeRecaptchaToken));
stub(client, 'exchangeToken').returns(
Promise.resolve(fakeRecaptchaAppCheckToken)
);
stub(storage, 'writeTokenToStorage').returns(Promise.resolve(undefined));

const listener1 = (): void => {
throw new Error();
Expand Down Expand Up @@ -183,20 +192,12 @@ describe('api', () => {
});

it('Listeners work when using Observer pattern', async () => {
const app = getFakeApp({ automaticDataCollectionEnabled: true });
activate(app, FAKE_SITE_KEY, true);
const fakePlatformLoggingProvider = getFakePlatformLoggingProvider();
const fakeRecaptchaToken = 'fake-recaptcha-token';
const fakeRecaptchaAppCheckToken = {
token: 'fake-recaptcha-app-check-token',
expireTimeMillis: 123,
issuedAtTimeMillis: 0
};
const app = getFakeApp();
activate(app, FAKE_SITE_KEY, false);
stub(reCAPTCHA, 'getToken').returns(Promise.resolve(fakeRecaptchaToken));
stub(client, 'exchangeToken').returns(
Promise.resolve(fakeRecaptchaAppCheckToken)
);
stub(storage, 'writeTokenToStorage').returns(Promise.resolve(undefined));

const listener1 = (): void => {
throw new Error();
Expand Down Expand Up @@ -238,11 +239,8 @@ describe('api', () => {
stub(logger.logger, 'error');
const app = getFakeApp();
activate(app, FAKE_SITE_KEY, false);
const fakePlatformLoggingProvider = getFakePlatformLoggingProvider();
const fakeRecaptchaToken = 'fake-recaptcha-token';
stub(reCAPTCHA, 'getToken').returns(Promise.resolve(fakeRecaptchaToken));
stub(client, 'exchangeToken').rejects('exchange error');
stub(storage, 'writeTokenToStorage').returns(Promise.resolve(undefined));

const listener1 = spy();

Expand Down
4 changes: 3 additions & 1 deletion packages/app-check/src/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ describe('client', () => {
});

it('returns a AppCheck token', async () => {
useFakeTimers();
// To get a consistent expireTime/issuedAtTime.
const clock = useFakeTimers();
fetchStub.returns(
Promise.resolve({
status: 200,
Expand All @@ -77,6 +78,7 @@ describe('client', () => {
expireTimeMillis: 3600,
issuedAtTimeMillis: 0
});
clock.restore();
});

it('throws when there is a network error', async () => {
Expand Down
18 changes: 15 additions & 3 deletions packages/app-check/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,21 @@ import {
import { Provider } from '@firebase/component';
import { PartialObserver } from '@firebase/util';

import { FirebaseService } from '@firebase/app-types/private';
import { getState } from './state';

export function factory(
app: FirebaseApp,
platformLoggerProvider: Provider<'platform-logger'>
): FirebaseAppCheck {
): FirebaseAppCheck & FirebaseService {
return {
app,
activate: (
siteKeyOrProvider: string | AppCheckProvider,
isTokenAutoRefreshEnabled?: boolean
) => activate(app, siteKeyOrProvider, isTokenAutoRefreshEnabled),
setTokenAutoRefreshEnabled: (isTokenAutoRefreshEnabled: boolean) =>
setTokenAutoRefreshEnabled(app, isTokenAutoRefreshEnabled),

getToken: forceRefresh =>
getToken(app, platformLoggerProvider, forceRefresh),
onTokenChanged: (
Expand All @@ -68,7 +71,16 @@ export function factory(
onNextOrObserver as (tokenResult: AppCheckTokenResult) => void,
onError,
onCompletion
)
),
INTERNAL: {
delete: () => {
const { tokenObservers } = getState(app);
for (const tokenObserver of tokenObservers) {
removeTokenListener(app, tokenObserver.next);
}
return Promise.resolve();
}
}
};
}

Expand Down

0 comments on commit 5d31e21

Please sign in to comment.