Skip to content

Commit f020821

Browse files
docs(app-check): explain App Check during server rendering (#3775)
* docs(app-check): explain App Check during server rendering The App Check guide said nothing about server-rendered apps. #3773 stops AngularFire from creating an App Check instance during server rendering, so the new section explains that inject(AppCheck) is null there, that Firebase requests made while rendering carry no App Check token, and how to opt back in with APP_CHECK_ON_SERVER. It also shows a browser-only config for 21.0.0-rc.1 and earlier, where the guide's setup fails with "document is not defined". * docs(app-check): use the dev-mode warning's wording in the SSR section The warning AngularFire prints during server rendering says it skips App Check there. The section now opens with the same words, so a reader arriving from the console finds them.
1 parent e11f0da commit f020821

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

‎docs/app-check.md‎

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,73 @@ export class AppCheckComponent {
4646
}
4747
```
4848

49+
## Server-side rendering
50+
51+
App Check's reCAPTCHA providers need a browser, so AngularFire skips App Check during server rendering. While a page renders on the server, AngularFire does not call the function you pass to `provideAppCheck`, and no App Check instance is created there. On the server, `inject(AppCheck)` returns `null`, although its type says `AppCheck`. Code that runs on both the server and the browser should check the platform before using it.
52+
53+
### Firebase requests made during server rendering
54+
55+
With no App Check instance on the server, requests to Firebase made while the server renders a page carry no App Check token. If you [enforce App Check](https://firebase.google.com/docs/app-check/enable-enforcement) for a Firebase product, those requests are rejected. Firebase's recommended fix is to hand a token from the browser to the server and pass it to `initializeServerApp` as `appCheckToken`, described in [Use App Check in SSR environments](https://firebase.google.com/docs/web/ssr-apps#use-app-check).
56+
57+
### Running App Check during server rendering
58+
59+
If your app runs App Check on the server on purpose, with a provider that works outside the browser such as a `CustomProvider` backed by the Firebase Admin SDK, provide `APP_CHECK_ON_SERVER` in the server-only config:
60+
61+
```ts
62+
// app.config.server.ts
63+
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
64+
import { provideServerRendering, withRoutes } from '@angular/ssr';
65+
import { APP_CHECK_ON_SERVER } from '@angular/fire/app-check';
66+
import { appConfig } from './app.config';
67+
import { serverRoutes } from './app.routes.server';
68+
69+
const serverConfig: ApplicationConfig = {
70+
providers: [
71+
provideServerRendering(withRoutes(serverRoutes)),
72+
{ provide: APP_CHECK_ON_SERVER, useValue: true },
73+
]
74+
};
75+
76+
export const config = mergeApplicationConfig(appConfig, serverConfig);
77+
```
78+
79+
The function passed to `provideAppCheck` then runs on the server too, so it has to choose a provider that works there.
80+
81+
### AngularFire 21.0.0-rc.1 and earlier
82+
83+
These releases run App Check during server rendering, so the setup in [Dependency Injection](#dependency-injection) fails with `ReferenceError: document is not defined`. Keep `provideAppCheck` out of the config the server uses by moving it into a config only the browser loads:
84+
85+
```ts
86+
// app.config.browser.ts
87+
import { ApplicationConfig, inject, mergeApplicationConfig } from '@angular/core';
88+
import { FirebaseApp } from '@angular/fire/app';
89+
import { provideAppCheck, initializeAppCheck, ReCaptchaV3Provider } from '@angular/fire/app-check';
90+
import { appConfig } from './app.config';
91+
92+
const browserConfig: ApplicationConfig = {
93+
providers: [
94+
provideAppCheck(() => initializeAppCheck(inject(FirebaseApp), {
95+
provider: new ReCaptchaV3Provider(/* configuration */),
96+
})),
97+
]
98+
};
99+
100+
export const config = mergeApplicationConfig(appConfig, browserConfig);
101+
```
102+
103+
Then bootstrap the browser with that config in `main.ts`:
104+
105+
```ts
106+
import { bootstrapApplication } from '@angular/platform-browser';
107+
import { config } from './app/app.config.browser';
108+
import { App } from './app/app';
109+
110+
bootstrapApplication(App, config)
111+
.catch((err) => console.error(err));
112+
```
113+
114+
The server then has no `AppCheck` provider at all, so inject it with `inject(AppCheck, { optional: true })`, which returns `null` on the server as later releases do.
115+
49116
## Firebase API
50117

51118
AngularFire wraps the Firebase JS SDK to ensure proper functionality in Angular, while providing the same API.

0 commit comments

Comments
 (0)